rk808.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. /*
  2. * MFD core driver for Rockchip RK808/RK818
  3. *
  4. * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
  5. *
  6. * Author: Chris Zhong <zyw@rock-chips.com>
  7. * Author: Zhang Qing <zhangqing@rock-chips.com>
  8. *
  9. * Copyright (C) 2016 PHYTEC Messtechnik GmbH
  10. *
  11. * Author: Wadim Egorov <w.egorov@phytec.de>
  12. *
  13. * This program is free software; you can redistribute it and/or modify it
  14. * under the terms and conditions of the GNU General Public License,
  15. * version 2, as published by the Free Software Foundation.
  16. *
  17. * This program is distributed in the hope it will be useful, but WITHOUT
  18. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  19. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  20. * more details.
  21. */
  22. #include <linux/i2c.h>
  23. #include <linux/interrupt.h>
  24. #include <linux/mfd/rk808.h>
  25. #include <linux/mfd/core.h>
  26. #include <linux/module.h>
  27. #include <linux/of_device.h>
  28. #include <linux/regmap.h>
  29. struct rk808_reg_data {
  30. int addr;
  31. int mask;
  32. int value;
  33. };
  34. static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
  35. {
  36. /*
  37. * Notes:
  38. * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
  39. * we don't use that feature. It's better to cache.
  40. * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since
  41. * bits are cleared in case when we shutoff anyway, but better safe.
  42. */
  43. switch (reg) {
  44. case RK808_SECONDS_REG ... RK808_WEEKS_REG:
  45. case RK808_RTC_STATUS_REG:
  46. case RK808_VB_MON_REG:
  47. case RK808_THERMAL_REG:
  48. case RK808_DCDC_UV_STS_REG:
  49. case RK808_LDO_UV_STS_REG:
  50. case RK808_DCDC_PG_REG:
  51. case RK808_LDO_PG_REG:
  52. case RK808_DEVCTRL_REG:
  53. case RK808_INT_STS_REG1:
  54. case RK808_INT_STS_REG2:
  55. return true;
  56. }
  57. return false;
  58. }
  59. static const struct regmap_config rk818_regmap_config = {
  60. .reg_bits = 8,
  61. .val_bits = 8,
  62. .max_register = RK818_USB_CTRL_REG,
  63. .cache_type = REGCACHE_RBTREE,
  64. .volatile_reg = rk808_is_volatile_reg,
  65. };
  66. static const struct regmap_config rk805_regmap_config = {
  67. .reg_bits = 8,
  68. .val_bits = 8,
  69. .max_register = RK805_OFF_SOURCE_REG,
  70. .cache_type = REGCACHE_RBTREE,
  71. .volatile_reg = rk808_is_volatile_reg,
  72. };
  73. static const struct regmap_config rk808_regmap_config = {
  74. .reg_bits = 8,
  75. .val_bits = 8,
  76. .max_register = RK808_IO_POL_REG,
  77. .cache_type = REGCACHE_RBTREE,
  78. .volatile_reg = rk808_is_volatile_reg,
  79. };
  80. static struct resource rtc_resources[] = {
  81. {
  82. .start = RK808_IRQ_RTC_ALARM,
  83. .end = RK808_IRQ_RTC_ALARM,
  84. .flags = IORESOURCE_IRQ,
  85. }
  86. };
  87. static struct resource rk805_key_resources[] = {
  88. {
  89. .start = RK805_IRQ_PWRON_FALL,
  90. .end = RK805_IRQ_PWRON_FALL,
  91. .flags = IORESOURCE_IRQ,
  92. },
  93. {
  94. .start = RK805_IRQ_PWRON_RISE,
  95. .end = RK805_IRQ_PWRON_RISE,
  96. .flags = IORESOURCE_IRQ,
  97. }
  98. };
  99. static const struct mfd_cell rk805s[] = {
  100. { .name = "rk808-clkout", },
  101. { .name = "rk808-regulator", },
  102. { .name = "rk805-pinctrl", },
  103. {
  104. .name = "rk808-rtc",
  105. .num_resources = ARRAY_SIZE(rtc_resources),
  106. .resources = &rtc_resources[0],
  107. },
  108. { .name = "rk805-pwrkey",
  109. .num_resources = ARRAY_SIZE(rk805_key_resources),
  110. .resources = &rk805_key_resources[0],
  111. },
  112. };
  113. static const struct mfd_cell rk808s[] = {
  114. { .name = "rk808-clkout", },
  115. { .name = "rk808-regulator", },
  116. {
  117. .name = "rk808-rtc",
  118. .num_resources = ARRAY_SIZE(rtc_resources),
  119. .resources = rtc_resources,
  120. },
  121. };
  122. static const struct mfd_cell rk818s[] = {
  123. { .name = "rk808-clkout", },
  124. { .name = "rk808-regulator", },
  125. {
  126. .name = "rk808-rtc",
  127. .num_resources = ARRAY_SIZE(rtc_resources),
  128. .resources = rtc_resources,
  129. },
  130. };
  131. static const struct rk808_reg_data rk805_pre_init_reg[] = {
  132. {RK805_BUCK1_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK,
  133. RK805_BUCK1_2_ILMAX_4000MA},
  134. {RK805_BUCK2_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK,
  135. RK805_BUCK1_2_ILMAX_4000MA},
  136. {RK805_BUCK3_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK,
  137. RK805_BUCK3_ILMAX_3000MA},
  138. {RK805_BUCK4_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK,
  139. RK805_BUCK4_ILMAX_3500MA},
  140. {RK805_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_400MA},
  141. {RK805_GPIO_IO_POL_REG, SLP_SD_MSK, SLEEP_FUN},
  142. {RK805_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP115C},
  143. };
  144. static const struct rk808_reg_data rk808_pre_init_reg[] = {
  145. { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA },
  146. { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA },
  147. { RK808_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA },
  148. { RK808_BUCK1_CONFIG_REG, BUCK1_RATE_MASK, BUCK_ILMIN_200MA },
  149. { RK808_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_200MA },
  150. { RK808_DCDC_UV_ACT_REG, BUCK_UV_ACT_MASK, BUCK_UV_ACT_DISABLE},
  151. { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT |
  152. VB_LO_SEL_3500MV },
  153. };
  154. static const struct rk808_reg_data rk818_pre_init_reg[] = {
  155. /* improve efficiency */
  156. { RK818_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_250MA },
  157. { RK818_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_250MA },
  158. { RK818_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA },
  159. { RK818_USB_CTRL_REG, RK818_USB_ILIM_SEL_MASK,
  160. RK818_USB_ILMIN_2000MA },
  161. /* close charger when usb lower then 3.4V */
  162. { RK818_USB_CTRL_REG, RK818_USB_CHG_SD_VSEL_MASK,
  163. (0x7 << 4) },
  164. /* no action when vref */
  165. { RK818_H5V_EN_REG, BIT(1), RK818_REF_RDY_CTRL },
  166. /* enable HDMI 5V */
  167. { RK818_H5V_EN_REG, BIT(0), RK818_H5V_EN },
  168. { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT |
  169. VB_LO_SEL_3500MV },
  170. };
  171. static const struct regmap_irq rk805_irqs[] = {
  172. [RK805_IRQ_PWRON_RISE] = {
  173. .mask = RK805_IRQ_PWRON_RISE_MSK,
  174. .reg_offset = 0,
  175. },
  176. [RK805_IRQ_VB_LOW] = {
  177. .mask = RK805_IRQ_VB_LOW_MSK,
  178. .reg_offset = 0,
  179. },
  180. [RK805_IRQ_PWRON] = {
  181. .mask = RK805_IRQ_PWRON_MSK,
  182. .reg_offset = 0,
  183. },
  184. [RK805_IRQ_PWRON_LP] = {
  185. .mask = RK805_IRQ_PWRON_LP_MSK,
  186. .reg_offset = 0,
  187. },
  188. [RK805_IRQ_HOTDIE] = {
  189. .mask = RK805_IRQ_HOTDIE_MSK,
  190. .reg_offset = 0,
  191. },
  192. [RK805_IRQ_RTC_ALARM] = {
  193. .mask = RK805_IRQ_RTC_ALARM_MSK,
  194. .reg_offset = 0,
  195. },
  196. [RK805_IRQ_RTC_PERIOD] = {
  197. .mask = RK805_IRQ_RTC_PERIOD_MSK,
  198. .reg_offset = 0,
  199. },
  200. [RK805_IRQ_PWRON_FALL] = {
  201. .mask = RK805_IRQ_PWRON_FALL_MSK,
  202. .reg_offset = 0,
  203. },
  204. };
  205. static const struct regmap_irq rk808_irqs[] = {
  206. /* INT_STS */
  207. [RK808_IRQ_VOUT_LO] = {
  208. .mask = RK808_IRQ_VOUT_LO_MSK,
  209. .reg_offset = 0,
  210. },
  211. [RK808_IRQ_VB_LO] = {
  212. .mask = RK808_IRQ_VB_LO_MSK,
  213. .reg_offset = 0,
  214. },
  215. [RK808_IRQ_PWRON] = {
  216. .mask = RK808_IRQ_PWRON_MSK,
  217. .reg_offset = 0,
  218. },
  219. [RK808_IRQ_PWRON_LP] = {
  220. .mask = RK808_IRQ_PWRON_LP_MSK,
  221. .reg_offset = 0,
  222. },
  223. [RK808_IRQ_HOTDIE] = {
  224. .mask = RK808_IRQ_HOTDIE_MSK,
  225. .reg_offset = 0,
  226. },
  227. [RK808_IRQ_RTC_ALARM] = {
  228. .mask = RK808_IRQ_RTC_ALARM_MSK,
  229. .reg_offset = 0,
  230. },
  231. [RK808_IRQ_RTC_PERIOD] = {
  232. .mask = RK808_IRQ_RTC_PERIOD_MSK,
  233. .reg_offset = 0,
  234. },
  235. /* INT_STS2 */
  236. [RK808_IRQ_PLUG_IN_INT] = {
  237. .mask = RK808_IRQ_PLUG_IN_INT_MSK,
  238. .reg_offset = 1,
  239. },
  240. [RK808_IRQ_PLUG_OUT_INT] = {
  241. .mask = RK808_IRQ_PLUG_OUT_INT_MSK,
  242. .reg_offset = 1,
  243. },
  244. };
  245. static const struct regmap_irq rk818_irqs[] = {
  246. /* INT_STS */
  247. [RK818_IRQ_VOUT_LO] = {
  248. .mask = RK818_IRQ_VOUT_LO_MSK,
  249. .reg_offset = 0,
  250. },
  251. [RK818_IRQ_VB_LO] = {
  252. .mask = RK818_IRQ_VB_LO_MSK,
  253. .reg_offset = 0,
  254. },
  255. [RK818_IRQ_PWRON] = {
  256. .mask = RK818_IRQ_PWRON_MSK,
  257. .reg_offset = 0,
  258. },
  259. [RK818_IRQ_PWRON_LP] = {
  260. .mask = RK818_IRQ_PWRON_LP_MSK,
  261. .reg_offset = 0,
  262. },
  263. [RK818_IRQ_HOTDIE] = {
  264. .mask = RK818_IRQ_HOTDIE_MSK,
  265. .reg_offset = 0,
  266. },
  267. [RK818_IRQ_RTC_ALARM] = {
  268. .mask = RK818_IRQ_RTC_ALARM_MSK,
  269. .reg_offset = 0,
  270. },
  271. [RK818_IRQ_RTC_PERIOD] = {
  272. .mask = RK818_IRQ_RTC_PERIOD_MSK,
  273. .reg_offset = 0,
  274. },
  275. [RK818_IRQ_USB_OV] = {
  276. .mask = RK818_IRQ_USB_OV_MSK,
  277. .reg_offset = 0,
  278. },
  279. /* INT_STS2 */
  280. [RK818_IRQ_PLUG_IN] = {
  281. .mask = RK818_IRQ_PLUG_IN_MSK,
  282. .reg_offset = 1,
  283. },
  284. [RK818_IRQ_PLUG_OUT] = {
  285. .mask = RK818_IRQ_PLUG_OUT_MSK,
  286. .reg_offset = 1,
  287. },
  288. [RK818_IRQ_CHG_OK] = {
  289. .mask = RK818_IRQ_CHG_OK_MSK,
  290. .reg_offset = 1,
  291. },
  292. [RK818_IRQ_CHG_TE] = {
  293. .mask = RK818_IRQ_CHG_TE_MSK,
  294. .reg_offset = 1,
  295. },
  296. [RK818_IRQ_CHG_TS1] = {
  297. .mask = RK818_IRQ_CHG_TS1_MSK,
  298. .reg_offset = 1,
  299. },
  300. [RK818_IRQ_TS2] = {
  301. .mask = RK818_IRQ_TS2_MSK,
  302. .reg_offset = 1,
  303. },
  304. [RK818_IRQ_CHG_CVTLIM] = {
  305. .mask = RK818_IRQ_CHG_CVTLIM_MSK,
  306. .reg_offset = 1,
  307. },
  308. [RK818_IRQ_DISCHG_ILIM] = {
  309. .mask = RK818_IRQ_DISCHG_ILIM_MSK,
  310. .reg_offset = 1,
  311. },
  312. };
  313. static struct regmap_irq_chip rk805_irq_chip = {
  314. .name = "rk805",
  315. .irqs = rk805_irqs,
  316. .num_irqs = ARRAY_SIZE(rk805_irqs),
  317. .num_regs = 1,
  318. .status_base = RK805_INT_STS_REG,
  319. .mask_base = RK805_INT_STS_MSK_REG,
  320. .ack_base = RK805_INT_STS_REG,
  321. .init_ack_masked = true,
  322. };
  323. static const struct regmap_irq_chip rk808_irq_chip = {
  324. .name = "rk808",
  325. .irqs = rk808_irqs,
  326. .num_irqs = ARRAY_SIZE(rk808_irqs),
  327. .num_regs = 2,
  328. .irq_reg_stride = 2,
  329. .status_base = RK808_INT_STS_REG1,
  330. .mask_base = RK808_INT_STS_MSK_REG1,
  331. .ack_base = RK808_INT_STS_REG1,
  332. .init_ack_masked = true,
  333. };
  334. static const struct regmap_irq_chip rk818_irq_chip = {
  335. .name = "rk818",
  336. .irqs = rk818_irqs,
  337. .num_irqs = ARRAY_SIZE(rk818_irqs),
  338. .num_regs = 2,
  339. .irq_reg_stride = 2,
  340. .status_base = RK818_INT_STS_REG1,
  341. .mask_base = RK818_INT_STS_MSK_REG1,
  342. .ack_base = RK818_INT_STS_REG1,
  343. .init_ack_masked = true,
  344. };
  345. static struct i2c_client *rk808_i2c_client;
  346. static void rk805_device_shutdown(void)
  347. {
  348. int ret;
  349. struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
  350. if (!rk808) {
  351. dev_warn(&rk808_i2c_client->dev,
  352. "have no rk805, so do nothing here\n");
  353. return;
  354. }
  355. ret = regmap_update_bits(rk808->regmap,
  356. RK805_DEV_CTRL_REG,
  357. DEV_OFF, DEV_OFF);
  358. if (ret)
  359. dev_err(&rk808_i2c_client->dev, "power off error!\n");
  360. }
  361. static void rk808_device_shutdown(void)
  362. {
  363. int ret;
  364. struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
  365. if (!rk808) {
  366. dev_warn(&rk808_i2c_client->dev,
  367. "have no rk808, so do nothing here\n");
  368. return;
  369. }
  370. ret = regmap_update_bits(rk808->regmap,
  371. RK808_DEVCTRL_REG,
  372. DEV_OFF_RST, DEV_OFF_RST);
  373. if (ret)
  374. dev_err(&rk808_i2c_client->dev, "power off error!\n");
  375. }
  376. static void rk818_device_shutdown(void)
  377. {
  378. int ret;
  379. struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
  380. if (!rk808) {
  381. dev_warn(&rk808_i2c_client->dev,
  382. "have no rk818, so do nothing here\n");
  383. return;
  384. }
  385. ret = regmap_update_bits(rk808->regmap,
  386. RK818_DEVCTRL_REG,
  387. DEV_OFF, DEV_OFF);
  388. if (ret)
  389. dev_err(&rk808_i2c_client->dev, "power off error!\n");
  390. }
  391. static const struct of_device_id rk808_of_match[] = {
  392. { .compatible = "rockchip,rk805" },
  393. { .compatible = "rockchip,rk808" },
  394. { .compatible = "rockchip,rk818" },
  395. { },
  396. };
  397. MODULE_DEVICE_TABLE(of, rk808_of_match);
  398. static int rk808_probe(struct i2c_client *client,
  399. const struct i2c_device_id *id)
  400. {
  401. struct device_node *np = client->dev.of_node;
  402. struct rk808 *rk808;
  403. const struct rk808_reg_data *pre_init_reg;
  404. const struct mfd_cell *cells;
  405. void (*pm_pwroff_fn)(void);
  406. int nr_pre_init_regs;
  407. int nr_cells;
  408. int pm_off = 0, msb, lsb;
  409. int ret;
  410. int i;
  411. rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL);
  412. if (!rk808)
  413. return -ENOMEM;
  414. /* Read chip variant */
  415. msb = i2c_smbus_read_byte_data(client, RK808_ID_MSB);
  416. if (msb < 0) {
  417. dev_err(&client->dev, "failed to read the chip id at 0x%x\n",
  418. RK808_ID_MSB);
  419. return msb;
  420. }
  421. lsb = i2c_smbus_read_byte_data(client, RK808_ID_LSB);
  422. if (lsb < 0) {
  423. dev_err(&client->dev, "failed to read the chip id at 0x%x\n",
  424. RK808_ID_LSB);
  425. return lsb;
  426. }
  427. rk808->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
  428. dev_info(&client->dev, "chip id: 0x%x\n", (unsigned int)rk808->variant);
  429. switch (rk808->variant) {
  430. case RK805_ID:
  431. rk808->regmap_cfg = &rk805_regmap_config;
  432. rk808->regmap_irq_chip = &rk805_irq_chip;
  433. pre_init_reg = rk805_pre_init_reg;
  434. nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg);
  435. cells = rk805s;
  436. nr_cells = ARRAY_SIZE(rk805s);
  437. pm_pwroff_fn = rk805_device_shutdown;
  438. break;
  439. case RK808_ID:
  440. rk808->regmap_cfg = &rk808_regmap_config;
  441. rk808->regmap_irq_chip = &rk808_irq_chip;
  442. pre_init_reg = rk808_pre_init_reg;
  443. nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg);
  444. cells = rk808s;
  445. nr_cells = ARRAY_SIZE(rk808s);
  446. pm_pwroff_fn = rk808_device_shutdown;
  447. break;
  448. case RK818_ID:
  449. rk808->regmap_cfg = &rk818_regmap_config;
  450. rk808->regmap_irq_chip = &rk818_irq_chip;
  451. pre_init_reg = rk818_pre_init_reg;
  452. nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg);
  453. cells = rk818s;
  454. nr_cells = ARRAY_SIZE(rk818s);
  455. pm_pwroff_fn = rk818_device_shutdown;
  456. break;
  457. default:
  458. dev_err(&client->dev, "Unsupported RK8XX ID %lu\n",
  459. rk808->variant);
  460. return -EINVAL;
  461. }
  462. rk808->i2c = client;
  463. i2c_set_clientdata(client, rk808);
  464. rk808->regmap = devm_regmap_init_i2c(client, rk808->regmap_cfg);
  465. if (IS_ERR(rk808->regmap)) {
  466. dev_err(&client->dev, "regmap initialization failed\n");
  467. return PTR_ERR(rk808->regmap);
  468. }
  469. if (!client->irq) {
  470. dev_err(&client->dev, "No interrupt support, no core IRQ\n");
  471. return -EINVAL;
  472. }
  473. ret = regmap_add_irq_chip(rk808->regmap, client->irq,
  474. IRQF_ONESHOT, -1,
  475. rk808->regmap_irq_chip, &rk808->irq_data);
  476. if (ret) {
  477. dev_err(&client->dev, "Failed to add irq_chip %d\n", ret);
  478. return ret;
  479. }
  480. for (i = 0; i < nr_pre_init_regs; i++) {
  481. ret = regmap_update_bits(rk808->regmap,
  482. pre_init_reg[i].addr,
  483. pre_init_reg[i].mask,
  484. pre_init_reg[i].value);
  485. if (ret) {
  486. dev_err(&client->dev,
  487. "0x%x write err\n",
  488. pre_init_reg[i].addr);
  489. return ret;
  490. }
  491. }
  492. ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
  493. cells, nr_cells, NULL, 0,
  494. regmap_irq_get_domain(rk808->irq_data));
  495. if (ret) {
  496. dev_err(&client->dev, "failed to add MFD devices %d\n", ret);
  497. goto err_irq;
  498. }
  499. pm_off = of_property_read_bool(np,
  500. "rockchip,system-power-controller");
  501. if (pm_off && !pm_power_off) {
  502. rk808_i2c_client = client;
  503. pm_power_off = pm_pwroff_fn;
  504. }
  505. return 0;
  506. err_irq:
  507. regmap_del_irq_chip(client->irq, rk808->irq_data);
  508. return ret;
  509. }
  510. static int rk808_remove(struct i2c_client *client)
  511. {
  512. struct rk808 *rk808 = i2c_get_clientdata(client);
  513. regmap_del_irq_chip(client->irq, rk808->irq_data);
  514. pm_power_off = NULL;
  515. return 0;
  516. }
  517. static const struct i2c_device_id rk808_ids[] = {
  518. { "rk805" },
  519. { "rk808" },
  520. { "rk818" },
  521. { },
  522. };
  523. MODULE_DEVICE_TABLE(i2c, rk808_ids);
  524. static struct i2c_driver rk808_i2c_driver = {
  525. .driver = {
  526. .name = "rk808",
  527. .of_match_table = rk808_of_match,
  528. },
  529. .probe = rk808_probe,
  530. .remove = rk808_remove,
  531. .id_table = rk808_ids,
  532. };
  533. module_i2c_driver(rk808_i2c_driver);
  534. MODULE_LICENSE("GPL");
  535. MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
  536. MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
  537. MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
  538. MODULE_DESCRIPTION("RK808/RK818 PMIC driver");