board-mop500-uib.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /*
  2. * Copyright (C) ST-Ericsson SA 2010
  3. *
  4. * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
  5. * License terms: GNU General Public License (GPL), version 2
  6. */
  7. #define pr_fmt(fmt) "mop500-uib: " fmt
  8. #include <linux/kernel.h>
  9. #include <linux/init.h>
  10. #include <linux/i2c.h>
  11. #include <mach/hardware.h>
  12. #include "board-mop500.h"
  13. #include "id.h"
  14. enum mop500_uib {
  15. STUIB,
  16. U8500UIB,
  17. };
  18. struct uib {
  19. const char *name;
  20. const char *option;
  21. void (*init)(void);
  22. };
  23. static struct uib __initdata mop500_uibs[] = {
  24. [STUIB] = {
  25. .name = "ST-UIB",
  26. .option = "stuib",
  27. .init = mop500_stuib_init,
  28. },
  29. [U8500UIB] = {
  30. .name = "U8500-UIB",
  31. .option = "u8500uib",
  32. .init = mop500_u8500uib_init,
  33. },
  34. };
  35. static struct uib *mop500_uib;
  36. static int __init mop500_uib_setup(char *str)
  37. {
  38. int i;
  39. for (i = 0; i < ARRAY_SIZE(mop500_uibs); i++) {
  40. struct uib *uib = &mop500_uibs[i];
  41. if (!strcmp(str, uib->option)) {
  42. mop500_uib = uib;
  43. break;
  44. }
  45. }
  46. if (i == ARRAY_SIZE(mop500_uibs))
  47. pr_err("invalid uib= option (%s)\n", str);
  48. return 1;
  49. }
  50. __setup("uib=", mop500_uib_setup);
  51. /*
  52. * The UIBs are detected after the I2C host controllers are registered, so
  53. * i2c_register_board_info() can't be used.
  54. */
  55. void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
  56. unsigned n)
  57. {
  58. struct i2c_adapter *adap;
  59. struct i2c_client *client;
  60. int i;
  61. adap = i2c_get_adapter(busnum);
  62. if (!adap) {
  63. pr_err("failed to get adapter i2c%d\n", busnum);
  64. return;
  65. }
  66. for (i = 0; i < n; i++) {
  67. client = i2c_new_device(adap, &info[i]);
  68. if (!client)
  69. pr_err("failed to register %s to i2c%d\n",
  70. info[i].type, busnum);
  71. }
  72. i2c_put_adapter(adap);
  73. }
  74. static void __init __mop500_uib_init(struct uib *uib, const char *why)
  75. {
  76. pr_info("%s (%s)\n", uib->name, why);
  77. uib->init();
  78. }
  79. /*
  80. * Detect the UIB attached based on the presence or absence of i2c devices.
  81. */
  82. int __init mop500_uib_init(void)
  83. {
  84. struct uib *uib = mop500_uib;
  85. struct i2c_adapter *i2c0;
  86. int ret;
  87. if (!cpu_is_u8500_family())
  88. return -ENODEV;
  89. if (uib) {
  90. __mop500_uib_init(uib, "from uib= boot argument");
  91. return 0;
  92. }
  93. i2c0 = i2c_get_adapter(0);
  94. if (!i2c0) {
  95. __mop500_uib_init(&mop500_uibs[STUIB],
  96. "fallback, could not get i2c0");
  97. return -ENODEV;
  98. }
  99. /* U8500-UIB has the TC35893 at 0x44 on I2C0, the ST-UIB doesn't. */
  100. ret = i2c_smbus_xfer(i2c0, 0x44, 0, I2C_SMBUS_WRITE, 0,
  101. I2C_SMBUS_QUICK, NULL);
  102. i2c_put_adapter(i2c0);
  103. if (ret == 0)
  104. uib = &mop500_uibs[U8500UIB];
  105. else
  106. uib = &mop500_uibs[STUIB];
  107. __mop500_uib_init(uib, "detected");
  108. return 0;
  109. }