lm3533-core.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * lm3533-core.c -- LM3533 Core
  4. *
  5. * Copyright (C) 2011-2012 Texas Instruments
  6. *
  7. * Author: Johan Hovold <[email protected]>
  8. */
  9. #include <linux/module.h>
  10. #include <linux/init.h>
  11. #include <linux/kernel.h>
  12. #include <linux/err.h>
  13. #include <linux/gpio.h>
  14. #include <linux/i2c.h>
  15. #include <linux/mfd/core.h>
  16. #include <linux/regmap.h>
  17. #include <linux/seq_file.h>
  18. #include <linux/slab.h>
  19. #include <linux/uaccess.h>
  20. #include <linux/mfd/lm3533.h>
  21. #define LM3533_BOOST_OVP_MASK 0x06
  22. #define LM3533_BOOST_OVP_SHIFT 1
  23. #define LM3533_BOOST_FREQ_MASK 0x01
  24. #define LM3533_BOOST_FREQ_SHIFT 0
  25. #define LM3533_BL_ID_MASK 1
  26. #define LM3533_LED_ID_MASK 3
  27. #define LM3533_BL_ID_MAX 1
  28. #define LM3533_LED_ID_MAX 3
  29. #define LM3533_HVLED_ID_MAX 2
  30. #define LM3533_LVLED_ID_MAX 5
  31. #define LM3533_REG_OUTPUT_CONF1 0x10
  32. #define LM3533_REG_OUTPUT_CONF2 0x11
  33. #define LM3533_REG_BOOST_PWM 0x2c
  34. #define LM3533_REG_MAX 0xb2
  35. static struct mfd_cell lm3533_als_devs[] = {
  36. {
  37. .name = "lm3533-als",
  38. .id = -1,
  39. },
  40. };
  41. static struct mfd_cell lm3533_bl_devs[] = {
  42. {
  43. .name = "lm3533-backlight",
  44. .id = 0,
  45. },
  46. {
  47. .name = "lm3533-backlight",
  48. .id = 1,
  49. },
  50. };
  51. static struct mfd_cell lm3533_led_devs[] = {
  52. {
  53. .name = "lm3533-leds",
  54. .id = 0,
  55. },
  56. {
  57. .name = "lm3533-leds",
  58. .id = 1,
  59. },
  60. {
  61. .name = "lm3533-leds",
  62. .id = 2,
  63. },
  64. {
  65. .name = "lm3533-leds",
  66. .id = 3,
  67. },
  68. };
  69. int lm3533_read(struct lm3533 *lm3533, u8 reg, u8 *val)
  70. {
  71. int tmp;
  72. int ret;
  73. ret = regmap_read(lm3533->regmap, reg, &tmp);
  74. if (ret < 0) {
  75. dev_err(lm3533->dev, "failed to read register %02x: %d\n",
  76. reg, ret);
  77. return ret;
  78. }
  79. *val = tmp;
  80. dev_dbg(lm3533->dev, "read [%02x]: %02x\n", reg, *val);
  81. return ret;
  82. }
  83. EXPORT_SYMBOL_GPL(lm3533_read);
  84. int lm3533_write(struct lm3533 *lm3533, u8 reg, u8 val)
  85. {
  86. int ret;
  87. dev_dbg(lm3533->dev, "write [%02x]: %02x\n", reg, val);
  88. ret = regmap_write(lm3533->regmap, reg, val);
  89. if (ret < 0) {
  90. dev_err(lm3533->dev, "failed to write register %02x: %d\n",
  91. reg, ret);
  92. }
  93. return ret;
  94. }
  95. EXPORT_SYMBOL_GPL(lm3533_write);
  96. int lm3533_update(struct lm3533 *lm3533, u8 reg, u8 val, u8 mask)
  97. {
  98. int ret;
  99. dev_dbg(lm3533->dev, "update [%02x]: %02x/%02x\n", reg, val, mask);
  100. ret = regmap_update_bits(lm3533->regmap, reg, mask, val);
  101. if (ret < 0) {
  102. dev_err(lm3533->dev, "failed to update register %02x: %d\n",
  103. reg, ret);
  104. }
  105. return ret;
  106. }
  107. EXPORT_SYMBOL_GPL(lm3533_update);
  108. static int lm3533_set_boost_freq(struct lm3533 *lm3533,
  109. enum lm3533_boost_freq freq)
  110. {
  111. int ret;
  112. ret = lm3533_update(lm3533, LM3533_REG_BOOST_PWM,
  113. freq << LM3533_BOOST_FREQ_SHIFT,
  114. LM3533_BOOST_FREQ_MASK);
  115. if (ret)
  116. dev_err(lm3533->dev, "failed to set boost frequency\n");
  117. return ret;
  118. }
  119. static int lm3533_set_boost_ovp(struct lm3533 *lm3533,
  120. enum lm3533_boost_ovp ovp)
  121. {
  122. int ret;
  123. ret = lm3533_update(lm3533, LM3533_REG_BOOST_PWM,
  124. ovp << LM3533_BOOST_OVP_SHIFT,
  125. LM3533_BOOST_OVP_MASK);
  126. if (ret)
  127. dev_err(lm3533->dev, "failed to set boost ovp\n");
  128. return ret;
  129. }
  130. /*
  131. * HVLED output config -- output hvled controlled by backlight bl
  132. */
  133. static int lm3533_set_hvled_config(struct lm3533 *lm3533, u8 hvled, u8 bl)
  134. {
  135. u8 val;
  136. u8 mask;
  137. int shift;
  138. int ret;
  139. if (hvled == 0 || hvled > LM3533_HVLED_ID_MAX)
  140. return -EINVAL;
  141. if (bl > LM3533_BL_ID_MAX)
  142. return -EINVAL;
  143. shift = hvled - 1;
  144. mask = LM3533_BL_ID_MASK << shift;
  145. val = bl << shift;
  146. ret = lm3533_update(lm3533, LM3533_REG_OUTPUT_CONF1, val, mask);
  147. if (ret)
  148. dev_err(lm3533->dev, "failed to set hvled config\n");
  149. return ret;
  150. }
  151. /*
  152. * LVLED output config -- output lvled controlled by LED led
  153. */
  154. static int lm3533_set_lvled_config(struct lm3533 *lm3533, u8 lvled, u8 led)
  155. {
  156. u8 reg;
  157. u8 val;
  158. u8 mask;
  159. int shift;
  160. int ret;
  161. if (lvled == 0 || lvled > LM3533_LVLED_ID_MAX)
  162. return -EINVAL;
  163. if (led > LM3533_LED_ID_MAX)
  164. return -EINVAL;
  165. if (lvled < 4) {
  166. reg = LM3533_REG_OUTPUT_CONF1;
  167. shift = 2 * lvled;
  168. } else {
  169. reg = LM3533_REG_OUTPUT_CONF2;
  170. shift = 2 * (lvled - 4);
  171. }
  172. mask = LM3533_LED_ID_MASK << shift;
  173. val = led << shift;
  174. ret = lm3533_update(lm3533, reg, val, mask);
  175. if (ret)
  176. dev_err(lm3533->dev, "failed to set lvled config\n");
  177. return ret;
  178. }
  179. static void lm3533_enable(struct lm3533 *lm3533)
  180. {
  181. if (gpio_is_valid(lm3533->gpio_hwen))
  182. gpio_set_value(lm3533->gpio_hwen, 1);
  183. }
  184. static void lm3533_disable(struct lm3533 *lm3533)
  185. {
  186. if (gpio_is_valid(lm3533->gpio_hwen))
  187. gpio_set_value(lm3533->gpio_hwen, 0);
  188. }
  189. enum lm3533_attribute_type {
  190. LM3533_ATTR_TYPE_BACKLIGHT,
  191. LM3533_ATTR_TYPE_LED,
  192. };
  193. struct lm3533_device_attribute {
  194. struct device_attribute dev_attr;
  195. enum lm3533_attribute_type type;
  196. union {
  197. struct {
  198. u8 id;
  199. } output;
  200. } u;
  201. };
  202. #define to_lm3533_dev_attr(_attr) \
  203. container_of(_attr, struct lm3533_device_attribute, dev_attr)
  204. static ssize_t show_output(struct device *dev,
  205. struct device_attribute *attr, char *buf)
  206. {
  207. struct lm3533 *lm3533 = dev_get_drvdata(dev);
  208. struct lm3533_device_attribute *lattr = to_lm3533_dev_attr(attr);
  209. int id = lattr->u.output.id;
  210. u8 reg;
  211. u8 val;
  212. u8 mask;
  213. int shift;
  214. int ret;
  215. if (lattr->type == LM3533_ATTR_TYPE_BACKLIGHT) {
  216. reg = LM3533_REG_OUTPUT_CONF1;
  217. shift = id - 1;
  218. mask = LM3533_BL_ID_MASK << shift;
  219. } else {
  220. if (id < 4) {
  221. reg = LM3533_REG_OUTPUT_CONF1;
  222. shift = 2 * id;
  223. } else {
  224. reg = LM3533_REG_OUTPUT_CONF2;
  225. shift = 2 * (id - 4);
  226. }
  227. mask = LM3533_LED_ID_MASK << shift;
  228. }
  229. ret = lm3533_read(lm3533, reg, &val);
  230. if (ret)
  231. return ret;
  232. val = (val & mask) >> shift;
  233. return scnprintf(buf, PAGE_SIZE, "%u\n", val);
  234. }
  235. static ssize_t store_output(struct device *dev,
  236. struct device_attribute *attr,
  237. const char *buf, size_t len)
  238. {
  239. struct lm3533 *lm3533 = dev_get_drvdata(dev);
  240. struct lm3533_device_attribute *lattr = to_lm3533_dev_attr(attr);
  241. int id = lattr->u.output.id;
  242. u8 val;
  243. int ret;
  244. if (kstrtou8(buf, 0, &val))
  245. return -EINVAL;
  246. if (lattr->type == LM3533_ATTR_TYPE_BACKLIGHT)
  247. ret = lm3533_set_hvled_config(lm3533, id, val);
  248. else
  249. ret = lm3533_set_lvled_config(lm3533, id, val);
  250. if (ret)
  251. return ret;
  252. return len;
  253. }
  254. #define LM3533_OUTPUT_ATTR(_name, _mode, _show, _store, _type, _id) \
  255. struct lm3533_device_attribute lm3533_dev_attr_##_name = \
  256. { .dev_attr = __ATTR(_name, _mode, _show, _store), \
  257. .type = _type, \
  258. .u.output = { .id = _id }, }
  259. #define LM3533_OUTPUT_ATTR_RW(_name, _type, _id) \
  260. LM3533_OUTPUT_ATTR(output_##_name, S_IRUGO | S_IWUSR, \
  261. show_output, store_output, _type, _id)
  262. #define LM3533_OUTPUT_HVLED_ATTR_RW(_nr) \
  263. LM3533_OUTPUT_ATTR_RW(hvled##_nr, LM3533_ATTR_TYPE_BACKLIGHT, _nr)
  264. #define LM3533_OUTPUT_LVLED_ATTR_RW(_nr) \
  265. LM3533_OUTPUT_ATTR_RW(lvled##_nr, LM3533_ATTR_TYPE_LED, _nr)
  266. /*
  267. * Output config:
  268. *
  269. * output_hvled<nr> 0-1
  270. * output_lvled<nr> 0-3
  271. */
  272. static LM3533_OUTPUT_HVLED_ATTR_RW(1);
  273. static LM3533_OUTPUT_HVLED_ATTR_RW(2);
  274. static LM3533_OUTPUT_LVLED_ATTR_RW(1);
  275. static LM3533_OUTPUT_LVLED_ATTR_RW(2);
  276. static LM3533_OUTPUT_LVLED_ATTR_RW(3);
  277. static LM3533_OUTPUT_LVLED_ATTR_RW(4);
  278. static LM3533_OUTPUT_LVLED_ATTR_RW(5);
  279. static struct attribute *lm3533_attributes[] = {
  280. &lm3533_dev_attr_output_hvled1.dev_attr.attr,
  281. &lm3533_dev_attr_output_hvled2.dev_attr.attr,
  282. &lm3533_dev_attr_output_lvled1.dev_attr.attr,
  283. &lm3533_dev_attr_output_lvled2.dev_attr.attr,
  284. &lm3533_dev_attr_output_lvled3.dev_attr.attr,
  285. &lm3533_dev_attr_output_lvled4.dev_attr.attr,
  286. &lm3533_dev_attr_output_lvled5.dev_attr.attr,
  287. NULL,
  288. };
  289. #define to_dev_attr(_attr) \
  290. container_of(_attr, struct device_attribute, attr)
  291. static umode_t lm3533_attr_is_visible(struct kobject *kobj,
  292. struct attribute *attr, int n)
  293. {
  294. struct device *dev = kobj_to_dev(kobj);
  295. struct lm3533 *lm3533 = dev_get_drvdata(dev);
  296. struct device_attribute *dattr = to_dev_attr(attr);
  297. struct lm3533_device_attribute *lattr = to_lm3533_dev_attr(dattr);
  298. enum lm3533_attribute_type type = lattr->type;
  299. umode_t mode = attr->mode;
  300. if (!lm3533->have_backlights && type == LM3533_ATTR_TYPE_BACKLIGHT)
  301. mode = 0;
  302. else if (!lm3533->have_leds && type == LM3533_ATTR_TYPE_LED)
  303. mode = 0;
  304. return mode;
  305. };
  306. static struct attribute_group lm3533_attribute_group = {
  307. .is_visible = lm3533_attr_is_visible,
  308. .attrs = lm3533_attributes
  309. };
  310. static int lm3533_device_als_init(struct lm3533 *lm3533)
  311. {
  312. struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
  313. int ret;
  314. if (!pdata->als)
  315. return 0;
  316. lm3533_als_devs[0].platform_data = pdata->als;
  317. lm3533_als_devs[0].pdata_size = sizeof(*pdata->als);
  318. ret = mfd_add_devices(lm3533->dev, 0, lm3533_als_devs, 1, NULL,
  319. 0, NULL);
  320. if (ret) {
  321. dev_err(lm3533->dev, "failed to add ALS device\n");
  322. return ret;
  323. }
  324. lm3533->have_als = 1;
  325. return 0;
  326. }
  327. static int lm3533_device_bl_init(struct lm3533 *lm3533)
  328. {
  329. struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
  330. int i;
  331. int ret;
  332. if (!pdata->backlights || pdata->num_backlights == 0)
  333. return 0;
  334. if (pdata->num_backlights > ARRAY_SIZE(lm3533_bl_devs))
  335. pdata->num_backlights = ARRAY_SIZE(lm3533_bl_devs);
  336. for (i = 0; i < pdata->num_backlights; ++i) {
  337. lm3533_bl_devs[i].platform_data = &pdata->backlights[i];
  338. lm3533_bl_devs[i].pdata_size = sizeof(pdata->backlights[i]);
  339. }
  340. ret = mfd_add_devices(lm3533->dev, 0, lm3533_bl_devs,
  341. pdata->num_backlights, NULL, 0, NULL);
  342. if (ret) {
  343. dev_err(lm3533->dev, "failed to add backlight devices\n");
  344. return ret;
  345. }
  346. lm3533->have_backlights = 1;
  347. return 0;
  348. }
  349. static int lm3533_device_led_init(struct lm3533 *lm3533)
  350. {
  351. struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
  352. int i;
  353. int ret;
  354. if (!pdata->leds || pdata->num_leds == 0)
  355. return 0;
  356. if (pdata->num_leds > ARRAY_SIZE(lm3533_led_devs))
  357. pdata->num_leds = ARRAY_SIZE(lm3533_led_devs);
  358. for (i = 0; i < pdata->num_leds; ++i) {
  359. lm3533_led_devs[i].platform_data = &pdata->leds[i];
  360. lm3533_led_devs[i].pdata_size = sizeof(pdata->leds[i]);
  361. }
  362. ret = mfd_add_devices(lm3533->dev, 0, lm3533_led_devs,
  363. pdata->num_leds, NULL, 0, NULL);
  364. if (ret) {
  365. dev_err(lm3533->dev, "failed to add LED devices\n");
  366. return ret;
  367. }
  368. lm3533->have_leds = 1;
  369. return 0;
  370. }
  371. static int lm3533_device_setup(struct lm3533 *lm3533,
  372. struct lm3533_platform_data *pdata)
  373. {
  374. int ret;
  375. ret = lm3533_set_boost_freq(lm3533, pdata->boost_freq);
  376. if (ret)
  377. return ret;
  378. return lm3533_set_boost_ovp(lm3533, pdata->boost_ovp);
  379. }
  380. static int lm3533_device_init(struct lm3533 *lm3533)
  381. {
  382. struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
  383. int ret;
  384. dev_dbg(lm3533->dev, "%s\n", __func__);
  385. if (!pdata) {
  386. dev_err(lm3533->dev, "no platform data\n");
  387. return -EINVAL;
  388. }
  389. lm3533->gpio_hwen = pdata->gpio_hwen;
  390. dev_set_drvdata(lm3533->dev, lm3533);
  391. if (gpio_is_valid(lm3533->gpio_hwen)) {
  392. ret = devm_gpio_request_one(lm3533->dev, lm3533->gpio_hwen,
  393. GPIOF_OUT_INIT_LOW, "lm3533-hwen");
  394. if (ret < 0) {
  395. dev_err(lm3533->dev,
  396. "failed to request HWEN GPIO %d\n",
  397. lm3533->gpio_hwen);
  398. return ret;
  399. }
  400. }
  401. lm3533_enable(lm3533);
  402. ret = lm3533_device_setup(lm3533, pdata);
  403. if (ret)
  404. goto err_disable;
  405. lm3533_device_als_init(lm3533);
  406. lm3533_device_bl_init(lm3533);
  407. lm3533_device_led_init(lm3533);
  408. ret = sysfs_create_group(&lm3533->dev->kobj, &lm3533_attribute_group);
  409. if (ret < 0) {
  410. dev_err(lm3533->dev, "failed to create sysfs attributes\n");
  411. goto err_unregister;
  412. }
  413. return 0;
  414. err_unregister:
  415. mfd_remove_devices(lm3533->dev);
  416. err_disable:
  417. lm3533_disable(lm3533);
  418. return ret;
  419. }
  420. static void lm3533_device_exit(struct lm3533 *lm3533)
  421. {
  422. dev_dbg(lm3533->dev, "%s\n", __func__);
  423. sysfs_remove_group(&lm3533->dev->kobj, &lm3533_attribute_group);
  424. mfd_remove_devices(lm3533->dev);
  425. lm3533_disable(lm3533);
  426. }
  427. static bool lm3533_readable_register(struct device *dev, unsigned int reg)
  428. {
  429. switch (reg) {
  430. case 0x10 ... 0x2c:
  431. case 0x30 ... 0x38:
  432. case 0x40 ... 0x45:
  433. case 0x50 ... 0x57:
  434. case 0x60 ... 0x6e:
  435. case 0x70 ... 0x75:
  436. case 0x80 ... 0x85:
  437. case 0x90 ... 0x95:
  438. case 0xa0 ... 0xa5:
  439. case 0xb0 ... 0xb2:
  440. return true;
  441. default:
  442. return false;
  443. }
  444. }
  445. static bool lm3533_volatile_register(struct device *dev, unsigned int reg)
  446. {
  447. switch (reg) {
  448. case 0x34 ... 0x36: /* zone */
  449. case 0x37 ... 0x38: /* adc */
  450. case 0xb0 ... 0xb1: /* fault */
  451. return true;
  452. default:
  453. return false;
  454. }
  455. }
  456. static bool lm3533_precious_register(struct device *dev, unsigned int reg)
  457. {
  458. switch (reg) {
  459. case 0x34: /* zone */
  460. return true;
  461. default:
  462. return false;
  463. }
  464. }
  465. static const struct regmap_config regmap_config = {
  466. .reg_bits = 8,
  467. .val_bits = 8,
  468. .max_register = LM3533_REG_MAX,
  469. .readable_reg = lm3533_readable_register,
  470. .volatile_reg = lm3533_volatile_register,
  471. .precious_reg = lm3533_precious_register,
  472. };
  473. static int lm3533_i2c_probe(struct i2c_client *i2c,
  474. const struct i2c_device_id *id)
  475. {
  476. struct lm3533 *lm3533;
  477. dev_dbg(&i2c->dev, "%s\n", __func__);
  478. lm3533 = devm_kzalloc(&i2c->dev, sizeof(*lm3533), GFP_KERNEL);
  479. if (!lm3533)
  480. return -ENOMEM;
  481. i2c_set_clientdata(i2c, lm3533);
  482. lm3533->regmap = devm_regmap_init_i2c(i2c, &regmap_config);
  483. if (IS_ERR(lm3533->regmap))
  484. return PTR_ERR(lm3533->regmap);
  485. lm3533->dev = &i2c->dev;
  486. lm3533->irq = i2c->irq;
  487. return lm3533_device_init(lm3533);
  488. }
  489. static void lm3533_i2c_remove(struct i2c_client *i2c)
  490. {
  491. struct lm3533 *lm3533 = i2c_get_clientdata(i2c);
  492. dev_dbg(&i2c->dev, "%s\n", __func__);
  493. lm3533_device_exit(lm3533);
  494. }
  495. static const struct i2c_device_id lm3533_i2c_ids[] = {
  496. { "lm3533", 0 },
  497. { },
  498. };
  499. MODULE_DEVICE_TABLE(i2c, lm3533_i2c_ids);
  500. static struct i2c_driver lm3533_i2c_driver = {
  501. .driver = {
  502. .name = "lm3533",
  503. },
  504. .id_table = lm3533_i2c_ids,
  505. .probe = lm3533_i2c_probe,
  506. .remove = lm3533_i2c_remove,
  507. };
  508. static int __init lm3533_i2c_init(void)
  509. {
  510. return i2c_add_driver(&lm3533_i2c_driver);
  511. }
  512. subsys_initcall(lm3533_i2c_init);
  513. static void __exit lm3533_i2c_exit(void)
  514. {
  515. i2c_del_driver(&lm3533_i2c_driver);
  516. }
  517. module_exit(lm3533_i2c_exit);
  518. MODULE_AUTHOR("Johan Hovold <[email protected]>");
  519. MODULE_DESCRIPTION("LM3533 Core");
  520. MODULE_LICENSE("GPL");