acer-ec-a500.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Acer Iconia Tab A500 Embedded Controller Driver
  4. *
  5. * Copyright 2020 GRATE-driver project
  6. */
  7. #include <linux/delay.h>
  8. #include <linux/i2c.h>
  9. #include <linux/mfd/core.h>
  10. #include <linux/module.h>
  11. #include <linux/of_device.h>
  12. #include <linux/reboot.h>
  13. #include <linux/regmap.h>
  14. #define A500_EC_I2C_ERR_TIMEOUT 500
  15. #define A500_EC_POWER_CMD_TIMEOUT 1000
  16. /*
  17. * Controller's firmware expects specific command opcodes to be used for the
  18. * corresponding registers. Unsupported commands are skipped by the firmware.
  19. */
  20. #define CMD_SHUTDOWN 0x0
  21. #define CMD_WARM_REBOOT 0x0
  22. #define CMD_COLD_REBOOT 0x1
  23. enum {
  24. REG_CURRENT_NOW = 0x03,
  25. REG_SHUTDOWN = 0x52,
  26. REG_WARM_REBOOT = 0x54,
  27. REG_COLD_REBOOT = 0x55,
  28. };
  29. static struct i2c_client *a500_ec_client_pm_off;
  30. static int a500_ec_read(void *context, const void *reg_buf, size_t reg_size,
  31. void *val_buf, size_t val_sizel)
  32. {
  33. struct i2c_client *client = context;
  34. unsigned int reg, retries = 5;
  35. u16 *ret_val = val_buf;
  36. s32 ret = 0;
  37. reg = *(u8 *)reg_buf;
  38. while (retries-- > 0) {
  39. ret = i2c_smbus_read_word_data(client, reg);
  40. if (ret >= 0)
  41. break;
  42. msleep(A500_EC_I2C_ERR_TIMEOUT);
  43. }
  44. if (ret < 0) {
  45. dev_err(&client->dev, "read 0x%x failed: %d\n", reg, ret);
  46. return ret;
  47. }
  48. *ret_val = ret;
  49. if (reg == REG_CURRENT_NOW)
  50. fsleep(10000);
  51. return 0;
  52. }
  53. static int a500_ec_write(void *context, const void *data, size_t count)
  54. {
  55. struct i2c_client *client = context;
  56. unsigned int reg, val, retries = 5;
  57. s32 ret = 0;
  58. reg = *(u8 *)(data + 0);
  59. val = *(u16 *)(data + 1);
  60. while (retries-- > 0) {
  61. ret = i2c_smbus_write_word_data(client, reg, val);
  62. if (ret >= 0)
  63. break;
  64. msleep(A500_EC_I2C_ERR_TIMEOUT);
  65. }
  66. if (ret < 0) {
  67. dev_err(&client->dev, "write 0x%x failed: %d\n", reg, ret);
  68. return ret;
  69. }
  70. return 0;
  71. }
  72. static const struct regmap_config a500_ec_regmap_config = {
  73. .name = "KB930",
  74. .reg_bits = 8,
  75. .val_bits = 16,
  76. .max_register = 0xff,
  77. };
  78. static const struct regmap_bus a500_ec_regmap_bus = {
  79. .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
  80. .val_format_endian_default = REGMAP_ENDIAN_LITTLE,
  81. .write = a500_ec_write,
  82. .read = a500_ec_read,
  83. .max_raw_read = 2,
  84. };
  85. static void a500_ec_poweroff(void)
  86. {
  87. i2c_smbus_write_word_data(a500_ec_client_pm_off,
  88. REG_SHUTDOWN, CMD_SHUTDOWN);
  89. mdelay(A500_EC_POWER_CMD_TIMEOUT);
  90. }
  91. static int a500_ec_restart_notify(struct notifier_block *this,
  92. unsigned long reboot_mode, void *data)
  93. {
  94. if (reboot_mode == REBOOT_WARM)
  95. i2c_smbus_write_word_data(a500_ec_client_pm_off,
  96. REG_WARM_REBOOT, CMD_WARM_REBOOT);
  97. else
  98. i2c_smbus_write_word_data(a500_ec_client_pm_off,
  99. REG_COLD_REBOOT, CMD_COLD_REBOOT);
  100. mdelay(A500_EC_POWER_CMD_TIMEOUT);
  101. return NOTIFY_DONE;
  102. }
  103. static struct notifier_block a500_ec_restart_handler = {
  104. .notifier_call = a500_ec_restart_notify,
  105. .priority = 200,
  106. };
  107. static const struct mfd_cell a500_ec_cells[] = {
  108. { .name = "acer-a500-iconia-battery", },
  109. { .name = "acer-a500-iconia-leds", },
  110. };
  111. static int a500_ec_probe(struct i2c_client *client)
  112. {
  113. struct regmap *regmap;
  114. int err;
  115. regmap = devm_regmap_init(&client->dev, &a500_ec_regmap_bus,
  116. client, &a500_ec_regmap_config);
  117. if (IS_ERR(regmap))
  118. return PTR_ERR(regmap);
  119. err = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO,
  120. a500_ec_cells, ARRAY_SIZE(a500_ec_cells),
  121. NULL, 0, NULL);
  122. if (err) {
  123. dev_err(&client->dev, "failed to add sub-devices: %d\n", err);
  124. return err;
  125. }
  126. if (of_device_is_system_power_controller(client->dev.of_node)) {
  127. a500_ec_client_pm_off = client;
  128. err = register_restart_handler(&a500_ec_restart_handler);
  129. if (err)
  130. return err;
  131. if (!pm_power_off)
  132. pm_power_off = a500_ec_poweroff;
  133. }
  134. return 0;
  135. }
  136. static void a500_ec_remove(struct i2c_client *client)
  137. {
  138. if (of_device_is_system_power_controller(client->dev.of_node)) {
  139. if (pm_power_off == a500_ec_poweroff)
  140. pm_power_off = NULL;
  141. unregister_restart_handler(&a500_ec_restart_handler);
  142. }
  143. }
  144. static const struct of_device_id a500_ec_match[] = {
  145. { .compatible = "acer,a500-iconia-ec" },
  146. { }
  147. };
  148. MODULE_DEVICE_TABLE(of, a500_ec_match);
  149. static struct i2c_driver a500_ec_driver = {
  150. .driver = {
  151. .name = "acer-a500-embedded-controller",
  152. .of_match_table = a500_ec_match,
  153. },
  154. .probe_new = a500_ec_probe,
  155. .remove = a500_ec_remove,
  156. };
  157. module_i2c_driver(a500_ec_driver);
  158. MODULE_DESCRIPTION("Acer Iconia Tab A500 Embedded Controller driver");
  159. MODULE_AUTHOR("Dmitry Osipenko <[email protected]>");
  160. MODULE_LICENSE("GPL");