首页 > 编程知识 正文

mtd设备,mtk cui_inline

时间:2023-05-05 04:27:59 阅读:127773 作者:3320

嵌入式开发的一个常见任务是调配新设备。 以前有很多任务,包括配置uboot、添加flash驱动程序支持、配置MTD分区和配置网络。 其中MTD分区信息往往以cmdline的形式传递给内核,有两种方法:通过uboot参数传递,以及内核配置CONFIG_CMDLINE参数。

在cmdline中,MTD分区信息具有以下固定格式:

mtdparts=mtddef[; MTD def ] MTD def :=MTD-id :部件def [, 部件def ]部件def :=size [ @ offset ] [ name ] [ ro ] [ lk ] MTD-id :=uniquenameusedinmappingdriver/设备(MTD size :=标准dardlinuxmemsizeor '-' todenoteallremainingspacesizeisautomaticallytruncatedatendofdeviceifspecior ) ped offset :=standardlinuxmemsizeifomittedthepartwillimmediatelyfollowthepreviouspartor0ifthefirstpartname :=' (' nanal MTD部件=SPI 32766.03360256 k (uboot )、2m (kernel )、6m (rootfs ).- ) (rootfs ) )。

其中mtd-id=spi32766.0,我接触的很多项目都采用这一个mtd-id,为什么是这个值? 32766是怎么得到的? 和flash芯片有关吗? 分析一下吧。

1,32766=0x7FFE,最初以为应该与闪存型号有关,但搜索闪存驱动器代码后未发现两者之间的关联。 另外,使用不同闪存芯片的器件采用了该值,表示与闪存没有关系。

2、那么分析代码。 首先,需要知道内核中的哪个变量表示mtd-id。 这里不是按照代码的执行顺序进行分析,而是打算按照我思考问题的方式进行分析。 既然mtdparts是cmdline参数,我们首先查看cmdline的分析函数。

staticintparse _ cmdline _ partitions (struct MTD _ info * master,struct mtd_partition **pparts,struct MTD _ part _ part _ s ) 部件; 部件=部件-下一步({ if (! mtd_id! strcmp (部件MTD_id,MTD_id ) ) break; (与cmdline的mtd-id匹配……) 12345678910111213上的代码显示内核中的mtd-id是在master-name中定义的,然后从该函数开始跟踪。 调用关系如下:

m25p _ probe-- MTD _ device _ parse _ register-- parse _ MTD _ partitions-- parse _ cmdline _ partitions 1234是

静态int M25 p _ probe (struct SPI _ device * SPI ({ . struct M25 p * flash; struct spi_nor *nor; flash=devm_kzalloc(SPI-dev,sizeof ) flash ),GFP_KERNEL ); nor-dev=spi-dev; //spi设备设备nor-MTD=flash-MTD; //master源. ret=SPI_nor_scan(nor,SPI_get_device_id ) SPI ),mode ); //在此为nor处理. return MTD _ device _ parse _ register (

&flash->mtd, NULL, &ppdata, data ? data->parts : NULL, data ? data->nr_parts : 0);} 1234567891011121314151617

继续跟踪spi_nor_scan

int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id, enum read_mode mode){ ... struct device *dev = nor->dev; struct mtd_info *mtd = nor->mtd; ... mtd->name = dev_name(dev);//mtd-id是设备dev的name ...} 12345678910

可以得出内核中mtd-id是spi设备名(spi->dev->name)
3、接下来我们去跟踪spi设备名是怎么得来的
查找spi设备驱动(platform_driver),一般是通过设备树dts信息去内核查找,跟踪platform_driver中相应的probe函数。这里的驱动函数就不列举了,不同的spi设备有不同的驱动,一般是由原厂商提供。驱动probe函数中一般的执行流程如下:

spi_alloc_master -->spi_register_master -->of_register_spi_devices -->spi_add_device -->device_add 12345

1) spi_alloc_master

struct spi_master *spi_alloc_master(struct device *dev, unsigned size){ struct spi_master *master; ... master = kzalloc(size + sizeof(*master), GFP_KERNEL); ... master->bus_num = -1;//注意这里初始化为-1 master->num_chipselect = 1; master->dev.class = &spi_master_class; master->dev.parent = get_device(dev); spi_master_set_devdata(master, &master[1]); return master;} 1234567891011121314

2)spi_register_master

int spi_register_master(struct spi_master *master){ static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1); // 重点,dyn_bus_id初始化为0x7FFF struct device *dev = master->dev.parent; ... if (master->num_chipselect == 0) return -EINVAL; if ((master->bus_num < 0) && master->dev.of_node) master->bus_num = of_alias_get_id(master->dev.of_node, "spi"); /* convention: dynamically assigned bus IDs count down from the max */ if (master->bus_num < 0) { // 初始化时bus_num=-1 /* FIXME switch to an IDR based scheme, something like * I2C now uses, so we can't run out of "dynamic" IDs */ master->bus_num = atomic_dec_return(&dyn_bus_id); //计算后bus_num=0x7FFE=32766 dynamic = 1; } ... /* register the device, then userspace will see it. * registration fails if the bus ID is in use. */ dev_set_name(&master->dev, "spi%u", master->bus_num);// master->dev->name="spi32766" status = device_add(&master->dev); if (status < 0) goto done; dev_dbg(dev, "registered master %s%sn", dev_name(&master->dev), dynamic ? " (dynamic)" : ""); ... /* Register devices from the device tree and ACPI */ of_register_spi_devices(master); acpi_register_spi_devices(master);done: return status;} 1234567891011121314151617181920212223242526272829303132333435363738

现在已经得到spi_master设备名为spi32766
3)of_register_spi_devices

static void of_register_spi_devices(struct spi_master *master){ struct spi_device *spi; struct device_node *nc; int rc; u32 value; if (!master->dev.of_node) return; for_each_available_child_of_node(master->dev.of_node, nc) { /* Alloc an spi_device */ spi = spi_alloc_device(master); // 这里会创建我们需要的spi设备 if (!spi) { dev_err(&master->dev, "spi_device alloc error for %sn", nc->full_name); spi_dev_put(spi); continue; } /* Select device driver */ if (of_modalias_node(nc, spi->modalias, sizeof(spi->modalias)) < 0) { dev_err(&master->dev, "cannot find modalias for %sn", nc->full_name); spi_dev_put(spi); continue; } /* Device address */ // 获取设备树里spi节点下的reg参数,赋值给spi->chip_select,代表片选ID,即第几片flash,0代表第一片flash rc = of_property_read_u32(nc, "reg", &value); if (rc) { dev_err(&master->dev, "%s has no valid 'reg' property (%d)n", nc->full_name, rc); spi_dev_put(spi); continue; } spi->chip_select = value;//一般为0,第一片flash ... } ... rc = spi_add_device(spi);//将spi设备(spi->dev)添加入linux device hierarchy,也可以说是devices bus中 ...} 123456789101112131415161718192021222324252627282930313233343536373839404142434445

4)spi_add_device

int spi_add_device(struct spi_device *spi){ ... spi_dev_set_name(spi);//确定spi->dev->name ... status = device_add(&spi->dev);//这是linux设备模型中一个很关键的函数,这里不详细讲,函数除了添加device到bus外,还会probe drivers for this device and attach device to driver. ...}static void spi_dev_set_name(struct spi_device *spi){ struct acpi_device *adev = ACPI_COMPANION(&spi->dev); if (adev) { dev_set_name(&spi->dev, "spi-%s", acpi_dev_name(adev)); return; } //最终确定spi设备名为"spi32766.0",dev_name(&spi->master->dev)为"spi32766", spi->chip_select为0 dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->master->dev), spi->chip_select);} 12345678910111213141516171819202122

至此,确定spi设备名spi32766.0,按代码流程分析,已经清楚为什么mtd-id是spi32766.0了。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。