20180205_jeffrey - silenceuncrio/diary GitHub Wiki
review
針對 build_dir\target-mipsel_24kec+dsp_uClibc-0.9.33.2\linux-ramips_mt7621\linux-3.10.14\drivers\mtd
source code 來追一下 MTD 的 init
定義 {{drivers_mtd}} = build_dir\target-mipsel_24kec+dsp_uClibc-0.9.33.2\linux-ramips_mt7621\linux-3.10.14\drivers\mtd
試著從下面的開機訊息來追流程
[ 2.264000] MediaTek Nand driver init, version v2.1 Fix AHB virt2phys error
[ 2.280000] Allocate 16 byte aligned buffer: 804c2450
[ 2.288000] Enable NFI Clock
[ 2.292000] # MTK NAND # : Use HW ECC
[ 2.300000] NAND ID [C2 DA 90 95 06, 00909506]
[ 2.284000] # MTK NAND # : Use HW ECC
[ 2.292000] NAND ID [C2 DA 90 95 06, 00909506]
[ 2.300000] Device found in MTK table, ID: c2da, EXT_ID: 909506
[ 2.312000] Support this Device in MTK table! c2da
[ 2.324000] NAND device: Manufacturer ID: 0xc2, Chip ID: 0xda (Macronix NAND 256MiB 3,3V 8-bit), 256MiB, page size: 2048, OOB size: 64
[ 2.348000] [NAND]select ecc bit:4, sparesize :64 spare_per_sector=16
[ 2.360000] Scanning device for bad blocks
[ 2.880000] Signature matched and data read!
[ 2.888000] load_fact_bbt success 2047
[ 2.896000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 2.916000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 2.936000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 2.952000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 2.972000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 2.992000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 3.012000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 3.032000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 3.052000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 3.072000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 3.092000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 3.112000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 3.132000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 3.152000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 3.172000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 3.192000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 3.208000] Creating 5 MTD partitions on "MT7621-NAND":
[ 3.220000] 0x000000000000-0x00000ff80000 : "ALL"
[ 3.232000] 0x000000000000-0x000000080000 : "Bootloader"
[ 3.244000] 0x000000080000-0x000000100000 : "Config"
[ 3.252000] 0x000000100000-0x000000140000 : "Factory"
[ 3.264000] 0x000000140000-0x00000ff80000 : "firmware"
[ 3.280000] 0x0000002d595f-0x00000ff80000 : "rootfs"
[ 3.288000] mtd: partition "rootfs" must either start or end on erase block boundary or be smaller than an erase block -- forcing read-only
[ 3.328000] mtd: partition "rootfs_data" created automatically, ofs=0xfc0000, len=0xefc0000
[ 3.344000] 0x000000fc0000-0x00000ff80000 : "rootfs_data"
[ 3.356000] [mtk_nand] probe successfully!
[ 3.364000] rootfs = 2d595f to fc0000
-
[ 2.264000] MediaTek Nand driver init, version v2.1 Fix AHB virt2phys error
{{drivers_mtd}}/nand/mtk_nand.c/mtk_nand_init()
-
[ 2.280000] Allocate 16 byte aligned buffer: 804c2450
{{drivers_mtd}}/nand//mtk_nand.c/mtk_nand_probe()
-
[ 2.288000] Enable NFI Clock
{{drivers_mtd}}/nand/mtk_nand.c/mtk_nand_init_hw()
-
[ 2.284000] # MTK NAND # : Use HW ECC
{{drivers_mtd}}/nand/mtk_nand.c/mtk_nand_init_hw()
-
[ 2.292000] NAND ID [C2 DA 90 95 06, 00909506]
{{drivers_mtd}}/nand//mtk_nand.c/mtk_nand_probe()
-
[ 2.300000] Device found in MTK table, ID: c2da, EXT_ID: 909506
{{drivers_mtd}}/nand//mtk_nand.c/get_device_info()
-
[ 2.312000] Support this Device in MTK table! c2da
{{drivers_mtd}}/nand//mtk_nand.c/mtk_nand_probe()
-
[ 2.324000] NAND device: Manufacturer ID: 0xc2, Chip ID: 0xda (Macronix NAND 256MiB 3,3V 8-bit), 256MiB, page size: 2048, OOB size: 64
{{drivers_mtd}}/nand_base.c/nand_get_flash_type()
-
[ 2.348000] [NAND]select ecc bit:4, sparesize :64 spare_per_sector=16
{{drivers_mtd}}/mtk_nand.c/mtk_nand_select_chip()
-
[ 2.360000] Scanning device for bad blocks
{{drivers_mtd}}/nand_bbt.c/create_bbt()
-
[ 2.880000] Signature matched and data read!
{{drivers_mtd}}/mtk_nand.c/read_fact_bbt()
-
[ 2.888000] load_fact_bbt success 2047
{{drivers_mtd}}/mtk_nand.c/load_fact_bbt()
-
[ 2.896000] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
...{{drivers_mtd}}/mtk_nand.c/mtk_nand_probe()
-
[ 3.208000] Creating 5 MTD partitions on "MT7621-NAND":
{{drivers_mtd}}/mtdpart.c/add_mtd_partitions()
-
[ 3.220000] 0x000000000000-0x00000ff80000 : "ALL"
{{drivers_mtd}}/mtdpart.c/allocate_partition()
-
[ 3.232000] 0x000000000000-0x000000080000 : "Bootloader"
{{drivers_mtd}}/mtdpart.c/allocate_partition()
-
[ 3.244000] 0x000000080000-0x000000100000 : "Config"
{{drivers_mtd}}/mtdpart.c/allocate_partition()
-
[ 3.252000] 0x000000100000-0x000000140000 : "Factory"
{{drivers_mtd}}/mtdpart.c/allocate_partition()
-
[ 3.264000] 0x000000140000-0x00000ff80000 : "firmware"
{{drivers_mtd}}/mtdpart.c/allocate_partition()
-
[ 3.280000] 0x0000002d595f-0x00000ff80000 : "rootfs"
{{drivers_mtd}}/mtdpart.c/allocate_partition()
-
[ 3.288000] mtd: partition "rootfs" must either start or end on erase block boundary or be smaller than an erase block -- forcing read-only
{{drivers_mtd}}/mtdpart.c/allocate_partition()
-
[ 3.328000] mtd: partition "rootfs_data" created automatically, ofs=0xfc0000, len=0xefc0000
{{drivers_mtd}}/mtdpart.c/split_rootfs_data()
-
[ 3.344000] 0x000000fc0000-0x00000ff80000 : "rootfs_data"
{{drivers_mtd}}/mtdpart.c/allocate_partition()
-
[ 3.356000] [mtk_nand] probe successfully!
{{drivers_mtd}}/nand/mtk_nand.c/mtk_nand_probe()
-
[ 3.364000] rootfs = 2d595f to fc0000
{{drivers_mtd}}/nand/mtk_nand.c/mtk_nand_probe()
{{drivers_mtd}}/nand/mtk_nand.c/
/******************************************************************************
Device driver structure
******************************************************************************/
static struct platform_driver mtk_nand_driver = {
.probe = mtk_nand_probe,
.remove = mtk_nand_remove,
.suspend = mtk_nand_suspend,
.resume = mtk_nand_resume,
.driver = {
.name = "MT7621-NAND",
.owner = THIS_MODULE,
},
};
試著化簡 mtk_nand_probe()
static int mtk_nand_probe(struct platform_device *pdev)
{
struct mtk_nand_host_hw *hw;
struct mtd_info *mtd;
struct nand_chip *nand_chip;
int err = 0;
int id;
u32 ext_id;
u8 ext_id1, ext_id2, ext_id3;
int i;
{
u32 data;
data = DRV_Reg32(RALINK_SYSCTL_BASE+0x60);
data &= ~((0x3<<18)|(0x3<<16));
data |= ((0x2<<18) |(0x2<<16));
DRV_WriteReg32(RALINK_SYSCTL_BASE+0x60, data);
}
hw = (struct mtk_nand_host_hw *)pdev->dev.platform_data;
BUG_ON(!hw);
/* Allocate memory for the device structure (and zero it) */
host = kzalloc(sizeof(struct mtk_nand_host), GFP_KERNEL);
if (!host)
{
MSG(INIT, "mtk_nand: failed to allocate device structure.\n");
return -ENOMEM;
}
/* Allocate memory for 16 byte aligned buffer */
local_buffer_16_align = local_buffer + 16 - ((u32) local_buffer % 16);
printk(KERN_INFO "Allocate 16 byte aligned buffer: %p\n", local_buffer_16_align);
host->hw = hw;
/* init mtd data structure */
nand_chip = &host->nand_chip;
nand_chip->priv = host; /* link the private data structures */
mtd = &host->mtd;
mtd->priv = nand_chip;
mtd->owner = THIS_MODULE;
mtd->name = "MT7621-NAND";
hw->nand_ecc_mode = NAND_ECC_HW;
/* Set address of NAND IO lines */
nand_chip->IO_ADDR_R = (void __iomem *)NFI_DATAR_REG32;
nand_chip->IO_ADDR_W = (void __iomem *)NFI_DATAW_REG32;
nand_chip->chip_delay = 20; /* 20us command delay time */
nand_chip->ecc.mode = hw->nand_ecc_mode; /* enable ECC */
nand_chip->read_byte = mtk_nand_read_byte;
nand_chip->read_buf = mtk_nand_read_buf;
nand_chip->write_buf = mtk_nand_write_buf;
nand_chip->select_chip = mtk_nand_select_chip;
nand_chip->dev_ready = mtk_nand_dev_ready;
nand_chip->cmdfunc = mtk_nand_command_bp;
nand_chip->ecc.read_page = mtk_nand_read_page_hwecc;
nand_chip->ecc.write_page = mtk_nand_write_page_hwecc;
nand_chip->ecc.layout = &nand_oob_64;
nand_chip->ecc.size = hw->nand_ecc_size; //2048
nand_chip->ecc.bytes = hw->nand_ecc_bytes; //32
// For BMT, we need to revise driver architecture
nand_chip->write_page = mtk_nand_write_page;
nand_chip->ecc.write_oob = NULL;
nand_chip->block_markbad = mtk_nand_block_markbad; // need to add nand_get_device()/nand_release_device().
nand_chip->erase = mtk_nand_erase;
nand_chip->read_page = mtk_nand_read_page;
nand_chip->ecc.read_oob = mtk_nand_read_oob;
nand_chip->block_bad = mtk_nand_block_bad;
mtk_nand_init_hw(host);
/* Select the device */
nand_chip->select_chip(mtd, NFI_DEFAULT_CS);
/*
* Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
* after power-up
*/
nand_chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
memset(&devinfo, 0 , sizeof(flashdev_info));
/* Send the command for reading device ID */
nand_chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
/* Read manufacturer and device IDs */
manu_id = nand_chip->read_byte(mtd);
dev_id = nand_chip->read_byte(mtd);
ext_id1 = nand_chip->read_byte(mtd);
ext_id2 = nand_chip->read_byte(mtd);
ext_id3 = nand_chip->read_byte(mtd);
ext_id = ext_id1 << 16 | ext_id2 << 8 | ext_id3;
id = dev_id | (manu_id << 8);
printk("NAND ID [%02X %02X %02X %02X %02X, %08x]\n",manu_id, dev_id,ext_id1,\
ext_id2,ext_id3,ext_id);
if (!get_device_info(id, ext_id, &devinfo))
{
u32 chip_mode = RALINK_REG(RALINK_SYSCTL_BASE+0x010)&0x0F;
MSG(INIT, "Not Support this Device! \r\n");
memset(&devinfo, 0 , sizeof(flashdev_info));
MSG(INIT, "chip_mode=%08X\n",chip_mode);
/* apply bootstrap first */
devinfo.addr_cycle = 5;
devinfo.iowidth = 8;
switch (chip_mode)
{
case 10:
devinfo.pagesize = 2048;
devinfo.sparesize = 128;
devinfo.totalsize = 128;
devinfo.blocksize = 128;
break;
case 11:
devinfo.pagesize = 4096;
devinfo.sparesize = 128;
devinfo.totalsize = 1024;
devinfo.blocksize = 256;
break;
case 12:
devinfo.pagesize = 4096;
devinfo.sparesize = 224;
devinfo.totalsize = 2048;
devinfo.blocksize = 512;
break;
default:
case 1:
devinfo.pagesize = 2048;
devinfo.sparesize = 64;
devinfo.totalsize = 128;
devinfo.blocksize = 128;
break;
}
devinfo.timmingsetting = NFI_DEFAULT_ACCESS_TIMING;
devinfo.devciename[0] = 'U';
devinfo.advancedmode = 0;
}
mtd->writesize = devinfo.pagesize;
mtd->erasesize = (devinfo.blocksize<<10);
mtd->oobsize = devinfo.sparesize;
nand_chip->chipsize = (devinfo.totalsize<<20);
nand_chip->page_shift = ffs(mtd->writesize) - 1;
nand_chip->pagemask = (nand_chip->chipsize >> nand_chip->page_shift) - 1;
nand_chip->phys_erase_shift = ffs(mtd->erasesize) - 1;
nand_chip->chip_shift = ffs(nand_chip->chipsize) - 1;//0x1C;//ffs(nand_chip->chipsize) - 1;
nand_chip->oob_poi = nand_chip->buffers->databuf + mtd->writesize;
nand_chip->badblockpos = 0;
if (devinfo.pagesize == 4096)
{
nand_chip->ecc.layout = &nand_oob_128;
} else if (devinfo.pagesize == 2048)
{
nand_chip->ecc.layout = &nand_oob_64;
} else if (devinfo.pagesize == 512)
{
nand_chip->ecc.layout = &nand_oob_16;
}
nand_chip->ecc.layout->eccbytes = devinfo.sparesize-OOB_AVAI_PER_SECTOR*(devinfo.pagesize/NAND_SECTOR_SIZE);
for(i=0;i<nand_chip->ecc.layout->eccbytes;i++){
nand_chip->ecc.layout->eccpos[i]=OOB_AVAI_PER_SECTOR*(devinfo.pagesize/NAND_SECTOR_SIZE)+i;
}
//MSG(INIT, "[NAND] pagesz:%d , oobsz: %d,eccbytes: %d\n",
//devinfo.pagesize, sizeof(g_kCMD.au1OOB),nand_chip->ecc.layout->eccbytes);
MSG(INIT, "Support this Device in MTK table! %x \r\n", id);
hw->nfi_bus_width = devinfo.iowidth;
DRV_WriteReg32(NFI_ACCCON_REG32, devinfo.timmingsetting);
/* 16-bit bus width */
if (hw->nfi_bus_width == 16)
{
MSG(INIT, "%s : Set the 16-bit I/O settings!\n", MODULE_NAME);
nand_chip->options |= NAND_BUSWIDTH_16;
}
mtd->oobsize = devinfo.sparesize;
hw->nfi_cs_num = 1;
/* Scan to find existance of the device */
if (nand_scan(mtd, hw->nfi_cs_num))
{
MSG(INIT, "%s : nand_scan fail.\n", MODULE_NAME);
err = -ENXIO;
goto out;
}
g_page_size = mtd->writesize;
platform_set_drvdata(pdev, host);
if (hw->nfi_bus_width == 16)
{
NFI_SET_REG16(NFI_PAGEFMT_REG16, PAGEFMT_DBYTE_EN);
}
nand_chip->select_chip(mtd, 0);
nand_chip->chipsize -= (FACT_BBT_POOL_SIZE) << nand_chip->phys_erase_shift;
mtd->size = nand_chip->chipsize;
CFG_BLOCKSIZE = mtd->erasesize;
if (load_fact_bbt(mtd) == 0)
{
int i;
int total_block, bbt_size;
total_block = 1 << (nand_chip->chip_shift - nand_chip->phys_erase_shift);
bbt_size = total_block >> 2;
for (i = 0; i < bbt_size; i++)
{
nand_chip->bbt[i] |= fact_bbt[i];
}
for (i = 0; i < bbt_size; i++)
{
printk("%02x ", nand_chip->bbt[i]);
if (!((i+1) & 0x1f))
printk("\n");
}
}
/* modify partition table */
g_pasStatic_Partition[1].size = LARGE_MTD_BOOT_PART_SIZE;
g_pasStatic_Partition[2].size = LARGE_MTD_CONFIG_PART_SIZE;
g_pasStatic_Partition[3].size = LARGE_MTD_FACTORY_PART_SIZE;
//g_pasStatic_Partition[4].size = CONFIG_MTD_KERNEL_PART_SIZ;
g_pasStatic_Partition[5].size = IMAGE1_SIZE - (LARGE_MTD_BOOT_PART_SIZE + LARGE_MTD_CONFIG_PART_SIZE \
+ LARGE_MTD_FACTORY_PART_SIZE + CONFIG_MTD_KERNEL_PART_SIZ) - MTD_ROOTFS_RESERVED_BLOCK;
err = add_mtd_partitions(mtd, g_pasStatic_Partition, part_num);
/* Successfully!! */
if (!err)
{
MSG(INIT, "[mtk_nand] probe successfully!\n");
nand_disable_clock();
shift_on_bbt = 1;
printk("rootfs = %x to %x\n", (int)rootfs_offset, (int)rootfs_data_offset);
return err;
}
/* Fail!! */
out:
MSG(INIT, "[NFI] mtk_nand_probe fail, err = %d!\n", err);
nand_release(mtd);
platform_set_drvdata(pdev, NULL);
kfree(host);
nand_disable_clock();
return err;
}
追一下 mtk_nand_probe()
的這一部分
/* modify partition table */
g_pasStatic_Partition[1].size = LARGE_MTD_BOOT_PART_SIZE;
g_pasStatic_Partition[2].size = LARGE_MTD_CONFIG_PART_SIZE;
g_pasStatic_Partition[3].size = LARGE_MTD_FACTORY_PART_SIZE;
g_pasStatic_Partition[5].size =
IMAGE1_SIZE - (
LARGE_MTD_BOOT_PART_SIZE +
LARGE_MTD_CONFIG_PART_SIZE +
LARGE_MTD_FACTORY_PART_SIZE +
CONFIG_MTD_KERNEL_PART_SIZ
) - MTD_ROOTFS_RESERVED_BLOCK;
err = add_mtd_partitions(mtd, g_pasStatic_Partition, part_num);
g_pasStatic_Partition
定義在 {{drivers_mtd}}/nand/partition.h
static struct mtd_partition g_pasStatic_Partition[] = {
{
name: "ALL",
size: MTDPART_SIZ_FULL,
offset: 0,
},
/* Put your own partition definitions here */
{
name: "Bootloader",
size: MTD_BOOT_PART_SIZE,
offset: 0,
}, {
name: "Config",
size: MTD_CONFIG_PART_SIZE,
offset: MTDPART_OFS_APPEND
}, {
name: "Factory",
size: MTD_FACTORY_PART_SIZE,
offset: MTDPART_OFS_APPEND
}, {
name: "firmware",
size: MTDPART_SIZ_FULL,
offset: 0x140000,
},
};