fdt_i2c.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /*
  2. * SPDX-License-Identifier: BSD-2-Clause
  3. *
  4. * Copyright (c) 2021 YADRO
  5. *
  6. * Authors:
  7. * Nikita Shubin <n.shubin@yadro.com>
  8. *
  9. * derivate: lib/utils/gpio/fdt_gpio.c
  10. * Authors:
  11. * Anup Patel <anup.patel@wdc.com>
  12. */
  13. #include <libfdt.h>
  14. #include <sbi/sbi_error.h>
  15. #include <sbi_utils/fdt/fdt_helper.h>
  16. #include <sbi_utils/i2c/fdt_i2c.h>
  17. /* List of FDT i2c adapter drivers generated at compile time */
  18. extern struct fdt_i2c_adapter *fdt_i2c_adapter_drivers[];
  19. extern unsigned long fdt_i2c_adapter_drivers_size;
  20. static int fdt_i2c_adapter_init(void *fdt, int nodeoff)
  21. {
  22. int pos, rc;
  23. struct fdt_i2c_adapter *drv;
  24. const struct fdt_match *match;
  25. /* Try all I2C drivers one-by-one */
  26. for (pos = 0; pos < fdt_i2c_adapter_drivers_size; pos++) {
  27. drv = fdt_i2c_adapter_drivers[pos];
  28. match = fdt_match_node(fdt, nodeoff, drv->match_table);
  29. if (match && drv->init) {
  30. rc = drv->init(fdt, nodeoff, match);
  31. if (rc == SBI_ENODEV)
  32. continue;
  33. if (rc)
  34. return rc;
  35. return 0;
  36. }
  37. }
  38. return SBI_ENOSYS;
  39. }
  40. static int fdt_i2c_adapter_find(void *fdt, int nodeoff,
  41. struct i2c_adapter **out_adapter)
  42. {
  43. int rc;
  44. struct i2c_adapter *adapter = i2c_adapter_find(nodeoff);
  45. if (!adapter) {
  46. /* I2C adapter not found so initialize matching driver */
  47. rc = fdt_i2c_adapter_init(fdt, nodeoff);
  48. if (rc)
  49. return rc;
  50. /* Try to find I2C adapter again */
  51. adapter = i2c_adapter_find(nodeoff);
  52. if (!adapter)
  53. return SBI_ENOSYS;
  54. }
  55. if (out_adapter)
  56. *out_adapter = adapter;
  57. return 0;
  58. }
  59. int fdt_i2c_adapter_get(void *fdt, int nodeoff,
  60. struct i2c_adapter **out_adapter)
  61. {
  62. int rc;
  63. struct i2c_adapter *adapter;
  64. if (!fdt || (nodeoff < 0) || !out_adapter)
  65. return SBI_EINVAL;
  66. rc = fdt_i2c_adapter_find(fdt, nodeoff, &adapter);
  67. if (rc)
  68. return rc;
  69. *out_adapter = adapter;
  70. return 0;
  71. }