.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * omap_device implementation |
---|
3 | 4 | * |
---|
.. | .. |
---|
9 | 10 | * Pandita, Sakari Poussa, Anand Sawant, Santosh Shilimkar, Richard |
---|
10 | 11 | * Woodruff |
---|
11 | 12 | * |
---|
12 | | - * This program is free software; you can redistribute it and/or modify |
---|
13 | | - * it under the terms of the GNU General Public License version 2 as |
---|
14 | | - * published by the Free Software Foundation. |
---|
15 | | - * |
---|
16 | 13 | * This code provides a consistent interface for OMAP device drivers |
---|
17 | 14 | * to control power management and interconnect properties of their |
---|
18 | 15 | * devices. |
---|
.. | .. |
---|
20 | 17 | * In the medium- to long-term, this code should be implemented as a |
---|
21 | 18 | * proper omap_bus/omap_device in Linux, no more platform_data func |
---|
22 | 19 | * pointers |
---|
23 | | - * |
---|
24 | | - * |
---|
25 | 20 | */ |
---|
26 | 21 | #undef DEBUG |
---|
27 | 22 | |
---|
.. | .. |
---|
124 | 119 | |
---|
125 | 120 | /** |
---|
126 | 121 | * omap_device_build_from_dt - build an omap_device with multiple hwmods |
---|
127 | | - * @pdev_name: name of the platform_device driver to use |
---|
128 | | - * @pdev_id: this platform_device's connection ID |
---|
129 | | - * @oh: ptr to the single omap_hwmod that backs this omap_device |
---|
130 | | - * @pdata: platform_data ptr to associate with the platform_device |
---|
131 | | - * @pdata_len: amount of memory pointed to by @pdata |
---|
| 122 | + * @pdev: The platform device to update. |
---|
132 | 123 | * |
---|
133 | 124 | * Function for building an omap_device already registered from device-tree |
---|
134 | 125 | * |
---|
.. | .. |
---|
251 | 242 | if (pdev->dev.of_node) |
---|
252 | 243 | omap_device_build_from_dt(pdev); |
---|
253 | 244 | omap_auxdata_legacy_init(dev); |
---|
254 | | - /* fall through */ |
---|
| 245 | + fallthrough; |
---|
255 | 246 | default: |
---|
256 | 247 | od = to_omap_device(pdev); |
---|
257 | 248 | if (od) |
---|
.. | .. |
---|
299 | 290 | |
---|
300 | 291 | /** |
---|
301 | 292 | * omap_device_get_context_loss_count - get lost context count |
---|
302 | | - * @od: struct omap_device * |
---|
| 293 | + * @pdev: The platform device to update. |
---|
303 | 294 | * |
---|
304 | 295 | * Using the primary hwmod, query the context loss count for this |
---|
305 | 296 | * device. |
---|
.. | .. |
---|
328 | 319 | /** |
---|
329 | 320 | * omap_device_alloc - allocate an omap_device |
---|
330 | 321 | * @pdev: platform_device that will be included in this omap_device |
---|
331 | | - * @oh: ptr to the single omap_hwmod that backs this omap_device |
---|
332 | | - * @pdata: platform_data ptr to associate with the platform_device |
---|
333 | | - * @pdata_len: amount of memory pointed to by @pdata |
---|
| 322 | + * @ohs: ptr to the omap_hwmod for this omap_device |
---|
| 323 | + * @oh_cnt: the size of the ohs list |
---|
334 | 324 | * |
---|
335 | 325 | * Convenience function for allocating an omap_device structure and filling |
---|
336 | 326 | * hwmods, and resources. |
---|
.. | .. |
---|
383 | 373 | od->pdev->archdata.od = NULL; |
---|
384 | 374 | kfree(od->hwmods); |
---|
385 | 375 | kfree(od); |
---|
386 | | -} |
---|
387 | | - |
---|
388 | | -/** |
---|
389 | | - * omap_device_copy_resources - Add legacy IO and IRQ resources |
---|
390 | | - * @oh: interconnect target module |
---|
391 | | - * @pdev: platform device to copy resources to |
---|
392 | | - * |
---|
393 | | - * We still have legacy DMA and smartreflex needing resources. |
---|
394 | | - * Let's populate what they need until we can eventually just |
---|
395 | | - * remove this function. Note that there should be no need to |
---|
396 | | - * call this from omap_device_build_from_dt(), nor should there |
---|
397 | | - * be any need to call it for other devices. |
---|
398 | | - */ |
---|
399 | | -static int |
---|
400 | | -omap_device_copy_resources(struct omap_hwmod *oh, |
---|
401 | | - struct platform_device *pdev) |
---|
402 | | -{ |
---|
403 | | - struct device_node *np, *child; |
---|
404 | | - struct property *prop; |
---|
405 | | - struct resource *res; |
---|
406 | | - const char *name; |
---|
407 | | - int error, irq = 0; |
---|
408 | | - |
---|
409 | | - if (!oh || !oh->od || !oh->od->pdev) |
---|
410 | | - return -EINVAL; |
---|
411 | | - |
---|
412 | | - np = oh->od->pdev->dev.of_node; |
---|
413 | | - if (!np) { |
---|
414 | | - error = -ENODEV; |
---|
415 | | - goto error; |
---|
416 | | - } |
---|
417 | | - |
---|
418 | | - res = kcalloc(2, sizeof(*res), GFP_KERNEL); |
---|
419 | | - if (!res) |
---|
420 | | - return -ENOMEM; |
---|
421 | | - |
---|
422 | | - /* Do we have a dts range for the interconnect target module? */ |
---|
423 | | - error = omap_hwmod_parse_module_range(oh, np, res); |
---|
424 | | - |
---|
425 | | - /* No ranges, rely on device reg entry */ |
---|
426 | | - if (error) |
---|
427 | | - error = of_address_to_resource(np, 0, res); |
---|
428 | | - if (error) |
---|
429 | | - goto free; |
---|
430 | | - |
---|
431 | | - /* SmartReflex needs first IO resource name to be "mpu" */ |
---|
432 | | - res[0].name = "mpu"; |
---|
433 | | - |
---|
434 | | - /* |
---|
435 | | - * We may have a configured "ti,sysc" interconnect target with a |
---|
436 | | - * dts child with the interrupt. If so use the first child's |
---|
437 | | - * first interrupt for "ti-hwmods" legacy support. |
---|
438 | | - */ |
---|
439 | | - of_property_for_each_string(np, "compatible", prop, name) |
---|
440 | | - if (!strncmp("ti,sysc-", name, 8)) |
---|
441 | | - break; |
---|
442 | | - |
---|
443 | | - child = of_get_next_available_child(np, NULL); |
---|
444 | | - |
---|
445 | | - if (name) |
---|
446 | | - irq = irq_of_parse_and_map(child, 0); |
---|
447 | | - if (!irq) |
---|
448 | | - irq = irq_of_parse_and_map(np, 0); |
---|
449 | | - if (!irq) { |
---|
450 | | - error = -EINVAL; |
---|
451 | | - goto free; |
---|
452 | | - } |
---|
453 | | - |
---|
454 | | - /* Legacy DMA code needs interrupt name to be "0" */ |
---|
455 | | - res[1].start = irq; |
---|
456 | | - res[1].end = irq; |
---|
457 | | - res[1].flags = IORESOURCE_IRQ; |
---|
458 | | - res[1].name = "0"; |
---|
459 | | - |
---|
460 | | - error = platform_device_add_resources(pdev, res, 2); |
---|
461 | | - |
---|
462 | | -free: |
---|
463 | | - kfree(res); |
---|
464 | | - |
---|
465 | | -error: |
---|
466 | | - WARN(error, "%s: %s device %s failed: %i\n", |
---|
467 | | - __func__, oh->name, dev_name(&pdev->dev), |
---|
468 | | - error); |
---|
469 | | - |
---|
470 | | - return error; |
---|
471 | | -} |
---|
472 | | - |
---|
473 | | -/** |
---|
474 | | - * omap_device_build - build and register an omap_device with one omap_hwmod |
---|
475 | | - * @pdev_name: name of the platform_device driver to use |
---|
476 | | - * @pdev_id: this platform_device's connection ID |
---|
477 | | - * @oh: ptr to the single omap_hwmod that backs this omap_device |
---|
478 | | - * @pdata: platform_data ptr to associate with the platform_device |
---|
479 | | - * @pdata_len: amount of memory pointed to by @pdata |
---|
480 | | - * |
---|
481 | | - * Convenience function for building and registering a single |
---|
482 | | - * omap_device record, which in turn builds and registers a |
---|
483 | | - * platform_device record. See omap_device_build_ss() for more |
---|
484 | | - * information. Returns ERR_PTR(-EINVAL) if @oh is NULL; otherwise, |
---|
485 | | - * passes along the return value of omap_device_build_ss(). |
---|
486 | | - */ |
---|
487 | | -struct platform_device __init *omap_device_build(const char *pdev_name, |
---|
488 | | - int pdev_id, |
---|
489 | | - struct omap_hwmod *oh, |
---|
490 | | - void *pdata, int pdata_len) |
---|
491 | | -{ |
---|
492 | | - int ret = -ENOMEM; |
---|
493 | | - struct platform_device *pdev; |
---|
494 | | - struct omap_device *od; |
---|
495 | | - |
---|
496 | | - if (!oh || !pdev_name) |
---|
497 | | - return ERR_PTR(-EINVAL); |
---|
498 | | - |
---|
499 | | - if (!pdata && pdata_len > 0) |
---|
500 | | - return ERR_PTR(-EINVAL); |
---|
501 | | - |
---|
502 | | - if (strncmp(oh->name, "smartreflex", 11) && |
---|
503 | | - strncmp(oh->name, "dma", 3)) { |
---|
504 | | - pr_warn("%s need to update %s to probe with dt\na", |
---|
505 | | - __func__, pdev_name); |
---|
506 | | - ret = -ENODEV; |
---|
507 | | - goto odbs_exit; |
---|
508 | | - } |
---|
509 | | - |
---|
510 | | - pdev = platform_device_alloc(pdev_name, pdev_id); |
---|
511 | | - if (!pdev) { |
---|
512 | | - ret = -ENOMEM; |
---|
513 | | - goto odbs_exit; |
---|
514 | | - } |
---|
515 | | - |
---|
516 | | - /* Set the dev_name early to allow dev_xxx in omap_device_alloc */ |
---|
517 | | - if (pdev->id != -1) |
---|
518 | | - dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); |
---|
519 | | - else |
---|
520 | | - dev_set_name(&pdev->dev, "%s", pdev->name); |
---|
521 | | - |
---|
522 | | - /* |
---|
523 | | - * Must be called before omap_device_alloc() as oh->od |
---|
524 | | - * only contains the currently registered omap_device |
---|
525 | | - * and will get overwritten by omap_device_alloc(). |
---|
526 | | - */ |
---|
527 | | - ret = omap_device_copy_resources(oh, pdev); |
---|
528 | | - if (ret) |
---|
529 | | - goto odbs_exit1; |
---|
530 | | - |
---|
531 | | - od = omap_device_alloc(pdev, &oh, 1); |
---|
532 | | - if (IS_ERR(od)) { |
---|
533 | | - ret = PTR_ERR(od); |
---|
534 | | - goto odbs_exit1; |
---|
535 | | - } |
---|
536 | | - |
---|
537 | | - ret = platform_device_add_data(pdev, pdata, pdata_len); |
---|
538 | | - if (ret) |
---|
539 | | - goto odbs_exit2; |
---|
540 | | - |
---|
541 | | - ret = omap_device_register(pdev); |
---|
542 | | - if (ret) |
---|
543 | | - goto odbs_exit2; |
---|
544 | | - |
---|
545 | | - return pdev; |
---|
546 | | - |
---|
547 | | -odbs_exit2: |
---|
548 | | - omap_device_delete(od); |
---|
549 | | -odbs_exit1: |
---|
550 | | - platform_device_put(pdev); |
---|
551 | | -odbs_exit: |
---|
552 | | - |
---|
553 | | - pr_err("omap_device: %s: build failed (%d)\n", pdev_name, ret); |
---|
554 | | - |
---|
555 | | - return ERR_PTR(ret); |
---|
556 | 376 | } |
---|
557 | 377 | |
---|
558 | 378 | #ifdef CONFIG_PM |
---|
.. | .. |
---|
656 | 476 | |
---|
657 | 477 | /** |
---|
658 | 478 | * omap_device_register - register an omap_device with one omap_hwmod |
---|
659 | | - * @od: struct omap_device * to register |
---|
| 479 | + * @pdev: the platform device (omap_device) to register. |
---|
660 | 480 | * |
---|
661 | 481 | * Register the omap_device structure. This currently just calls |
---|
662 | 482 | * platform_device_register() on the underlying platform_device. |
---|
.. | .. |
---|
675 | 495 | |
---|
676 | 496 | /** |
---|
677 | 497 | * omap_device_enable - fully activate an omap_device |
---|
678 | | - * @od: struct omap_device * to activate |
---|
| 498 | + * @pdev: the platform device to activate |
---|
679 | 499 | * |
---|
680 | 500 | * Do whatever is necessary for the hwmods underlying omap_device @od |
---|
681 | 501 | * to be accessible and ready to operate. This generally involves |
---|
.. | .. |
---|
709 | 529 | |
---|
710 | 530 | /** |
---|
711 | 531 | * omap_device_idle - idle an omap_device |
---|
712 | | - * @od: struct omap_device * to idle |
---|
| 532 | + * @pdev: The platform_device (omap_device) to idle |
---|
713 | 533 | * |
---|
714 | 534 | * Idle omap_device @od. Device drivers call this function indirectly |
---|
715 | 535 | * via pm_runtime_put*(). Returns -EINVAL if the omap_device is not |
---|