struct device {
struct device *parent;
struct device_private *p;
struct kobject kobj;
const char *init_name; /* initial name of the device */
struct device_type *type;
struct semaphore sem; /* semaphore to synchronize calls to
* its driver.
*/
struct bus_type *bus; /* type of bus device is on */
struct device_driver *driver; /* which driver has allocated this
device */
void *driver_data; /* data private to the driver */
void *platform_data; /* Platform specific data, device
core doesn't touch it */
struct dev_pm_info power;
#ifdef CONFIG_NUMA
int numa_node; /* NUMA node this device is close to */
#endif
u64 *dma_mask; /* dma mask (if dma'able device) */
u64 coherent_dma_mask;/* Like dma_mask, but for
alloc_coherent mappings as
not all hardware supports
64 bit addresses for consistent
allocations such descriptors. */
struct device_dma_parameters *dma_parms;
struct list_head dma_pools; /* dma pools (if dma'ble) */
struct dma_coherent_mem *dma_mem; /* internal for coherent mem
override */
/* arch specific additions */
struct dev_archdata archdata;
dev_t devt; /* dev_t, creates the sysfs "dev" */
spinlock_t devres_lock;
struct list_head devres_head;
struct klist_node knode_class;
struct class *class;
struct attribute_group **groups; /* optional groups */
void (*release)(struct device *dev);
};
struct platform_device {
const char * name;
int id;
struct device dev;
u32 num_resources;
struct resource * resource;
struct platform_device_id *id_entry;
};
struct platform_device cns3xxx_flash_device = {
.name = "cns3xxxflash",//设备名称,要与设备驱动名称一致
.id = 0,
.dev = {
.platform_data = &cns3xxx_flash_data,//设备特定数据
},
};
struct flash_platform_data {//该结构体只有ARM体系结构有定义
const char *map_name;
const char *name;
unsigned int width;
int (*init)(void);
void (*exit)(void);
void (*set_vpp)(int on);
void (*mmcontrol)(struct mtd_info *mtd, int sync_read);
struct mtd_partition *parts;
unsigned int nr_parts;
};
static struct flash_platform_data cns3xxx_flash_data = {
.map_name = "cfi_probe",//cfi 类型flash
.width = 2,//16位宽
.init = cns3xxx_flash_init,
.exit = cns3xxx_flash_exit,
.set_vpp = cns3xxx_flash_set_vpp,
};
static int cns3xxx_flash_init(void)
{
return 0;
}
static void cns3xxx_flash_exit(void)
{
}
static void cns3xxx_flash_set_vpp(int on)
{
}
int cns3xxx_flash_register(struct resource *res, u32 num)//特定的flash资源注册函数
{
cns3xxx_flash_device.resource = res;
cns3xxx_flash_device.num_resources = num;
return platform_device_register(&cns3xxx_flash_device);//注册flash设备
}
/*
* Cavium Networks ARM11 MPCore platform devices
*/
static struct resource cns3xxx_flash_resource[] = {
[0] = {
.start = CNS3XXX_FLASH0_BASE,
.end = CNS3XXX_FLASH0_BASE + CNS3XXX_FLASH0_SIZE - 1,
.flags = IORESOURCE_MEM,
}, /*
[1] = {
.start = CNS3XXX_FLASH1_BASE,
.end = CNS3XXX_FLASH1_BASE + CNS3XXX_FLASH1_SIZE - 1,
.flags = IORESOURCE_MEM,
}, */
};
#define CNS3XXX_FLASH0_BASE 0x10000000 /* Flash/SRAM Memory Bank 0 */
#ifdef CONFIG_SILICON
#define CNS3XXX_FLASH0_SIZE SZ_128M
#else
#define CNS3XXX_FLASH0_SIZE SZ_8M
#endif
static void __init cns3xxx_init(void)
{
int i;
#ifdef CONFIG_CACHE_L2X0
/* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
* Bits: .... ...0 0111 1001 0000 .... .... .... */
l2x0_init((void __iomem *) CNS3XXX_TC11MP_L220_BASE_VIRT, 0x00790000, 0xfe000fff);
#endif
#ifdef CONFIG_CACHE_L2CC
l2cc_init((void __iomem *) CNS3XXX_L2C_BASE_VIRT);
#endif
#ifdef CONFIG_CNS3XXX_DMAC
dmac_init();
#endif
#ifdef CONFIG_CNS3XXX_RAID
cns_rdma_init();
#endif
Normal
0
7.8 磅
0
2
false
false
false
EN-US
ZH-CN
X-NONE
MicrosoftInternetExplorer4
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:普通表格;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.5pt;
mso-bidi-font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;
mso-font-kerning:1.0pt;}
cns3xxx_flash_register(cns3xxx_flash_resource,
ARRAY_SIZE(cns3xxx_flash_resource));//此时注册FLASH资源
platform_add_devices(cns3xxx_devs, ARRAY_SIZE(cns3xxx_devs));
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
struct amba_device *d = amba_devs[i];
int ret;
cns3xxx_pwr_power_up(CNS3XXX_PWR_PLL(PLL_LCD));
cns3xxx_pwr_clk_en(CNS3XXX_PWR_CLK_EN(LCDC));
cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(LCDC));
ret = amba_device_register(d, &iomem_resource);
if(ret)
printk("%s=>%d: %d\n", __FUNCTION__, __LINE__, ret);
}
lm_device_register(&cns3xxx_usb_otg_device);
i2c_register_board_info(0, cns3xxx_i2c_devices, ARRAY_SIZE(cns3xxx_i2c_devices));
i2c_register_board_info(1, cns3xxx_i2c_gpio_devices, ARRAY_SIZE(cns3xxx_i2c_gpio_devices));
spi_register_board_info(cns3xxx_spi_devices, ARRAY_SIZE(cns3xxx_spi_devices));
cns3xxx_proc_dir = proc_mkdir("cns3xxx", NULL);
#ifdef CONFIG_DEBUG_FS
cns3xxx_debugfs_dir = debugfs_create_dir("cns3xxx", NULL);
#endif
#ifdef CONFIG_CACHE_L2CC
l2cc_proc_init();
#endif
pm_power_off = cns3xxx_power_off;
}
//FLASH驱动结构
static struct platform_driver cns3xxxflash_driver = {
.probe = cns3xxxflash_probe,//初始化函数
.remove = cns3xxxflash_remove,
.driver = {
.name = "cns3xxxflash",//设备驱动名称,与上面设备名称一致
.owner = THIS_MODULE,
},
};
static int cns3xxxflash_probe(struct platform_device *dev)
{
struct flash_platform_data *plat = dev->dev.platform_data;
struct resource *res = dev->resource;
unsigned int size = res->end - res->start + 1;
struct cns3xxxflash_info *info;
int err;
void __iomem *base;
struct mtd_partition *parts;
int nb_parts = 0;
int parsed_nr_parts = 0;
parts = cns3xxx_flash_partitions;//分区表
nb_parts = ARRAY_SIZE(cns3xxx_flash_partitions);//分区数目
//分配一个驱动自定义结构
info = kzalloc(sizeof(struct cns3xxxflash_info), GFP_KERNEL);
if (!info) {
err = -ENOMEM;
goto out;
}
info->plat = plat;
if (plat && plat->init) {//此时调用的其实是cns3xxx_flash_init,它不做任何事情
err = plat->init();
if (err)
goto no_resource;
}
info->res = request_mem_region(res->start, size, "flash");//登记内存资源使用情况
if (!info->res) {
err = -EBUSY;
goto no_resource;
}
base = ioremap(res->start, size);//把物理地址映射到内核讯地址,方便内核进行访问
if (!base) {
err = -ENOMEM;
goto no_mem;
}
/*
* look for CFI based flash parts fitted to this board//cfi 相关初始化
*/
info->map.size = size;
info->map.bankwidth = plat->width;
info->map.phys = res->start;
info->map.virt = base;
info->map.name = "cns3xxxflash";
simple_map_init(&info->map);//对MAP进行进一步初始化
/*
* Also, the CFI layer automatically works out what size
* of chips we have, and does the necessary identification
* for us automatically.
*/
info->mtd = do_map_probe(plat->map_name, &info->map);//进行flash驱动的自n动探测,因//map_name为"cfi_probe",所以其实调用了cfi驱动模块进行处理
if (!info->mtd) {
err = -ENXIO;
goto no_device;
}
info->mtd->owner = THIS_MODULE;
if (parsed_nr_parts > 0) {//条件为假
parts = parsed_parts;
nb_parts = parsed_nr_parts;
}
if (nb_parts == 0) {
printk(KERN_NOTICE "CNS3XXX NOR flash: No partition info available \n");
if (add_mtd_device(info->mtd))
return -ENXIO;
} else {
printk(KERN_NOTICE "CNS3XXX NOR flash: Using static partition definition\n");
return add_mtd_partitions(info->mtd, parts, nb_parts);//增加mtd分区信息
}
platform_set_drvdata(dev, info);
err = parse_mtd_partitions(info->mtd, probes, &info->parts, 0);
if (err > 0) {
err = add_mtd_partitions(info->mtd, info->parts, err);
if (err)
printk(KERN_ERR
"mtd partition registration failed: %d\n", err);
}
if (err == 0)
platform_set_drvdata(dev, info);
/*
* If we got an error, free all resources.
*/
if (err < 0) {
if (info->mtd) {
del_mtd_partitions(info->mtd);
map_destroy(info->mtd);
}
kfree(info->parts);
no_device:
iounmap(base);
no_mem:
release_mem_region(res->start, size);
no_resource:
if (plat && plat->exit)
plat->exit();
kfree(info);
}
out:
return err;
}
struct cns3xxxflash_info {//驱动特定结构
struct flash_platform_data *plat;
struct resource *res;//指向资源信息
struct mtd_partition *parts;//分区信息
struct mtd_info *mtd;//mtd信息
struct map_info map;//map信息
};
//对FLASH的位宽进行合法性判断
#define simple_map_init(map) BUG_ON(!map_bankwidth_supported((map)->bankwidth))
static inline int map_bankwidth_supported(int w)
{
switch (w) {
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
case 1:
#endif
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
case 2:
#endif
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
case 4:
#endif
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
case 8:
#endif
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_16
case 16:
#endif
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
case 32:
#endif
return 1;
default:
return 0;
}
}
static int cns3xxxflash_remove(struct platform_device *dev)
{
struct cns3xxxflash_info *info = platform_get_drvdata(dev);
platform_set_drvdata(dev, NULL);
if (info) {
if (info->mtd) {
del_mtd_partitions(info->mtd);//删除分区
map_destroy(info->mtd);//销毁mtd设备
}
kfree(info->parts);
iounmap(info->map.virt);
release_resource(info->res);
kfree(info->res);
if (info->plat && info->plat->exit)
info->plat->exit();
kfree(info);
}
return 0;
}