cregit-Linux how code gets into the kernel

Release 4.11 drivers/mtd/maps/intel_vr_nor.c

Directory: drivers/mtd/maps
/*
 * drivers/mtd/maps/intel_vr_nor.c
 *
 * An MTD map driver for a NOR flash bank on the Expansion Bus of the Intel
 * Vermilion Range chipset.
 *
 * The Vermilion Range Expansion Bus supports four chip selects, each of which
 * has 64MiB of address space.  The 2nd BAR of the Expansion Bus PCI Device
 * is a 256MiB memory region containing the address spaces for all four of the
 * chip selects, with start addresses hardcoded on 64MiB boundaries.
 *
 * This map driver only supports NOR flash on chip select 0.  The buswidth
 * (either 8 bits or 16 bits) is determined by reading the Expansion Bus Timing
 * and Control Register for Chip Select 0 (EXP_TIMING_CS0).  This driver does
 * not modify the value in the EXP_TIMING_CS0 register except to enable writing
 * and disable boot acceleration.  The timing parameters in the register are
 * assumed to have been properly initialized by the BIOS.  The reset default
 * timing parameters are maximally conservative (slow), so access to the flash
 * will be slower than it should be if the BIOS has not initialized the timing
 * parameters.
 *
 * Author: Andy Lowe <alowe@mvista.com>
 *
 * 2006 (c) MontaVista Software, Inc. This file is licensed under
 * the terms of the GNU General Public License version 2. This program
 * is licensed "as is" without any warranty of any kind, whether express
 * or implied.
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/cfi.h>
#include <linux/mtd/flashchip.h>


#define DRV_NAME "vr_nor"


struct vr_nor_mtd {
	
void __iomem *csr_base;
	
struct map_info map;
	
struct mtd_info *info;
	
struct pci_dev *dev;
};

/* Expansion Bus Configuration and Status Registers are in BAR 0 */

#define EXP_CSR_MBAR 0
/* Expansion Bus Memory Window is BAR 1 */

#define EXP_WIN_MBAR 1
/* Maximum address space for Chip Select 0 is 64MiB */

#define CS0_SIZE 0x04000000
/* Chip Select 0 is at offset 0 in the Memory Window */

#define CS0_START 0x0
/* Chip Select 0 Timing Register is at offset 0 in CSR */

#define EXP_TIMING_CS0 0x00

#define TIMING_CS_EN		(1 << 31)	
/* Chip Select Enable */

#define TIMING_BOOT_ACCEL_DIS	(1 <<  8)	
/* Boot Acceleration Disable */

#define TIMING_WR_EN		(1 <<  1)	
/* Write Enable */

#define TIMING_BYTE_EN		(1 <<  0)	
/* 8-bit vs 16-bit bus */

#define TIMING_MASK		0x3FFF0000


static void vr_nor_destroy_partitions(struct vr_nor_mtd *p) { mtd_device_unregister(p->info); }

Contributors

PersonTokensPropCommitsCommitProp
David Woodhouse1794.44%150.00%
Jamie Iles15.56%150.00%
Total18100.00%2100.00%


static int vr_nor_init_partitions(struct vr_nor_mtd *p) { /* register the flash bank */ /* partition the flash bank */ return mtd_device_parse_register(p->info, NULL, NULL, NULL, 0); }

Contributors

PersonTokensPropCommitsCommitProp
David Woodhouse2379.31%125.00%
Dmitry Baryshkov517.24%250.00%
Artem B. Bityutskiy13.45%125.00%
Total29100.00%4100.00%


static void vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p) { map_destroy(p->info); }

Contributors

PersonTokensPropCommitsCommitProp
David Woodhouse18100.00%1100.00%
Total18100.00%1100.00%


static int vr_nor_mtd_setup(struct vr_nor_mtd *p) { static const char * const probe_types[] = { "cfi_probe", "jedec_probe", NULL }; const char * const *type; for (type = probe_types; !p->info && *type; type++) p->info = do_map_probe(*type, &p->map); if (!p->info) return -ENODEV; p->info->dev.parent = &p->dev->dev; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
David Woodhouse8488.42%133.33%
Frans Klaver99.47%133.33%
Artem B. Bityutskiy22.11%133.33%
Total95100.00%3100.00%


static void vr_nor_destroy_maps(struct vr_nor_mtd *p) { unsigned int exp_timing_cs0; /* write-protect the flash bank */ exp_timing_cs0 = readl(p->csr_base + EXP_TIMING_CS0); exp_timing_cs0 &= ~TIMING_WR_EN; writel(exp_timing_cs0, p->csr_base + EXP_TIMING_CS0); /* unmap the flash window */ iounmap(p->map.virt); /* unmap the csr window */ iounmap(p->csr_base); }

Contributors

PersonTokensPropCommitsCommitProp
David Woodhouse61100.00%1100.00%
Total61100.00%1100.00%

/* * Initialize the map_info structure and map the flash. * Returns 0 on success, nonzero otherwise. */
static int vr_nor_init_maps(struct vr_nor_mtd *p) { unsigned long csr_phys, csr_len; unsigned long win_phys, win_len; unsigned int exp_timing_cs0; int err; csr_phys = pci_resource_start(p->dev, EXP_CSR_MBAR); csr_len = pci_resource_len(p->dev, EXP_CSR_MBAR); win_phys = pci_resource_start(p->dev, EXP_WIN_MBAR); win_len = pci_resource_len(p->dev, EXP_WIN_MBAR); if (!csr_phys || !csr_len || !win_phys || !win_len) return -ENODEV; if (win_len < (CS0_START + CS0_SIZE)) return -ENXIO; p->csr_base = ioremap_nocache(csr_phys, csr_len); if (!p->csr_base) return -ENOMEM; exp_timing_cs0 = readl(p->csr_base + EXP_TIMING_CS0); if (!(exp_timing_cs0 & TIMING_CS_EN)) { dev_warn(&p->dev->dev, "Expansion Bus Chip Select 0 " "is disabled.\n"); err = -ENODEV; goto release; } if ((exp_timing_cs0 & TIMING_MASK) == TIMING_MASK) { dev_warn(&p->dev->dev, "Expansion Bus Chip Select 0 " "is configured for maximally slow access times.\n"); } p->map.name = DRV_NAME; p->map.bankwidth = (exp_timing_cs0 & TIMING_BYTE_EN) ? 1 : 2; p->map.phys = win_phys + CS0_START; p->map.size = CS0_SIZE; p->map.virt = ioremap_nocache(p->map.phys, p->map.size); if (!p->map.virt) { err = -ENOMEM; goto release; } simple_map_init(&p->map); /* Enable writes to flash bank */ exp_timing_cs0 |= TIMING_BOOT_ACCEL_DIS | TIMING_WR_EN; writel(exp_timing_cs0, p->csr_base + EXP_TIMING_CS0); return 0; release: iounmap(p->csr_base); return err; }

Contributors

PersonTokensPropCommitsCommitProp
David Woodhouse319100.00%1100.00%
Total319100.00%1100.00%

static struct pci_device_id vr_nor_pci_ids[] = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x500D)}, {0,} };
static void vr_nor_pci_remove(struct pci_dev *dev) { struct vr_nor_mtd *p = pci_get_drvdata(dev); vr_nor_destroy_partitions(p); vr_nor_destroy_mtd_setup(p); vr_nor_destroy_maps(p); kfree(p); pci_release_regions(dev); pci_disable_device(dev); }

Contributors

PersonTokensPropCommitsCommitProp
David Woodhouse51100.00%1100.00%
Total51100.00%1100.00%


static int vr_nor_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct vr_nor_mtd *p = NULL; unsigned int exp_timing_cs0; int err; err = pci_enable_device(dev); if (err) goto out; err = pci_request_regions(dev, DRV_NAME); if (err) goto disable_dev; p = kzalloc(sizeof(*p), GFP_KERNEL); err = -ENOMEM; if (!p) goto release; p->dev = dev; err = vr_nor_init_maps(p); if (err) goto release; err = vr_nor_mtd_setup(p); if (err) goto destroy_maps; err = vr_nor_init_partitions(p); if (err) goto destroy_mtd_setup; pci_set_drvdata(dev, p); return 0; destroy_mtd_setup: map_destroy(p->info); destroy_maps: /* write-protect the flash bank */ exp_timing_cs0 = readl(p->csr_base + EXP_TIMING_CS0); exp_timing_cs0 &= ~TIMING_WR_EN; writel(exp_timing_cs0, p->csr_base + EXP_TIMING_CS0); /* unmap the flash window */ iounmap(p->map.virt); /* unmap the csr window */ iounmap(p->csr_base); release: kfree(p); pci_release_regions(dev); disable_dev: pci_disable_device(dev); out: return err; }

Contributors

PersonTokensPropCommitsCommitProp
David Woodhouse226100.00%1100.00%
Total226100.00%1100.00%

static struct pci_driver vr_nor_pci_driver = { .name = DRV_NAME, .probe = vr_nor_pci_probe, .remove = vr_nor_pci_remove, .id_table = vr_nor_pci_ids, }; module_pci_driver(vr_nor_pci_driver); MODULE_AUTHOR("Andy Lowe"); MODULE_DESCRIPTION("MTD map driver for NOR flash on Intel Vermilion Range"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, vr_nor_pci_ids);

Overall Contributors

PersonTokensPropCommitsCommitProp
David Woodhouse97597.70%111.11%
Frans Klaver90.90%111.11%
Dmitry Baryshkov50.50%222.22%
Artem B. Bityutskiy30.30%222.22%
Tejun Heo30.30%111.11%
Axel Lin20.20%111.11%
Jamie Iles10.10%111.11%
Greg Kroah-Hartman0.00%00.00%
Total998100.00%9100.00%
Directory: drivers/mtd/maps
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.