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,
}, */
#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
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);
#ifdef CONFIG_CACHE_L2CC
l2cc_init((void __iomem *) CNS3XXX_L2C_BASE_VIRT);
#ifdef CONFIG_CNS3XXX_DMAC
dmac_init();
#ifdef CONFIG_CNS3XXX_RAID
cns_rdma_init();
Normal
7.8 磅
2
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 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);
l2cc_proc_init();
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;
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) {
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);
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 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:
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
case 2:
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_4
case 4:
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
case 8:
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_16
case 16:
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
case 32:
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裝置
iounmap(info->map.virt);
release_resource(info->res);
kfree(info->res);
if (info->plat && info->plat->exit)
info->plat->exit();