系統平台: ARMv4

kernel 版本: 2.6.21

 

前家公司的嵌入式產品系統架構沒有很大,所以不需要很大容量的flash;
又該SOC上面沒有NOR or NAND flash的controller,所以只能使用SPI Flash
做為存放zImage以及相關DATA之用。


最早的時候是公司其他同仁利用字元驅動+IOCTL的方式來讀寫SPI Flash,
後來想要能夠套用本來Linux就有的MTD架構,於是乎就抱持著研究的精神
來研究一下相關的東西XD。


那時候google出來有用的訊息不太多,後來偶然發現新一點的kernel 2.6.28裡面
有一個支援 SPI flash 的驅動程式 m25p80.c,於是乎我就把它搬進來2.6.21,
然後再做了一點小修改,如此一來就支援 Linux 本來用來讀取flash的MTD架構,
更白話的說就是可以支援MTD partition切割以及利用mtd-utils等工具來讀寫flash了。


下圖是整個的架構圖,可以看到user-space發出讀寫命令開始,整個架構會牽扯到
MTD跟SPI兩大模組,MTD core 與SPI core 方面kernel 已經幫我們準備好了,
我們要做的就是修改/新增m25p80.c 與SOC上面的SPI controller 驅動程式。

1336666668-1140745386

  


我們主要的修改如下:


A.在 m25p80.c上面新增flash的支援到m25p_data 這個結構陣列中,他的結構原型如下:


struct flash_info {
    char        *name;

    /* JEDEC id zero means "no ID" (most older chips); otherwise it has
     * a high byte of zero plus three data bytes: the manufacturer id,
     * then a two byte device id.
     */
    u32        jedec_id;
    u16        ext_id;

    /* The size listed here is what works with OPCODE_SE, which isn't
     * necessarily called a "sector" by the vendor.
     */
    unsigned sector_size;
    u16        n_sectors;

    u16        flags;
#define    SECT_4K        0x01        /* OPCODE_BE_4K works uniformly */
};


所以請參閱你的spi flash規格書填入對應的數據 以winbond的SPI flash w25q64為例,我們會填入:
{ "w25q64" , 0xef4017, 0, 64 * 1024, 128, }, 我們把name取作 w25q64,JEDEC_ID是 0xef4017,
後面則是flash相關的資訊

B.接下來要在適當的地方註冊spi_board_info與MTD_Partition等資訊,請先看另外三個結構:
In kernel_Src/include/linux/spi/spi.h
struct spi_board_info {

    char        modalias[KOBJ_NAME_LEN];
    const void    *platform_data;
    void        *controller_data;
    int        irq;

    u32        max_speed_hz;

    u16        bus_num;
    u16        chip_select;

    u8        mode;

};


In kernel_src/include/linux/mtd/partitions.h
struct mtd_partition {
    char *name;            /* identifier string */
    u_int32_t size;            /* partition size */
    u_int32_t offset;        /* offset within the master MTD space */
    u_int32_t mask_flags;        /* master MTD flags to mask out for this partition */
    struct nand_ecclayout *ecclayout;    /* out of band layout for this partition (NAND only)*/
    struct mtd_info **mtdp;        /* pointer to store the MTD object */
};

In kernel_src/include/linux/spi/flash.h:
struct flash_platform_data {
    char        *name;
    struct mtd_partition *parts;
    unsigned int    nr_parts;

    char        *type;

    /* we'll likely add more ... use JEDEC IDs, etc */
};


spi_board_info需要指定你要控制的spi slave資訊; flash_platform_data要指定你flash的name、type與mtd_partition的資訊 ,
所以我們可以填入以下資料(注意spi_board_info的modalias欄位需要把值設為m25p80):
static struct spi_board_info my_spi_board[] = { //Need to modify ,some fields NULL!
  [0] = { 
    .modalias = "m25p80", 
    .platform_data = &spi_flashdata,         
    .chip_select = 0,                  
    .max_speed_hz = 500*1000, 
  }, 
}; 
 
static struct mtd_partition partition_info[] = {
    {
        .name    = "Boot Strap",
        .offset  =  0x0,
        .size    =  0x100000,
    },
    {
        .name    = "ARM-BOOT",
        .offset  = 0x100000,
        .size    = 0x100000,
    },
    {
        .name    = "zImage",
        .offset  = 0x200000,
        .size    = 0x600000,
    },
    {
       .name     = "Jffs2 Partition",
       .offset   = 0x800000,
       .size     = 0x200000,
    },
    
};
static struct flash_platform_data spi_flashdata = { 

  .name="w25q64",
  .type="w25q64",
  .parts=partition_info,
  .nr_parts=ARRAY_SIZE(partition_info),
}; 


填完了以上資料,我們呼叫以下函式好將資料註冊到kernel 內部
 spi_register_board_info(my_spi_board,1);

至於何時呼叫spi_register_board_info,你可以參考你SOC上的例子, 一般來說類似的資訊都集中在以下資料夾:
kernel_Src/arch/arm/mach-xxxx/ (xxxx是你的SOC名稱)

可以看到我們把spi_flashdata結構的type欄位設為w25q64, m25p80模組會在probe的時候搜尋m25p_data[]裡面
是否有 name為w25q64的元素,一但找到後會透過SPI去讀取SPI flash的 JEDEC_ID然後比對,一致之後m25p80會
繼續帶入你註冊的 MTD_Partition資訊,如此一來就可以使用MTD來分割flash了。 至於SPI controller,你可以參考
spi_s3c24xx.c依樣畫葫蘆即可。

NOTE: m25p80.c is in Kernel_Source/drivers/mtd/devices/m25p80.c
NOTE: spi_s3c24xx.c.c is in
Kernel_Source/drivers/spi/spi_s3c24xx.c
NOTE: 當然了,config kernel 的時候相關的SPI 與MTD設定都要打開。

 

arrow
arrow
    創作者介紹
    創作者 giros 的頭像
    giros

    亂走亂拍

    giros 發表在 痞客邦 留言(0) 人氣()