天天看點

flash驅動分析

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();

繼續閱讀