316/**
317 * platform_device_register - add a platform-level device
318 * @pdev: platform device we\'re adding
319 */
320int platform_device_register(struct platform_device *pdev)
321{
322 device_initialize(&pdev->dev);
323 return platform_device_add(pdev);
324}
325EXPORT_SYMBOL_GPL(platform_device_register);
我们看到注册一个platform device分为了两部分,初始化这个platform_device,然后将此platform_device添加到platform总线中。输入参数platform_device可以是静态的全局设备。
另外一种机制就是动态申请platform_device_alloc一个platform_device设备,然后通过platform_device_add_resources及platform_device_add_data等添加相关资源和属性。
无论哪一种platform_device,最终都将通过platform_device_add注册到platform总线上。
229/**
230 * platform_device_add - add a platform device to device hierarchy
231 * @pdev: platform device we\'re adding
232 *
233 * This is part 2 of platform_device_register(), though may be called
234 * separately _iff_ pdev was allocated by platform_device_alloc().
235 */
236int platform_device_add(struct platform_device *pdev)
237{
238 int i, ret = 0;
239
240 if (!pdev)
241 return -EINVAL;
242
初始化设备的parent为platform_bus,初始化设备的总线为platform_bus_type。
243 if (!pdev->dev.parent)
244 pdev->dev.parent = &platform_bus;
245
246 pdev->dev.bus = &platform_bus_type;
247
/*++++++++++++++
The platform_device.dev.bus_id is the canonical name for the devices.
It\'s built from two components:
* platform_device.name ... which is also used to for driver matching.
* platform_device.id ... the device instance number, or else "-1"
to indicate there\'s only one.
These are concatenated, so name/id "serial"/0 indicates bus_id "serial.0", and
"serial/3" indicates bus_id "serial.3"; both would use the platform_driver
named "serial". While "my_rtc"/-1 would be bus_id "my_rtc" (no instance id)
and use the platform_driver called "my_rtc".
++++++++++++++*/
248 if (pdev->id != -1)
249 snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%d", pdev->name,
250 pdev->id);
251 else
252 strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);
253
设置设备struct device 的bus_id成员,留心这个地方,在以后还需要用到这个的。
254 for (i = 0; i < pdev->num_resources; i++) {
255 struct resource *p, *r = &pdev->resource[i];
256
257 if (r->name == NULL)
258 r->name = pdev->dev.bus_id;
259
260 p = r->parent;
261 if (!p) {
262 if (r->flags & IORESOURCE_MEM)
263 p = &iomem_resource;
264 else if (r->flags & IORESOURCE_IO)
265 p = &ioport_resource;
266 }
//resources分为两种IORESOURCE_MEM和IORESOURCE_IO
//CPU对外设IO端口物理地址的编址方式有两种:I/O映射方式和内存映射方式
267
268 if (p && insert_resource(p, r)) {
269 printk(KERN_ERR
270 "%s: failed to claim resource %d/n",
271 pdev->dev.bus_id, i);
272 ret = -EBUSY;
273 goto failed;
274 }
275 }
276
277 pr_debug("Registering platform device \'%s\'. Parent at %s/n",
278 pdev->dev.bus_id, pdev->dev.parent->bus_id);
279
280 ret = device_add(&pdev->dev);
281 if (ret == 0)
282 return ret;
283
284 failed:
285 while (--i >= 0)
286 if (pdev->resource[i].flags & (IORESOURCE_MEM|IORESOURCE_IO))
287 release_resource(&pdev->resource[i]);
288 return ret;
289}
290EXPORT_SYMBOL_GPL(platform_device_add);