20180205_jeffrey - silenceuncrio/diary GitHub Wiki

0920

review

0935

針對 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()

1025

{{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,
               },
};

1140

試著化簡 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;
}

1140

追一下 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);

1310

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,
    },
};
⚠️ **GitHub.com Fallback** ⚠️