leds-is31fl32xx.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Driver for ISSI IS31FL32xx family of I2C LED controllers
  4. *
  5. * Copyright 2015 Allworx Corp.
  6. *
  7. * Datasheets:
  8. * http://www.issi.com/US/product-analog-fxled-driver.shtml
  9. * http://www.si-en.com/product.asp?parentid=890
  10. */
  11. #include <linux/device.h>
  12. #include <linux/i2c.h>
  13. #include <linux/kernel.h>
  14. #include <linux/leds.h>
  15. #include <linux/module.h>
  16. #include <linux/of.h>
  17. /* Used to indicate a device has no such register */
  18. #define IS31FL32XX_REG_NONE 0xFF
  19. /* Software Shutdown bit in Shutdown Register */
  20. #define IS31FL32XX_SHUTDOWN_SSD_ENABLE 0
  21. #define IS31FL32XX_SHUTDOWN_SSD_DISABLE BIT(0)
  22. /* IS31FL3216 has a number of unique registers */
  23. #define IS31FL3216_CONFIG_REG 0x00
  24. #define IS31FL3216_LIGHTING_EFFECT_REG 0x03
  25. #define IS31FL3216_CHANNEL_CONFIG_REG 0x04
  26. /* Software Shutdown bit in 3216 Config Register */
  27. #define IS31FL3216_CONFIG_SSD_ENABLE BIT(7)
  28. #define IS31FL3216_CONFIG_SSD_DISABLE 0
  29. #define IS31FL32XX_PWM_FREQUENCY_22KHZ 0x01
  30. /* Registers for IS31FL3293 */
  31. #define IS31FL3293_SHUTDOWN_REG 0x01
  32. #define IS31FL3293_SHUTDOWN_SSD_DISABLE BIT(0)
  33. #define IS31FL3293_SHUTDOWN_EN1 BIT(4)
  34. #define IS31FL3293_SHUTDOWN_EN2 BIT(5)
  35. #define IS31FL3293_SHUTDOWN_EN3 BIT(6)
  36. #define IS31FL3293_GCC_REG 0x03
  37. #define IS31FL3293_GCC_LEVEL_MAX 0x3f
  38. #define IS31FL3293_CL_REG 0x10
  39. #define IS31FL3293_COLOR_UPDATE_REG 0x27
  40. #define IS31FL3293_COLOR_UPDATE_MAGIC 0xc5
  41. #define IS31FL3293_RESET_REG 0x3c
  42. #define IS31FL3293_RESET_MAGIC 0xc5
  43. #define IS31FL3293_MAX_MICROAMP 20000
  44. struct is31fl32xx_priv;
  45. struct is31fl32xx_led_data {
  46. struct led_classdev cdev;
  47. u8 channel; /* 1-based, max priv->cdef->channels */
  48. u32 max_microamp;
  49. struct is31fl32xx_priv *priv;
  50. };
  51. struct is31fl32xx_priv {
  52. const struct is31fl32xx_chipdef *cdef;
  53. struct i2c_client *client;
  54. unsigned int num_leds;
  55. struct is31fl32xx_led_data leds[];
  56. };
  57. /**
  58. * struct is31fl32xx_chipdef - chip-specific attributes
  59. * @channels : Number of LED channels
  60. * @shutdown_reg : address of Shutdown register (optional)
  61. * @pwm_update_reg : address of PWM Update register
  62. * @pwm_update_value : value to write to PWM Update register
  63. * @global_control_reg : address of Global Control register (optional)
  64. * @reset_reg : address of Reset register (optional)
  65. * @output_frequency_setting_reg: address of output frequency register (optional)
  66. * @pwm_register_base : address of first PWM register
  67. * @pwm_registers_reversed: : true if PWM registers count down instead of up
  68. * @led_control_register_base : address of first LED control register (optional)
  69. * @enable_bits_per_led_control_register: number of LEDs enable bits in each
  70. * @brightness_steps : number of brightness steps supported by the chip
  71. * @reset_func : pointer to reset function
  72. * @sw_shutdown_func : pointer to software shutdown function
  73. *
  74. * For all optional register addresses, the sentinel value %IS31FL32XX_REG_NONE
  75. * indicates that this chip has no such register.
  76. *
  77. * If non-NULL, @reset_func will be called during probing to set all
  78. * necessary registers to a known initialization state. This is needed
  79. * for chips that do not have a @reset_reg.
  80. *
  81. * @enable_bits_per_led_control_register must be >=1 if
  82. * @led_control_register_base != %IS31FL32XX_REG_NONE.
  83. */
  84. struct is31fl32xx_chipdef {
  85. u8 channels;
  86. u8 shutdown_reg;
  87. u8 pwm_update_reg;
  88. u8 pwm_update_value;
  89. u8 global_control_reg;
  90. u8 reset_reg;
  91. u8 output_frequency_setting_reg;
  92. u8 pwm_register_base;
  93. bool pwm_registers_reversed;
  94. u8 led_control_register_base;
  95. u8 enable_bits_per_led_control_register;
  96. u16 brightness_steps;
  97. int (*reset_func)(struct is31fl32xx_priv *priv);
  98. int (*sw_shutdown_func)(struct is31fl32xx_priv *priv, bool enable);
  99. };
  100. static int is31fl32xx_write(struct is31fl32xx_priv *priv, u8 reg, u8 val)
  101. {
  102. int ret;
  103. dev_dbg(&priv->client->dev, "writing register 0x%02X=0x%02X", reg, val);
  104. ret = i2c_smbus_write_byte_data(priv->client, reg, val);
  105. if (ret) {
  106. dev_err(&priv->client->dev,
  107. "register write to 0x%02X failed (error %d)",
  108. reg, ret);
  109. }
  110. return ret;
  111. }
  112. /*
  113. * Custom reset function for IS31FL3216 because it does not have a RESET
  114. * register the way that the other IS31FL32xx chips do. We don't bother
  115. * writing the GPIO and animation registers, because the registers we
  116. * do write ensure those will have no effect.
  117. */
  118. static int is31fl3216_reset(struct is31fl32xx_priv *priv)
  119. {
  120. unsigned int i;
  121. int ret;
  122. ret = is31fl32xx_write(priv, IS31FL3216_CONFIG_REG,
  123. IS31FL3216_CONFIG_SSD_ENABLE);
  124. if (ret)
  125. return ret;
  126. for (i = 0; i < priv->cdef->channels; i++) {
  127. ret = is31fl32xx_write(priv, priv->cdef->pwm_register_base+i,
  128. 0x00);
  129. if (ret)
  130. return ret;
  131. }
  132. ret = is31fl32xx_write(priv, priv->cdef->pwm_update_reg, 0);
  133. if (ret)
  134. return ret;
  135. ret = is31fl32xx_write(priv, IS31FL3216_LIGHTING_EFFECT_REG, 0x00);
  136. if (ret)
  137. return ret;
  138. ret = is31fl32xx_write(priv, IS31FL3216_CHANNEL_CONFIG_REG, 0x00);
  139. if (ret)
  140. return ret;
  141. return 0;
  142. }
  143. /*
  144. * Custom Software-Shutdown function for IS31FL3216 because it does not have
  145. * a SHUTDOWN register the way that the other IS31FL32xx chips do.
  146. * We don't bother doing a read/modify/write on the CONFIG register because
  147. * we only ever use a value of '0' for the other fields in that register.
  148. */
  149. static int is31fl3216_software_shutdown(struct is31fl32xx_priv *priv,
  150. bool enable)
  151. {
  152. u8 value = enable ? IS31FL3216_CONFIG_SSD_ENABLE :
  153. IS31FL3216_CONFIG_SSD_DISABLE;
  154. return is31fl32xx_write(priv, IS31FL3216_CONFIG_REG, value);
  155. }
  156. /*
  157. * Custom Reset function for IS31FL3293. We need to set the global current limit
  158. * and write to the color update register once.
  159. */
  160. static int is31fl3293_reset(struct is31fl32xx_priv *priv)
  161. {
  162. int i, ret;
  163. ret = is31fl32xx_write(priv, IS31FL3293_RESET_REG,
  164. IS31FL3293_RESET_MAGIC);
  165. if (ret)
  166. return ret;
  167. /* Set the global current limit to maximum */
  168. ret = is31fl32xx_write(priv, IS31FL3293_GCC_REG,
  169. IS31FL3293_GCC_LEVEL_MAX);
  170. if (ret)
  171. return ret;
  172. for (i = 0; i < priv->num_leds; i++) {
  173. struct is31fl32xx_led_data *led_data = &priv->leds[i];
  174. int current_level_reg = IS31FL3293_CL_REG + led_data->channel - 1;
  175. int microamp = max(led_data->max_microamp, IS31FL3293_MAX_MICROAMP);
  176. int current_level = (microamp * 0xff) / IS31FL3293_MAX_MICROAMP;
  177. ret = is31fl32xx_write(priv, current_level_reg, current_level);
  178. if (ret)
  179. return ret;
  180. }
  181. ret = is31fl32xx_write(priv, IS31FL3293_COLOR_UPDATE_REG,
  182. IS31FL3293_COLOR_UPDATE_MAGIC);
  183. if (ret)
  184. return ret;
  185. return 0;
  186. }
  187. /*
  188. * Custom Software-Shutdown function for IS31FL3293 because the SHUTDOWN
  189. * register of this device also has bits to enable the channels.
  190. */
  191. static int is31fl3293_software_shutdown(struct is31fl32xx_priv *priv,
  192. bool enable)
  193. {
  194. u8 value = 0;
  195. if (!enable)
  196. value = IS31FL3293_SHUTDOWN_SSD_DISABLE |
  197. IS31FL3293_SHUTDOWN_EN1 |
  198. IS31FL3293_SHUTDOWN_EN2 |
  199. IS31FL3293_SHUTDOWN_EN3;
  200. return is31fl32xx_write(priv, IS31FL3293_SHUTDOWN_REG, value);
  201. }
  202. /*
  203. * NOTE: A mutex is not needed in this function because:
  204. * - All referenced data is read-only after probe()
  205. * - The I2C core has a mutex on to protect the bus
  206. * - There are no read/modify/write operations
  207. * - Intervening operations between the write of the PWM register
  208. * and the Update register are harmless.
  209. *
  210. * Example:
  211. * PWM_REG_1 write 16
  212. * UPDATE_REG write 0
  213. * PWM_REG_2 write 128
  214. * UPDATE_REG write 0
  215. * vs:
  216. * PWM_REG_1 write 16
  217. * PWM_REG_2 write 128
  218. * UPDATE_REG write 0
  219. * UPDATE_REG write 0
  220. * are equivalent. Poking the Update register merely applies all PWM
  221. * register writes up to that point.
  222. */
  223. static int is31fl32xx_brightness_set(struct led_classdev *led_cdev,
  224. enum led_brightness brightness)
  225. {
  226. const struct is31fl32xx_led_data *led_data =
  227. container_of(led_cdev, struct is31fl32xx_led_data, cdev);
  228. const struct is31fl32xx_chipdef *cdef = led_data->priv->cdef;
  229. u8 pwm_register_offset;
  230. int ret;
  231. dev_dbg(led_cdev->dev, "%s: %d\n", __func__, brightness);
  232. /* NOTE: led_data->channel is 1-based */
  233. if (cdef->pwm_registers_reversed)
  234. pwm_register_offset = cdef->channels - led_data->channel;
  235. else
  236. pwm_register_offset = led_data->channel - 1;
  237. switch (cdef->brightness_steps) {
  238. case 256:
  239. ret = is31fl32xx_write(led_data->priv,
  240. cdef->pwm_register_base + pwm_register_offset,
  241. brightness);
  242. if (ret)
  243. return ret;
  244. break;
  245. case 4096:
  246. /* IS31FL329x devices use two registers to store 12 bits of brightness */
  247. pwm_register_offset *= 2;
  248. ret = is31fl32xx_write(led_data->priv,
  249. cdef->pwm_register_base + pwm_register_offset,
  250. brightness & 0xff);
  251. if (ret)
  252. return ret;
  253. ret = is31fl32xx_write(led_data->priv,
  254. cdef->pwm_register_base + pwm_register_offset + 1,
  255. (brightness >> 8) & 0xf);
  256. if (ret)
  257. return ret;
  258. break;
  259. }
  260. return is31fl32xx_write(led_data->priv, cdef->pwm_update_reg,
  261. cdef->pwm_update_value);
  262. }
  263. static int is31fl32xx_reset_regs(struct is31fl32xx_priv *priv)
  264. {
  265. const struct is31fl32xx_chipdef *cdef = priv->cdef;
  266. int ret;
  267. if (cdef->reset_reg != IS31FL32XX_REG_NONE) {
  268. ret = is31fl32xx_write(priv, cdef->reset_reg, 0);
  269. if (ret)
  270. return ret;
  271. }
  272. if (cdef->reset_func)
  273. return cdef->reset_func(priv);
  274. return 0;
  275. }
  276. static int is31fl32xx_software_shutdown(struct is31fl32xx_priv *priv,
  277. bool enable)
  278. {
  279. const struct is31fl32xx_chipdef *cdef = priv->cdef;
  280. int ret;
  281. if (cdef->shutdown_reg != IS31FL32XX_REG_NONE) {
  282. u8 value = enable ? IS31FL32XX_SHUTDOWN_SSD_ENABLE :
  283. IS31FL32XX_SHUTDOWN_SSD_DISABLE;
  284. ret = is31fl32xx_write(priv, cdef->shutdown_reg, value);
  285. if (ret)
  286. return ret;
  287. }
  288. if (cdef->sw_shutdown_func)
  289. return cdef->sw_shutdown_func(priv, enable);
  290. return 0;
  291. }
  292. static int is31fl32xx_init_regs(struct is31fl32xx_priv *priv)
  293. {
  294. const struct is31fl32xx_chipdef *cdef = priv->cdef;
  295. int ret;
  296. ret = is31fl32xx_reset_regs(priv);
  297. if (ret)
  298. return ret;
  299. /*
  300. * Set enable bit for all channels.
  301. * We will control state with PWM registers alone.
  302. */
  303. if (cdef->led_control_register_base != IS31FL32XX_REG_NONE) {
  304. u8 value =
  305. GENMASK(cdef->enable_bits_per_led_control_register-1, 0);
  306. u8 num_regs = cdef->channels /
  307. cdef->enable_bits_per_led_control_register;
  308. int i;
  309. for (i = 0; i < num_regs; i++) {
  310. ret = is31fl32xx_write(priv,
  311. cdef->led_control_register_base+i,
  312. value);
  313. if (ret)
  314. return ret;
  315. }
  316. }
  317. ret = is31fl32xx_software_shutdown(priv, false);
  318. if (ret)
  319. return ret;
  320. if (cdef->global_control_reg != IS31FL32XX_REG_NONE) {
  321. ret = is31fl32xx_write(priv, cdef->global_control_reg, 0x00);
  322. if (ret)
  323. return ret;
  324. }
  325. return 0;
  326. }
  327. static int is31fl32xx_parse_child_dt(const struct device *dev,
  328. const struct device_node *child,
  329. struct is31fl32xx_led_data *led_data)
  330. {
  331. struct led_classdev *cdev = &led_data->cdev;
  332. int ret = 0;
  333. u32 reg;
  334. ret = of_property_read_u32(child, "reg", &reg);
  335. if (ret || reg < 1 || reg > led_data->priv->cdef->channels) {
  336. dev_err(dev,
  337. "Child node %pOF does not have a valid reg property\n",
  338. child);
  339. return -EINVAL;
  340. }
  341. led_data->channel = reg;
  342. of_property_read_u32(child, "led-max-microamp", &led_data->max_microamp);
  343. cdev->brightness_set_blocking = is31fl32xx_brightness_set;
  344. return 0;
  345. }
  346. static struct is31fl32xx_led_data *is31fl32xx_find_led_data(
  347. struct is31fl32xx_priv *priv,
  348. u8 channel)
  349. {
  350. size_t i;
  351. for (i = 0; i < priv->num_leds; i++) {
  352. if (priv->leds[i].channel == channel)
  353. return &priv->leds[i];
  354. }
  355. return NULL;
  356. }
  357. static int is31fl32xx_parse_dt(struct device *dev,
  358. struct is31fl32xx_priv *priv)
  359. {
  360. const struct is31fl32xx_chipdef *cdef = priv->cdef;
  361. int ret = 0;
  362. if ((cdef->output_frequency_setting_reg != IS31FL32XX_REG_NONE) &&
  363. of_property_read_bool(dev_of_node(dev), "issi,22khz-pwm")) {
  364. ret = is31fl32xx_write(priv, cdef->output_frequency_setting_reg,
  365. IS31FL32XX_PWM_FREQUENCY_22KHZ);
  366. if (ret) {
  367. dev_err(dev, "Failed to write output PWM frequency register\n");
  368. return ret;
  369. }
  370. }
  371. for_each_available_child_of_node_scoped(dev_of_node(dev), child) {
  372. struct led_init_data init_data = {};
  373. struct is31fl32xx_led_data *led_data =
  374. &priv->leds[priv->num_leds];
  375. const struct is31fl32xx_led_data *other_led_data;
  376. led_data->priv = priv;
  377. led_data->cdev.max_brightness = priv->cdef->brightness_steps - 1;
  378. ret = is31fl32xx_parse_child_dt(dev, child, led_data);
  379. if (ret)
  380. return ret;
  381. /* Detect if channel is already in use by another child */
  382. other_led_data = is31fl32xx_find_led_data(priv,
  383. led_data->channel);
  384. if (other_led_data) {
  385. dev_err(dev,
  386. "Node %pOF 'reg' conflicts with another LED\n",
  387. child);
  388. return -EINVAL;
  389. }
  390. init_data.fwnode = of_fwnode_handle(child);
  391. ret = devm_led_classdev_register_ext(dev, &led_data->cdev,
  392. &init_data);
  393. if (ret) {
  394. dev_err(dev, "Failed to register LED for %pOF: %d\n",
  395. child, ret);
  396. return ret;
  397. }
  398. priv->num_leds++;
  399. }
  400. return 0;
  401. }
  402. static const struct is31fl32xx_chipdef is31fl3236_cdef = {
  403. .channels = 36,
  404. .shutdown_reg = 0x00,
  405. .pwm_update_reg = 0x25,
  406. .global_control_reg = 0x4a,
  407. .reset_reg = 0x4f,
  408. .output_frequency_setting_reg = IS31FL32XX_REG_NONE,
  409. .pwm_register_base = 0x01,
  410. .led_control_register_base = 0x26,
  411. .enable_bits_per_led_control_register = 1,
  412. };
  413. static const struct is31fl32xx_chipdef is31fl3236a_cdef = {
  414. .channels = 36,
  415. .shutdown_reg = 0x00,
  416. .pwm_update_reg = 0x25,
  417. .global_control_reg = 0x4a,
  418. .reset_reg = 0x4f,
  419. .output_frequency_setting_reg = 0x4b,
  420. .pwm_register_base = 0x01,
  421. .led_control_register_base = 0x26,
  422. .enable_bits_per_led_control_register = 1,
  423. .brightness_steps = 256,
  424. };
  425. static const struct is31fl32xx_chipdef is31fl3235_cdef = {
  426. .channels = 28,
  427. .shutdown_reg = 0x00,
  428. .pwm_update_reg = 0x25,
  429. .global_control_reg = 0x4a,
  430. .reset_reg = 0x4f,
  431. .output_frequency_setting_reg = IS31FL32XX_REG_NONE,
  432. .pwm_register_base = 0x05,
  433. .led_control_register_base = 0x2a,
  434. .enable_bits_per_led_control_register = 1,
  435. .brightness_steps = 256,
  436. };
  437. static const struct is31fl32xx_chipdef is31fl3218_cdef = {
  438. .channels = 18,
  439. .shutdown_reg = 0x00,
  440. .pwm_update_reg = 0x16,
  441. .global_control_reg = IS31FL32XX_REG_NONE,
  442. .reset_reg = 0x17,
  443. .output_frequency_setting_reg = IS31FL32XX_REG_NONE,
  444. .pwm_register_base = 0x01,
  445. .led_control_register_base = 0x13,
  446. .enable_bits_per_led_control_register = 6,
  447. .brightness_steps = 256,
  448. };
  449. static const struct is31fl32xx_chipdef is31fl3216_cdef = {
  450. .channels = 16,
  451. .shutdown_reg = IS31FL32XX_REG_NONE,
  452. .pwm_update_reg = 0xB0,
  453. .global_control_reg = IS31FL32XX_REG_NONE,
  454. .reset_reg = IS31FL32XX_REG_NONE,
  455. .output_frequency_setting_reg = IS31FL32XX_REG_NONE,
  456. .pwm_register_base = 0x10,
  457. .pwm_registers_reversed = true,
  458. .led_control_register_base = 0x01,
  459. .enable_bits_per_led_control_register = 8,
  460. .reset_func = is31fl3216_reset,
  461. .sw_shutdown_func = is31fl3216_software_shutdown,
  462. .brightness_steps = 256,
  463. };
  464. static const struct is31fl32xx_chipdef is31fl3293_cdef = {
  465. .channels = 3,
  466. .shutdown_reg = IS31FL32XX_REG_NONE,
  467. .pwm_update_reg = 0x28,
  468. .pwm_update_value = 0xc5,
  469. .global_control_reg = IS31FL32XX_REG_NONE,
  470. .reset_reg = IS31FL32XX_REG_NONE,
  471. .pwm_register_base = 0x19,
  472. .led_control_register_base = IS31FL32XX_REG_NONE,
  473. .brightness_steps = 4096,
  474. .reset_func = is31fl3293_reset,
  475. .sw_shutdown_func = is31fl3293_software_shutdown,
  476. };
  477. static const struct of_device_id of_is31fl32xx_match[] = {
  478. { .compatible = "issi,is31fl3293", .data = &is31fl3293_cdef, },
  479. { .compatible = "issi,is31fl3236", .data = &is31fl3236_cdef, },
  480. { .compatible = "issi,is31fl3236a", .data = &is31fl3236a_cdef, },
  481. { .compatible = "issi,is31fl3235", .data = &is31fl3235_cdef, },
  482. { .compatible = "issi,is31fl3218", .data = &is31fl3218_cdef, },
  483. { .compatible = "si-en,sn3218", .data = &is31fl3218_cdef, },
  484. { .compatible = "issi,is31fl3216", .data = &is31fl3216_cdef, },
  485. { .compatible = "si-en,sn3216", .data = &is31fl3216_cdef, },
  486. {},
  487. };
  488. MODULE_DEVICE_TABLE(of, of_is31fl32xx_match);
  489. static int is31fl32xx_probe(struct i2c_client *client)
  490. {
  491. const struct is31fl32xx_chipdef *cdef;
  492. struct device *dev = &client->dev;
  493. struct is31fl32xx_priv *priv;
  494. int count;
  495. int ret = 0;
  496. cdef = device_get_match_data(dev);
  497. count = of_get_available_child_count(dev_of_node(dev));
  498. if (!count)
  499. return -EINVAL;
  500. priv = devm_kzalloc(dev, struct_size(priv, leds, count),
  501. GFP_KERNEL);
  502. if (!priv)
  503. return -ENOMEM;
  504. priv->client = client;
  505. priv->cdef = cdef;
  506. i2c_set_clientdata(client, priv);
  507. ret = is31fl32xx_parse_dt(dev, priv);
  508. if (ret)
  509. return ret;
  510. ret = is31fl32xx_init_regs(priv);
  511. if (ret)
  512. return ret;
  513. return 0;
  514. }
  515. static void is31fl32xx_remove(struct i2c_client *client)
  516. {
  517. struct is31fl32xx_priv *priv = i2c_get_clientdata(client);
  518. int ret;
  519. ret = is31fl32xx_reset_regs(priv);
  520. if (ret)
  521. dev_err(&client->dev, "Failed to reset registers on removal (%pe)\n",
  522. ERR_PTR(ret));
  523. }
  524. /*
  525. * i2c-core (and modalias) requires that id_table be properly filled,
  526. * even though it is not used for DeviceTree based instantiation.
  527. */
  528. static const struct i2c_device_id is31fl32xx_id[] = {
  529. { "is31fl3293" },
  530. { "is31fl3236" },
  531. { "is31fl3236a" },
  532. { "is31fl3235" },
  533. { "is31fl3218" },
  534. { "sn3218" },
  535. { "is31fl3216" },
  536. { "sn3216" },
  537. {},
  538. };
  539. MODULE_DEVICE_TABLE(i2c, is31fl32xx_id);
  540. static struct i2c_driver is31fl32xx_driver = {
  541. .driver = {
  542. .name = "is31fl32xx",
  543. .of_match_table = of_is31fl32xx_match,
  544. },
  545. .probe = is31fl32xx_probe,
  546. .remove = is31fl32xx_remove,
  547. .id_table = is31fl32xx_id,
  548. };
  549. module_i2c_driver(is31fl32xx_driver);
  550. MODULE_AUTHOR("David Rivshin <drivshin@allworx.com>");
  551. MODULE_DESCRIPTION("ISSI IS31FL32xx LED driver");
  552. MODULE_LICENSE("GPL v2");