13d0407baSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 23d0407baSopenharmony_ci/* 33d0407baSopenharmony_ci * MFD core driver for Rockchip RK808/RK818 43d0407baSopenharmony_ci * 53d0407baSopenharmony_ci * Copyright (c) 2014-2018, Fuzhou Rockchip Electronics Co., Ltd 63d0407baSopenharmony_ci * 73d0407baSopenharmony_ci * Author: Chris Zhong <zyw@rock-chips.com> 83d0407baSopenharmony_ci * Author: Zhang Qing <zhangqing@rock-chips.com> 93d0407baSopenharmony_ci * 103d0407baSopenharmony_ci * Copyright (C) 2016 PHYTEC Messtechnik GmbH 113d0407baSopenharmony_ci * 123d0407baSopenharmony_ci * Author: Wadim Egorov <w.egorov@phytec.de> 133d0407baSopenharmony_ci */ 143d0407baSopenharmony_ci 153d0407baSopenharmony_ci#include <linux/i2c.h> 163d0407baSopenharmony_ci#include <linux/interrupt.h> 173d0407baSopenharmony_ci#include <linux/mfd/rk808.h> 183d0407baSopenharmony_ci#include <linux/mfd/core.h> 193d0407baSopenharmony_ci#include <linux/module.h> 203d0407baSopenharmony_ci#include <linux/of_device.h> 213d0407baSopenharmony_ci#include <linux/reboot.h> 223d0407baSopenharmony_ci#include <linux/regmap.h> 233d0407baSopenharmony_ci#include <linux/syscore_ops.h> 243d0407baSopenharmony_ci#include <linux/pinctrl/consumer.h> 253d0407baSopenharmony_ci#include <linux/pinctrl/devinfo.h> 263d0407baSopenharmony_ci 273d0407baSopenharmony_cistruct rk808_reg_data { 283d0407baSopenharmony_ci int addr; 293d0407baSopenharmony_ci int mask; 303d0407baSopenharmony_ci int value; 313d0407baSopenharmony_ci}; 323d0407baSopenharmony_ci 333d0407baSopenharmony_cistatic bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) 343d0407baSopenharmony_ci{ 353d0407baSopenharmony_ci /* 363d0407baSopenharmony_ci * Notes: 373d0407baSopenharmony_ci * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but 383d0407baSopenharmony_ci * we don't use that feature. It's better to cache. 393d0407baSopenharmony_ci * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since 403d0407baSopenharmony_ci * bits are cleared in case when we shutoff anyway, but better safe. 413d0407baSopenharmony_ci */ 423d0407baSopenharmony_ci 433d0407baSopenharmony_ci switch (reg) { 443d0407baSopenharmony_ci case RK808_SECONDS_REG ... RK808_WEEKS_REG: 453d0407baSopenharmony_ci case RK808_RTC_STATUS_REG: 463d0407baSopenharmony_ci case RK808_VB_MON_REG: 473d0407baSopenharmony_ci case RK808_THERMAL_REG: 483d0407baSopenharmony_ci case RK808_DCDC_UV_STS_REG: 493d0407baSopenharmony_ci case RK808_LDO_UV_STS_REG: 503d0407baSopenharmony_ci case RK808_DCDC_PG_REG: 513d0407baSopenharmony_ci case RK808_LDO_PG_REG: 523d0407baSopenharmony_ci case RK808_DEVCTRL_REG: 533d0407baSopenharmony_ci case RK808_INT_STS_REG1: 543d0407baSopenharmony_ci case RK808_INT_STS_REG2: 553d0407baSopenharmony_ci return true; 563d0407baSopenharmony_ci default: 573d0407baSopenharmony_ci break; 583d0407baSopenharmony_ci } 593d0407baSopenharmony_ci 603d0407baSopenharmony_ci return false; 613d0407baSopenharmony_ci} 623d0407baSopenharmony_ci 633d0407baSopenharmony_cistatic bool rk817_is_volatile_reg(struct device *dev, unsigned int reg) 643d0407baSopenharmony_ci{ 653d0407baSopenharmony_ci /* 663d0407baSopenharmony_ci * Notes: 673d0407baSopenharmony_ci * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but 683d0407baSopenharmony_ci * we don't use that feature. It's better to cache. 693d0407baSopenharmony_ci */ 703d0407baSopenharmony_ci 713d0407baSopenharmony_ci switch (reg) { 723d0407baSopenharmony_ci case RK817_SECONDS_REG ... RK817_WEEKS_REG: 733d0407baSopenharmony_ci case RK817_RTC_STATUS_REG: 743d0407baSopenharmony_ci case RK817_ADC_CONFIG0 ... RK817_CURE_ADC_K0: 753d0407baSopenharmony_ci case RK817_CHRG_STS: 763d0407baSopenharmony_ci case RK817_CHRG_OUT: 773d0407baSopenharmony_ci case RK817_CHRG_IN: 783d0407baSopenharmony_ci case RK817_SYS_STS: 793d0407baSopenharmony_ci case RK817_INT_STS_REG0: 803d0407baSopenharmony_ci case RK817_INT_STS_REG1: 813d0407baSopenharmony_ci case RK817_INT_STS_REG2: 823d0407baSopenharmony_ci return true; 833d0407baSopenharmony_ci default: 843d0407baSopenharmony_ci break; 853d0407baSopenharmony_ci } 863d0407baSopenharmony_ci 873d0407baSopenharmony_ci return false; 883d0407baSopenharmony_ci} 893d0407baSopenharmony_ci 903d0407baSopenharmony_cistatic bool rk818_is_volatile_reg(struct device *dev, unsigned int reg) 913d0407baSopenharmony_ci{ 923d0407baSopenharmony_ci /* 933d0407baSopenharmony_ci * Notes: 943d0407baSopenharmony_ci * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but 953d0407baSopenharmony_ci * we don't use that feature. It's better to cache. 963d0407baSopenharmony_ci * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since 973d0407baSopenharmony_ci * bits are cleared in case when we shutoff anyway, but better safe. 983d0407baSopenharmony_ci */ 993d0407baSopenharmony_ci 1003d0407baSopenharmony_ci switch (reg) { 1013d0407baSopenharmony_ci case RK808_SECONDS_REG ... RK808_WEEKS_REG: 1023d0407baSopenharmony_ci case RK808_RTC_STATUS_REG: 1033d0407baSopenharmony_ci case RK808_VB_MON_REG: 1043d0407baSopenharmony_ci case RK808_THERMAL_REG: 1053d0407baSopenharmony_ci case RK808_DCDC_EN_REG: 1063d0407baSopenharmony_ci case RK808_LDO_EN_REG: 1073d0407baSopenharmony_ci case RK808_DCDC_UV_STS_REG: 1083d0407baSopenharmony_ci case RK808_LDO_UV_STS_REG: 1093d0407baSopenharmony_ci case RK808_DCDC_PG_REG: 1103d0407baSopenharmony_ci case RK808_LDO_PG_REG: 1113d0407baSopenharmony_ci case RK808_DEVCTRL_REG: 1123d0407baSopenharmony_ci case RK808_INT_STS_REG1: 1133d0407baSopenharmony_ci case RK808_INT_STS_REG2: 1143d0407baSopenharmony_ci case RK808_INT_STS_MSK_REG1: 1153d0407baSopenharmony_ci case RK808_INT_STS_MSK_REG2: 1163d0407baSopenharmony_ci case RK816_INT_STS_REG1: 1173d0407baSopenharmony_ci case RK816_INT_STS_MSK_REG1: 1183d0407baSopenharmony_ci case RK818_SUP_STS_REG ... RK818_SAVE_DATA19: 1193d0407baSopenharmony_ci return true; 1203d0407baSopenharmony_ci default: 1213d0407baSopenharmony_ci break; 1223d0407baSopenharmony_ci } 1233d0407baSopenharmony_ci 1243d0407baSopenharmony_ci return false; 1253d0407baSopenharmony_ci} 1263d0407baSopenharmony_ci 1273d0407baSopenharmony_cistatic const struct regmap_config rk818_regmap_config = { 1283d0407baSopenharmony_ci .reg_bits = RK_REG_BITS, 1293d0407baSopenharmony_ci .val_bits = RK_VAL_BITS, 1303d0407baSopenharmony_ci .max_register = RK818_SAVE_DATA19, 1313d0407baSopenharmony_ci .cache_type = REGCACHE_RBTREE, 1323d0407baSopenharmony_ci .volatile_reg = rk818_is_volatile_reg, 1333d0407baSopenharmony_ci}; 1343d0407baSopenharmony_ci 1353d0407baSopenharmony_cistatic const struct regmap_config rk805_regmap_config = { 1363d0407baSopenharmony_ci .reg_bits = RK_REG_BITS, 1373d0407baSopenharmony_ci .val_bits = RK_VAL_BITS, 1383d0407baSopenharmony_ci .max_register = RK805_OFF_SOURCE_REG, 1393d0407baSopenharmony_ci .cache_type = REGCACHE_RBTREE, 1403d0407baSopenharmony_ci .volatile_reg = rk808_is_volatile_reg, 1413d0407baSopenharmony_ci}; 1423d0407baSopenharmony_ci 1433d0407baSopenharmony_cistatic const struct regmap_config rk808_regmap_config = { 1443d0407baSopenharmony_ci .reg_bits = RK_REG_BITS, 1453d0407baSopenharmony_ci .val_bits = RK_VAL_BITS, 1463d0407baSopenharmony_ci .max_register = RK808_IO_POL_REG, 1473d0407baSopenharmony_ci .cache_type = REGCACHE_RBTREE, 1483d0407baSopenharmony_ci .volatile_reg = rk808_is_volatile_reg, 1493d0407baSopenharmony_ci}; 1503d0407baSopenharmony_ci 1513d0407baSopenharmony_cistatic const struct regmap_config rk816_regmap_config = { 1523d0407baSopenharmony_ci .reg_bits = RK_REG_BITS, 1533d0407baSopenharmony_ci .val_bits = RK_VAL_BITS, 1543d0407baSopenharmony_ci .max_register = RK816_DATA18_REG, 1553d0407baSopenharmony_ci .cache_type = REGCACHE_RBTREE, 1563d0407baSopenharmony_ci .volatile_reg = rk818_is_volatile_reg, 1573d0407baSopenharmony_ci}; 1583d0407baSopenharmony_ci 1593d0407baSopenharmony_cistatic const struct regmap_config rk817_regmap_config = { 1603d0407baSopenharmony_ci .reg_bits = RK_REG_BITS, 1613d0407baSopenharmony_ci .val_bits = RK_VAL_BITS, 1623d0407baSopenharmony_ci .max_register = RK817_GPIO_INT_CFG, 1633d0407baSopenharmony_ci .num_reg_defaults_raw = RK817_GPIO_INT_CFG + 1, 1643d0407baSopenharmony_ci .cache_type = REGCACHE_RBTREE, 1653d0407baSopenharmony_ci .volatile_reg = rk817_is_volatile_reg, 1663d0407baSopenharmony_ci}; 1673d0407baSopenharmony_ci 1683d0407baSopenharmony_cistatic struct resource rtc_resources[] = { 1693d0407baSopenharmony_ci DEFINE_RES_IRQ(RK808_IRQ_RTC_ALARM), 1703d0407baSopenharmony_ci}; 1713d0407baSopenharmony_ci 1723d0407baSopenharmony_cistatic struct resource rk816_rtc_resources[] = { 1733d0407baSopenharmony_ci DEFINE_RES_IRQ(RK816_IRQ_RTC_ALARM), 1743d0407baSopenharmony_ci}; 1753d0407baSopenharmony_ci 1763d0407baSopenharmony_cistatic struct resource rk817_rtc_resources[] = { 1773d0407baSopenharmony_ci DEFINE_RES_IRQ(RK817_IRQ_RTC_ALARM), 1783d0407baSopenharmony_ci}; 1793d0407baSopenharmony_ci 1803d0407baSopenharmony_cistatic struct resource rk805_key_resources[] = { 1813d0407baSopenharmony_ci DEFINE_RES_IRQ(RK805_IRQ_PWRON_FALL), 1823d0407baSopenharmony_ci DEFINE_RES_IRQ(RK805_IRQ_PWRON_RISE), 1833d0407baSopenharmony_ci}; 1843d0407baSopenharmony_ci 1853d0407baSopenharmony_cistatic struct resource rk816_pwrkey_resources[] = { 1863d0407baSopenharmony_ci DEFINE_RES_IRQ(RK816_IRQ_PWRON_FALL), 1873d0407baSopenharmony_ci DEFINE_RES_IRQ(RK816_IRQ_PWRON_RISE), 1883d0407baSopenharmony_ci}; 1893d0407baSopenharmony_ci 1903d0407baSopenharmony_cistatic struct resource rk817_pwrkey_resources[] = { 1913d0407baSopenharmony_ci DEFINE_RES_IRQ(RK817_IRQ_PWRON_FALL), 1923d0407baSopenharmony_ci DEFINE_RES_IRQ(RK817_IRQ_PWRON_RISE), 1933d0407baSopenharmony_ci}; 1943d0407baSopenharmony_ci 1953d0407baSopenharmony_cistatic const struct mfd_cell rk805s[] = { 1963d0407baSopenharmony_ci { 1973d0407baSopenharmony_ci .name = "rk808-clkout", 1983d0407baSopenharmony_ci }, 1993d0407baSopenharmony_ci { 2003d0407baSopenharmony_ci .name = "rk808-regulator", 2013d0407baSopenharmony_ci }, 2023d0407baSopenharmony_ci { 2033d0407baSopenharmony_ci .name = "rk805-pinctrl", 2043d0407baSopenharmony_ci }, 2053d0407baSopenharmony_ci { 2063d0407baSopenharmony_ci .name = "rk808-rtc", 2073d0407baSopenharmony_ci .num_resources = ARRAY_SIZE(rtc_resources), 2083d0407baSopenharmony_ci .resources = &rtc_resources[0], 2093d0407baSopenharmony_ci }, 2103d0407baSopenharmony_ci { 2113d0407baSopenharmony_ci .name = "rk805-pwrkey", 2123d0407baSopenharmony_ci .num_resources = ARRAY_SIZE(rk805_key_resources), 2133d0407baSopenharmony_ci .resources = &rk805_key_resources[0], 2143d0407baSopenharmony_ci }, 2153d0407baSopenharmony_ci}; 2163d0407baSopenharmony_ci 2173d0407baSopenharmony_cistatic const struct mfd_cell rk808s[] = { 2183d0407baSopenharmony_ci { 2193d0407baSopenharmony_ci .name = "rk808-clkout", 2203d0407baSopenharmony_ci }, 2213d0407baSopenharmony_ci { 2223d0407baSopenharmony_ci .name = "rk808-regulator", 2233d0407baSopenharmony_ci }, 2243d0407baSopenharmony_ci { 2253d0407baSopenharmony_ci .name = "rk808-rtc", 2263d0407baSopenharmony_ci .num_resources = ARRAY_SIZE(rtc_resources), 2273d0407baSopenharmony_ci .resources = rtc_resources, 2283d0407baSopenharmony_ci }, 2293d0407baSopenharmony_ci}; 2303d0407baSopenharmony_ci 2313d0407baSopenharmony_cistatic const struct mfd_cell rk816s[] = { 2323d0407baSopenharmony_ci { 2333d0407baSopenharmony_ci .name = "rk808-clkout", 2343d0407baSopenharmony_ci }, 2353d0407baSopenharmony_ci { 2363d0407baSopenharmony_ci .name = "rk808-regulator", 2373d0407baSopenharmony_ci }, 2383d0407baSopenharmony_ci { 2393d0407baSopenharmony_ci .name = "rk805-pinctrl", 2403d0407baSopenharmony_ci }, 2413d0407baSopenharmony_ci { 2423d0407baSopenharmony_ci .name = "rk816-battery", 2433d0407baSopenharmony_ci .of_compatible = "rk816-battery", 2443d0407baSopenharmony_ci }, 2453d0407baSopenharmony_ci { 2463d0407baSopenharmony_ci .name = "rk805-pwrkey", 2473d0407baSopenharmony_ci .num_resources = ARRAY_SIZE(rk816_pwrkey_resources), 2483d0407baSopenharmony_ci .resources = &rk816_pwrkey_resources[0], 2493d0407baSopenharmony_ci }, 2503d0407baSopenharmony_ci { 2513d0407baSopenharmony_ci .name = "rk808-rtc", 2523d0407baSopenharmony_ci .num_resources = ARRAY_SIZE(rk816_rtc_resources), 2533d0407baSopenharmony_ci .resources = &rk816_rtc_resources[0], 2543d0407baSopenharmony_ci }, 2553d0407baSopenharmony_ci}; 2563d0407baSopenharmony_ci 2573d0407baSopenharmony_cistatic const struct mfd_cell rk817s[] = { 2583d0407baSopenharmony_ci { 2593d0407baSopenharmony_ci .name = "rk808-clkout", 2603d0407baSopenharmony_ci }, 2613d0407baSopenharmony_ci { 2623d0407baSopenharmony_ci .name = "rk808-regulator", 2633d0407baSopenharmony_ci }, 2643d0407baSopenharmony_ci { 2653d0407baSopenharmony_ci .name = "rk817-battery", 2663d0407baSopenharmony_ci .of_compatible = "rk817,battery", 2673d0407baSopenharmony_ci }, 2683d0407baSopenharmony_ci { 2693d0407baSopenharmony_ci .name = "rk817-charger", 2703d0407baSopenharmony_ci .of_compatible = "rk817,charger", 2713d0407baSopenharmony_ci }, 2723d0407baSopenharmony_ci { 2733d0407baSopenharmony_ci .name = "rk805-pwrkey", 2743d0407baSopenharmony_ci .num_resources = ARRAY_SIZE(rk817_pwrkey_resources), 2753d0407baSopenharmony_ci .resources = &rk817_pwrkey_resources[0], 2763d0407baSopenharmony_ci }, 2773d0407baSopenharmony_ci { 2783d0407baSopenharmony_ci .name = "rk808-rtc", 2793d0407baSopenharmony_ci .num_resources = ARRAY_SIZE(rk817_rtc_resources), 2803d0407baSopenharmony_ci .resources = &rk817_rtc_resources[0], 2813d0407baSopenharmony_ci }, 2823d0407baSopenharmony_ci { 2833d0407baSopenharmony_ci .name = "rk817-codec", 2843d0407baSopenharmony_ci .of_compatible = "rockchip,rk817-codec", 2853d0407baSopenharmony_ci }, 2863d0407baSopenharmony_ci}; 2873d0407baSopenharmony_ci 2883d0407baSopenharmony_cistatic const struct mfd_cell rk818s[] = { 2893d0407baSopenharmony_ci { 2903d0407baSopenharmony_ci .name = "rk808-clkout", 2913d0407baSopenharmony_ci }, 2923d0407baSopenharmony_ci { 2933d0407baSopenharmony_ci .name = "rk808-regulator", 2943d0407baSopenharmony_ci }, 2953d0407baSopenharmony_ci { 2963d0407baSopenharmony_ci .name = "rk818-battery", 2973d0407baSopenharmony_ci .of_compatible = "rk818-battery", 2983d0407baSopenharmony_ci }, 2993d0407baSopenharmony_ci { 3003d0407baSopenharmony_ci .name = "rk818-charger", 3013d0407baSopenharmony_ci }, 3023d0407baSopenharmony_ci { 3033d0407baSopenharmony_ci .name = "rk808-rtc", 3043d0407baSopenharmony_ci .num_resources = ARRAY_SIZE(rtc_resources), 3053d0407baSopenharmony_ci .resources = rtc_resources, 3063d0407baSopenharmony_ci }, 3073d0407baSopenharmony_ci}; 3083d0407baSopenharmony_ci 3093d0407baSopenharmony_cistatic const struct rk808_reg_data rk805_pre_init_reg[] = { 3103d0407baSopenharmony_ci {RK805_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_400MA}, 3113d0407baSopenharmony_ci {RK805_GPIO_IO_POL_REG, SLP_SD_MSK, SLEEP_FUN}, 3123d0407baSopenharmony_ci {RK805_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP115C}, 3133d0407baSopenharmony_ci {RK808_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, 3143d0407baSopenharmony_ci}; 3153d0407baSopenharmony_ci 3163d0407baSopenharmony_cistatic struct rk808_reg_data rk805_suspend_reg[] = { 3173d0407baSopenharmony_ci {RK805_BUCK3_CONFIG_REG, PWM_MODE_MSK, AUTO_PWM_MODE}, 3183d0407baSopenharmony_ci}; 3193d0407baSopenharmony_ci 3203d0407baSopenharmony_cistatic struct rk808_reg_data rk805_resume_reg[] = { 3213d0407baSopenharmony_ci {RK805_BUCK3_CONFIG_REG, PWM_MODE_MSK, FPWM_MODE}, 3223d0407baSopenharmony_ci}; 3233d0407baSopenharmony_ci 3243d0407baSopenharmony_cistatic const struct rk808_reg_data rk808_pre_init_reg[] = { 3253d0407baSopenharmony_ci {RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA}, 3263d0407baSopenharmony_ci {RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA}, 3273d0407baSopenharmony_ci {RK808_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA}, 3283d0407baSopenharmony_ci {RK808_BUCK1_CONFIG_REG, BUCK1_RATE_MASK, BUCK_ILMIN_200MA}, 3293d0407baSopenharmony_ci {RK808_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_200MA}, 3303d0407baSopenharmony_ci {RK808_DCDC_UV_ACT_REG, BUCK_UV_ACT_MASK, BUCK_UV_ACT_DISABLE}, 3313d0407baSopenharmony_ci {RK808_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, 3323d0407baSopenharmony_ci {RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT | VB_LO_SEL_3500MV}, 3333d0407baSopenharmony_ci}; 3343d0407baSopenharmony_ci 3353d0407baSopenharmony_cistatic const struct rk808_reg_data rk816_pre_init_reg[] = { 3363d0407baSopenharmony_ci /* buck4 Max ILMIT */ 3373d0407baSopenharmony_ci {RK816_BUCK4_CONFIG_REG, REG_WRITE_MSK, BUCK4_MAX_ILIMIT}, 3383d0407baSopenharmony_ci /* hotdie temperature: 105c */ 3393d0407baSopenharmony_ci {RK816_THERMAL_REG, REG_WRITE_MSK, TEMP105C}, 3403d0407baSopenharmony_ci /* set buck 12.5mv/us */ 3413d0407baSopenharmony_ci {RK816_BUCK1_CONFIG_REG, BUCK_RATE_MSK, BUCK_RATE_12_5MV_US}, 3423d0407baSopenharmony_ci {RK816_BUCK2_CONFIG_REG, BUCK_RATE_MSK, BUCK_RATE_12_5MV_US}, 3433d0407baSopenharmony_ci /* enable RTC_PERIOD & RTC_ALARM int */ 3443d0407baSopenharmony_ci {RK816_INT_STS_MSK_REG2, REG_WRITE_MSK, RTC_PERIOD_ALARM_INT_EN}, 3453d0407baSopenharmony_ci /* set bat 3.0 low and act shutdown */ 3463d0407baSopenharmony_ci {RK816_VB_MON_REG, VBAT_LOW_VOL_MASK | VBAT_LOW_ACT_MASK, RK816_VBAT_LOW_3V0 | EN_VABT_LOW_SHUT_DOWN}, 3473d0407baSopenharmony_ci /* enable PWRON rising/faling int */ 3483d0407baSopenharmony_ci {RK816_INT_STS_MSK_REG1, REG_WRITE_MSK, RK816_PWRON_FALL_RISE_INT_EN}, 3493d0407baSopenharmony_ci /* enable PLUG IN/OUT int */ 3503d0407baSopenharmony_ci {RK816_INT_STS_MSK_REG3, REG_WRITE_MSK, PLUGIN_OUT_INT_EN}, 3513d0407baSopenharmony_ci /* clear int flags */ 3523d0407baSopenharmony_ci {RK816_INT_STS_REG1, REG_WRITE_MSK, ALL_INT_FLAGS_ST}, 3533d0407baSopenharmony_ci {RK816_INT_STS_REG2, REG_WRITE_MSK, ALL_INT_FLAGS_ST}, 3543d0407baSopenharmony_ci {RK816_INT_STS_REG3, REG_WRITE_MSK, ALL_INT_FLAGS_ST}, 3553d0407baSopenharmony_ci {RK816_DCDC_EN_REG2, BOOST_EN_MASK, BOOST_DISABLE}, 3563d0407baSopenharmony_ci /* set write mask bit 1, otherwise 'is_enabled()' get wrong status */ 3573d0407baSopenharmony_ci {RK816_LDO_EN_REG1, REGS_WMSK, REGS_WMSK}, 3583d0407baSopenharmony_ci {RK816_LDO_EN_REG2, REGS_WMSK, REGS_WMSK}, 3593d0407baSopenharmony_ci}; 3603d0407baSopenharmony_ci 3613d0407baSopenharmony_cistatic const struct rk808_reg_data rk817_pre_init_reg[] = { 3623d0407baSopenharmony_ci {RK817_SYS_CFG(3), RK817_SLPPOL_MSK, RK817_SLPPOL_L}, 3633d0407baSopenharmony_ci {RK817_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, 3643d0407baSopenharmony_ci {RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_L}, 3653d0407baSopenharmony_ci {RK817_SYS_CFG(1), RK817_HOTDIE_TEMP_MSK | RK817_TSD_TEMP_MSK, RK817_HOTDIE_105 | RK817_TSD_140}, 3663d0407baSopenharmony_ci}; 3673d0407baSopenharmony_ci 3683d0407baSopenharmony_cistatic const struct rk808_reg_data rk818_pre_init_reg[] = { 3693d0407baSopenharmony_ci /* improve efficiency */ 3703d0407baSopenharmony_ci {RK818_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_250MA}, 3713d0407baSopenharmony_ci {RK818_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_250MA}, 3723d0407baSopenharmony_ci {RK818_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA}, 3733d0407baSopenharmony_ci {RK818_USB_CTRL_REG, RK818_USB_ILIM_SEL_MASK, RK818_USB_ILMIN_2000MA}, 3743d0407baSopenharmony_ci /* close charger when usb lower then 3.4V */ 3753d0407baSopenharmony_ci {RK818_USB_CTRL_REG, RK818_USB_CHG_SD_VSEL_MASK, (0x7 << 4)}, 3763d0407baSopenharmony_ci /* no action when vref */ 3773d0407baSopenharmony_ci {RK818_H5V_EN_REG, BIT(1), RK818_REF_RDY_CTRL}, 3783d0407baSopenharmony_ci /* enable HDMI 5V */ 3793d0407baSopenharmony_ci {RK818_H5V_EN_REG, BIT(0), RK818_H5V_EN}, 3803d0407baSopenharmony_ci {RK808_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, 3813d0407baSopenharmony_ci {RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT | VB_LO_SEL_3500MV}, 3823d0407baSopenharmony_ci {RK808_CLK32OUT_REG, CLK32KOUT2_FUNC_MASK, CLK32KOUT2_FUNC}, 3833d0407baSopenharmony_ci}; 3843d0407baSopenharmony_ci 3853d0407baSopenharmony_cistatic const struct regmap_irq rk805_irqs[] = { 3863d0407baSopenharmony_ci [RK805_IRQ_PWRON_RISE] = 3873d0407baSopenharmony_ci { 3883d0407baSopenharmony_ci .mask = RK805_IRQ_PWRON_RISE_MSK, 3893d0407baSopenharmony_ci .reg_offset = 0, 3903d0407baSopenharmony_ci }, 3913d0407baSopenharmony_ci [RK805_IRQ_VB_LOW] = 3923d0407baSopenharmony_ci { 3933d0407baSopenharmony_ci .mask = RK805_IRQ_VB_LOW_MSK, 3943d0407baSopenharmony_ci .reg_offset = 0, 3953d0407baSopenharmony_ci }, 3963d0407baSopenharmony_ci [RK805_IRQ_PWRON] = 3973d0407baSopenharmony_ci { 3983d0407baSopenharmony_ci .mask = RK805_IRQ_PWRON_MSK, 3993d0407baSopenharmony_ci .reg_offset = 0, 4003d0407baSopenharmony_ci }, 4013d0407baSopenharmony_ci [RK805_IRQ_PWRON_LP] = 4023d0407baSopenharmony_ci { 4033d0407baSopenharmony_ci .mask = RK805_IRQ_PWRON_LP_MSK, 4043d0407baSopenharmony_ci .reg_offset = 0, 4053d0407baSopenharmony_ci }, 4063d0407baSopenharmony_ci [RK805_IRQ_HOTDIE] = 4073d0407baSopenharmony_ci { 4083d0407baSopenharmony_ci .mask = RK805_IRQ_HOTDIE_MSK, 4093d0407baSopenharmony_ci .reg_offset = 0, 4103d0407baSopenharmony_ci }, 4113d0407baSopenharmony_ci [RK805_IRQ_RTC_ALARM] = 4123d0407baSopenharmony_ci { 4133d0407baSopenharmony_ci .mask = RK805_IRQ_RTC_ALARM_MSK, 4143d0407baSopenharmony_ci .reg_offset = 0, 4153d0407baSopenharmony_ci }, 4163d0407baSopenharmony_ci [RK805_IRQ_RTC_PERIOD] = 4173d0407baSopenharmony_ci { 4183d0407baSopenharmony_ci .mask = RK805_IRQ_RTC_PERIOD_MSK, 4193d0407baSopenharmony_ci .reg_offset = 0, 4203d0407baSopenharmony_ci }, 4213d0407baSopenharmony_ci [RK805_IRQ_PWRON_FALL] = 4223d0407baSopenharmony_ci { 4233d0407baSopenharmony_ci .mask = RK805_IRQ_PWRON_FALL_MSK, 4243d0407baSopenharmony_ci .reg_offset = 0, 4253d0407baSopenharmony_ci }, 4263d0407baSopenharmony_ci}; 4273d0407baSopenharmony_ci 4283d0407baSopenharmony_cistatic const struct regmap_irq rk808_irqs[] = { 4293d0407baSopenharmony_ci /* INT_STS */ 4303d0407baSopenharmony_ci [RK808_IRQ_VOUT_LO] = 4313d0407baSopenharmony_ci { 4323d0407baSopenharmony_ci .mask = RK808_IRQ_VOUT_LO_MSK, 4333d0407baSopenharmony_ci .reg_offset = 0, 4343d0407baSopenharmony_ci }, 4353d0407baSopenharmony_ci [RK808_IRQ_VB_LO] = 4363d0407baSopenharmony_ci { 4373d0407baSopenharmony_ci .mask = RK808_IRQ_VB_LO_MSK, 4383d0407baSopenharmony_ci .reg_offset = 0, 4393d0407baSopenharmony_ci }, 4403d0407baSopenharmony_ci [RK808_IRQ_PWRON] = 4413d0407baSopenharmony_ci { 4423d0407baSopenharmony_ci .mask = RK808_IRQ_PWRON_MSK, 4433d0407baSopenharmony_ci .reg_offset = 0, 4443d0407baSopenharmony_ci }, 4453d0407baSopenharmony_ci [RK808_IRQ_PWRON_LP] = 4463d0407baSopenharmony_ci { 4473d0407baSopenharmony_ci .mask = RK808_IRQ_PWRON_LP_MSK, 4483d0407baSopenharmony_ci .reg_offset = 0, 4493d0407baSopenharmony_ci }, 4503d0407baSopenharmony_ci [RK808_IRQ_HOTDIE] = 4513d0407baSopenharmony_ci { 4523d0407baSopenharmony_ci .mask = RK808_IRQ_HOTDIE_MSK, 4533d0407baSopenharmony_ci .reg_offset = 0, 4543d0407baSopenharmony_ci }, 4553d0407baSopenharmony_ci [RK808_IRQ_RTC_ALARM] = 4563d0407baSopenharmony_ci { 4573d0407baSopenharmony_ci .mask = RK808_IRQ_RTC_ALARM_MSK, 4583d0407baSopenharmony_ci .reg_offset = 0, 4593d0407baSopenharmony_ci }, 4603d0407baSopenharmony_ci [RK808_IRQ_RTC_PERIOD] = 4613d0407baSopenharmony_ci { 4623d0407baSopenharmony_ci .mask = RK808_IRQ_RTC_PERIOD_MSK, 4633d0407baSopenharmony_ci .reg_offset = 0, 4643d0407baSopenharmony_ci }, 4653d0407baSopenharmony_ci 4663d0407baSopenharmony_ci /* INT_STS2 */ 4673d0407baSopenharmony_ci [RK808_IRQ_PLUG_IN_INT] = 4683d0407baSopenharmony_ci { 4693d0407baSopenharmony_ci .mask = RK808_IRQ_PLUG_IN_INT_MSK, 4703d0407baSopenharmony_ci .reg_offset = 1, 4713d0407baSopenharmony_ci }, 4723d0407baSopenharmony_ci [RK808_IRQ_PLUG_OUT_INT] = 4733d0407baSopenharmony_ci { 4743d0407baSopenharmony_ci .mask = RK808_IRQ_PLUG_OUT_INT_MSK, 4753d0407baSopenharmony_ci .reg_offset = 1, 4763d0407baSopenharmony_ci }, 4773d0407baSopenharmony_ci}; 4783d0407baSopenharmony_ci 4793d0407baSopenharmony_cistatic struct rk808_reg_data rk816_suspend_reg[] = { 4803d0407baSopenharmony_ci /* set bat 3.4v low and act irq */ 4813d0407baSopenharmony_ci {RK816_VB_MON_REG, VBAT_LOW_VOL_MASK | VBAT_LOW_ACT_MASK, RK816_VBAT_LOW_3V4 | EN_VBAT_LOW_IRQ}, 4823d0407baSopenharmony_ci}; 4833d0407baSopenharmony_ci 4843d0407baSopenharmony_cistatic struct rk808_reg_data rk816_resume_reg[] = { 4853d0407baSopenharmony_ci /* set bat 3.0v low and act shutdown */ 4863d0407baSopenharmony_ci {RK816_VB_MON_REG, VBAT_LOW_VOL_MASK | VBAT_LOW_ACT_MASK, RK816_VBAT_LOW_3V0 | EN_VABT_LOW_SHUT_DOWN}, 4873d0407baSopenharmony_ci}; 4883d0407baSopenharmony_ci 4893d0407baSopenharmony_cistatic const struct regmap_irq rk816_irqs[] = { 4903d0407baSopenharmony_ci /* INT_STS */ 4913d0407baSopenharmony_ci [RK816_IRQ_PWRON_FALL] = 4923d0407baSopenharmony_ci { 4933d0407baSopenharmony_ci .mask = RK816_IRQ_PWRON_FALL_MSK, 4943d0407baSopenharmony_ci .reg_offset = 0, 4953d0407baSopenharmony_ci }, 4963d0407baSopenharmony_ci [RK816_IRQ_PWRON_RISE] = 4973d0407baSopenharmony_ci { 4983d0407baSopenharmony_ci .mask = RK816_IRQ_PWRON_RISE_MSK, 4993d0407baSopenharmony_ci .reg_offset = 0, 5003d0407baSopenharmony_ci }, 5013d0407baSopenharmony_ci [RK816_IRQ_VB_LOW] = 5023d0407baSopenharmony_ci { 5033d0407baSopenharmony_ci .mask = RK816_IRQ_VB_LOW_MSK, 5043d0407baSopenharmony_ci .reg_offset = 1, 5053d0407baSopenharmony_ci }, 5063d0407baSopenharmony_ci [RK816_IRQ_PWRON] = 5073d0407baSopenharmony_ci { 5083d0407baSopenharmony_ci .mask = RK816_IRQ_PWRON_MSK, 5093d0407baSopenharmony_ci .reg_offset = 1, 5103d0407baSopenharmony_ci }, 5113d0407baSopenharmony_ci [RK816_IRQ_PWRON_LP] = 5123d0407baSopenharmony_ci { 5133d0407baSopenharmony_ci .mask = RK816_IRQ_PWRON_LP_MSK, 5143d0407baSopenharmony_ci .reg_offset = 1, 5153d0407baSopenharmony_ci }, 5163d0407baSopenharmony_ci [RK816_IRQ_HOTDIE] = 5173d0407baSopenharmony_ci { 5183d0407baSopenharmony_ci .mask = RK816_IRQ_HOTDIE_MSK, 5193d0407baSopenharmony_ci .reg_offset = 1, 5203d0407baSopenharmony_ci }, 5213d0407baSopenharmony_ci [RK816_IRQ_RTC_ALARM] = 5223d0407baSopenharmony_ci { 5233d0407baSopenharmony_ci .mask = RK816_IRQ_RTC_ALARM_MSK, 5243d0407baSopenharmony_ci .reg_offset = 1, 5253d0407baSopenharmony_ci }, 5263d0407baSopenharmony_ci [RK816_IRQ_RTC_PERIOD] = 5273d0407baSopenharmony_ci { 5283d0407baSopenharmony_ci .mask = RK816_IRQ_RTC_PERIOD_MSK, 5293d0407baSopenharmony_ci .reg_offset = 1, 5303d0407baSopenharmony_ci }, 5313d0407baSopenharmony_ci [RK816_IRQ_USB_OV] = 5323d0407baSopenharmony_ci { 5333d0407baSopenharmony_ci .mask = RK816_IRQ_USB_OV_MSK, 5343d0407baSopenharmony_ci .reg_offset = 1, 5353d0407baSopenharmony_ci }, 5363d0407baSopenharmony_ci}; 5373d0407baSopenharmony_ci 5383d0407baSopenharmony_cistatic struct rk808_reg_data rk818_suspend_reg[] = { 5393d0407baSopenharmony_ci /* set bat 3.4v low and act irq */ 5403d0407baSopenharmony_ci {RK808_VB_MON_REG, VBAT_LOW_VOL_MASK | VBAT_LOW_ACT_MASK, RK808_VBAT_LOW_3V4 | EN_VBAT_LOW_IRQ}, 5413d0407baSopenharmony_ci}; 5423d0407baSopenharmony_ci 5433d0407baSopenharmony_cistatic struct rk808_reg_data rk818_resume_reg[] = { 5443d0407baSopenharmony_ci /* set bat 3.0v low and act shutdown */ 5453d0407baSopenharmony_ci {RK808_VB_MON_REG, VBAT_LOW_VOL_MASK | VBAT_LOW_ACT_MASK, RK808_VBAT_LOW_3V0 | EN_VABT_LOW_SHUT_DOWN}, 5463d0407baSopenharmony_ci}; 5473d0407baSopenharmony_ci 5483d0407baSopenharmony_cistatic const struct regmap_irq rk818_irqs[] = { 5493d0407baSopenharmony_ci /* INT_STS */ 5503d0407baSopenharmony_ci [RK818_IRQ_VOUT_LO] = 5513d0407baSopenharmony_ci { 5523d0407baSopenharmony_ci .mask = RK818_IRQ_VOUT_LO_MSK, 5533d0407baSopenharmony_ci .reg_offset = 0, 5543d0407baSopenharmony_ci }, 5553d0407baSopenharmony_ci [RK818_IRQ_VB_LO] = 5563d0407baSopenharmony_ci { 5573d0407baSopenharmony_ci .mask = RK818_IRQ_VB_LO_MSK, 5583d0407baSopenharmony_ci .reg_offset = 0, 5593d0407baSopenharmony_ci }, 5603d0407baSopenharmony_ci [RK818_IRQ_PWRON] = 5613d0407baSopenharmony_ci { 5623d0407baSopenharmony_ci .mask = RK818_IRQ_PWRON_MSK, 5633d0407baSopenharmony_ci .reg_offset = 0, 5643d0407baSopenharmony_ci }, 5653d0407baSopenharmony_ci [RK818_IRQ_PWRON_LP] = 5663d0407baSopenharmony_ci { 5673d0407baSopenharmony_ci .mask = RK818_IRQ_PWRON_LP_MSK, 5683d0407baSopenharmony_ci .reg_offset = 0, 5693d0407baSopenharmony_ci }, 5703d0407baSopenharmony_ci [RK818_IRQ_HOTDIE] = 5713d0407baSopenharmony_ci { 5723d0407baSopenharmony_ci .mask = RK818_IRQ_HOTDIE_MSK, 5733d0407baSopenharmony_ci .reg_offset = 0, 5743d0407baSopenharmony_ci }, 5753d0407baSopenharmony_ci [RK818_IRQ_RTC_ALARM] = 5763d0407baSopenharmony_ci { 5773d0407baSopenharmony_ci .mask = RK818_IRQ_RTC_ALARM_MSK, 5783d0407baSopenharmony_ci .reg_offset = 0, 5793d0407baSopenharmony_ci }, 5803d0407baSopenharmony_ci [RK818_IRQ_RTC_PERIOD] = 5813d0407baSopenharmony_ci { 5823d0407baSopenharmony_ci .mask = RK818_IRQ_RTC_PERIOD_MSK, 5833d0407baSopenharmony_ci .reg_offset = 0, 5843d0407baSopenharmony_ci }, 5853d0407baSopenharmony_ci [RK818_IRQ_USB_OV] = 5863d0407baSopenharmony_ci { 5873d0407baSopenharmony_ci .mask = RK818_IRQ_USB_OV_MSK, 5883d0407baSopenharmony_ci .reg_offset = 0, 5893d0407baSopenharmony_ci }, 5903d0407baSopenharmony_ci 5913d0407baSopenharmony_ci /* INT_STS2 */ 5923d0407baSopenharmony_ci [RK818_IRQ_PLUG_IN] = 5933d0407baSopenharmony_ci { 5943d0407baSopenharmony_ci .mask = RK818_IRQ_PLUG_IN_MSK, 5953d0407baSopenharmony_ci .reg_offset = 1, 5963d0407baSopenharmony_ci }, 5973d0407baSopenharmony_ci [RK818_IRQ_PLUG_OUT] = 5983d0407baSopenharmony_ci { 5993d0407baSopenharmony_ci .mask = RK818_IRQ_PLUG_OUT_MSK, 6003d0407baSopenharmony_ci .reg_offset = 1, 6013d0407baSopenharmony_ci }, 6023d0407baSopenharmony_ci [RK818_IRQ_CHG_OK] = 6033d0407baSopenharmony_ci { 6043d0407baSopenharmony_ci .mask = RK818_IRQ_CHG_OK_MSK, 6053d0407baSopenharmony_ci .reg_offset = 1, 6063d0407baSopenharmony_ci }, 6073d0407baSopenharmony_ci [RK818_IRQ_CHG_TE] = 6083d0407baSopenharmony_ci { 6093d0407baSopenharmony_ci .mask = RK818_IRQ_CHG_TE_MSK, 6103d0407baSopenharmony_ci .reg_offset = 1, 6113d0407baSopenharmony_ci }, 6123d0407baSopenharmony_ci [RK818_IRQ_CHG_TS1] = 6133d0407baSopenharmony_ci { 6143d0407baSopenharmony_ci .mask = RK818_IRQ_CHG_TS1_MSK, 6153d0407baSopenharmony_ci .reg_offset = 1, 6163d0407baSopenharmony_ci }, 6173d0407baSopenharmony_ci [RK818_IRQ_TS2] = 6183d0407baSopenharmony_ci { 6193d0407baSopenharmony_ci .mask = RK818_IRQ_TS2_MSK, 6203d0407baSopenharmony_ci .reg_offset = 1, 6213d0407baSopenharmony_ci }, 6223d0407baSopenharmony_ci [RK818_IRQ_CHG_CVTLIM] = 6233d0407baSopenharmony_ci { 6243d0407baSopenharmony_ci .mask = RK818_IRQ_CHG_CVTLIM_MSK, 6253d0407baSopenharmony_ci .reg_offset = 1, 6263d0407baSopenharmony_ci }, 6273d0407baSopenharmony_ci [RK818_IRQ_DISCHG_ILIM] = 6283d0407baSopenharmony_ci { 6293d0407baSopenharmony_ci .mask = RK818_IRQ_DISCHG_ILIM_MSK, 6303d0407baSopenharmony_ci .reg_offset = 1, 6313d0407baSopenharmony_ci }, 6323d0407baSopenharmony_ci}; 6333d0407baSopenharmony_ci 6343d0407baSopenharmony_cistatic const struct regmap_irq rk817_irqs[RK817_IRQ_END] = { 6353d0407baSopenharmony_ci REGMAP_IRQ_REG_LINE(0, 8), REGMAP_IRQ_REG_LINE(1, 8), REGMAP_IRQ_REG_LINE(2, 8), REGMAP_IRQ_REG_LINE(3, 8), 6363d0407baSopenharmony_ci REGMAP_IRQ_REG_LINE(4, 8), REGMAP_IRQ_REG_LINE(5, 8), REGMAP_IRQ_REG_LINE(6, 8), REGMAP_IRQ_REG_LINE(7, 8), 6373d0407baSopenharmony_ci REGMAP_IRQ_REG_LINE(8, 8), REGMAP_IRQ_REG_LINE(9, 8), REGMAP_IRQ_REG_LINE(10, 8), REGMAP_IRQ_REG_LINE(11, 8), 6383d0407baSopenharmony_ci REGMAP_IRQ_REG_LINE(12, 8), REGMAP_IRQ_REG_LINE(13, 8), REGMAP_IRQ_REG_LINE(14, 8), REGMAP_IRQ_REG_LINE(15, 8), 6393d0407baSopenharmony_ci REGMAP_IRQ_REG_LINE(16, 8), REGMAP_IRQ_REG_LINE(17, 8), REGMAP_IRQ_REG_LINE(18, 8), REGMAP_IRQ_REG_LINE(19, 8), 6403d0407baSopenharmony_ci REGMAP_IRQ_REG_LINE(20, 8), REGMAP_IRQ_REG_LINE(21, 8), REGMAP_IRQ_REG_LINE(22, 8), REGMAP_IRQ_REG_LINE(23, 8)}; 6413d0407baSopenharmony_ci 6423d0407baSopenharmony_cistatic struct regmap_irq_chip rk805_irq_chip = { 6433d0407baSopenharmony_ci .name = "rk805", 6443d0407baSopenharmony_ci .irqs = rk805_irqs, 6453d0407baSopenharmony_ci .num_irqs = ARRAY_SIZE(rk805_irqs), 6463d0407baSopenharmony_ci .num_regs = 1, 6473d0407baSopenharmony_ci .status_base = RK805_INT_STS_REG, 6483d0407baSopenharmony_ci .mask_base = RK805_INT_STS_MSK_REG, 6493d0407baSopenharmony_ci .ack_base = RK805_INT_STS_REG, 6503d0407baSopenharmony_ci .init_ack_masked = true, 6513d0407baSopenharmony_ci}; 6523d0407baSopenharmony_ci 6533d0407baSopenharmony_cistatic const struct regmap_irq_chip rk808_irq_chip = { 6543d0407baSopenharmony_ci .name = "rk808", 6553d0407baSopenharmony_ci .irqs = rk808_irqs, 6563d0407baSopenharmony_ci .num_irqs = ARRAY_SIZE(rk808_irqs), 6573d0407baSopenharmony_ci .num_regs = 2, 6583d0407baSopenharmony_ci .irq_reg_stride = 2, 6593d0407baSopenharmony_ci .status_base = RK808_INT_STS_REG1, 6603d0407baSopenharmony_ci .mask_base = RK808_INT_STS_MSK_REG1, 6613d0407baSopenharmony_ci .ack_base = RK808_INT_STS_REG1, 6623d0407baSopenharmony_ci .init_ack_masked = true, 6633d0407baSopenharmony_ci}; 6643d0407baSopenharmony_ci 6653d0407baSopenharmony_cistatic const struct regmap_irq rk816_battery_irqs[] = { 6663d0407baSopenharmony_ci /* INT_STS */ 6673d0407baSopenharmony_ci [RK816_IRQ_PLUG_IN] = 6683d0407baSopenharmony_ci { 6693d0407baSopenharmony_ci .mask = RK816_IRQ_PLUG_IN_MSK, 6703d0407baSopenharmony_ci .reg_offset = 0, 6713d0407baSopenharmony_ci }, 6723d0407baSopenharmony_ci [RK816_IRQ_PLUG_OUT] = 6733d0407baSopenharmony_ci { 6743d0407baSopenharmony_ci .mask = RK816_IRQ_PLUG_OUT_MSK, 6753d0407baSopenharmony_ci .reg_offset = 0, 6763d0407baSopenharmony_ci }, 6773d0407baSopenharmony_ci [RK816_IRQ_CHG_OK] = 6783d0407baSopenharmony_ci { 6793d0407baSopenharmony_ci .mask = RK816_IRQ_CHG_OK_MSK, 6803d0407baSopenharmony_ci .reg_offset = 0, 6813d0407baSopenharmony_ci }, 6823d0407baSopenharmony_ci [RK816_IRQ_CHG_TE] = 6833d0407baSopenharmony_ci { 6843d0407baSopenharmony_ci .mask = RK816_IRQ_CHG_TE_MSK, 6853d0407baSopenharmony_ci .reg_offset = 0, 6863d0407baSopenharmony_ci }, 6873d0407baSopenharmony_ci [RK816_IRQ_CHG_TS] = 6883d0407baSopenharmony_ci { 6893d0407baSopenharmony_ci .mask = RK816_IRQ_CHG_TS_MSK, 6903d0407baSopenharmony_ci .reg_offset = 0, 6913d0407baSopenharmony_ci }, 6923d0407baSopenharmony_ci [RK816_IRQ_CHG_CVTLIM] = 6933d0407baSopenharmony_ci { 6943d0407baSopenharmony_ci .mask = RK816_IRQ_CHG_CVTLIM_MSK, 6953d0407baSopenharmony_ci .reg_offset = 0, 6963d0407baSopenharmony_ci }, 6973d0407baSopenharmony_ci [RK816_IRQ_DISCHG_ILIM] = 6983d0407baSopenharmony_ci { 6993d0407baSopenharmony_ci .mask = RK816_IRQ_DISCHG_ILIM_MSK, 7003d0407baSopenharmony_ci .reg_offset = 0, 7013d0407baSopenharmony_ci }, 7023d0407baSopenharmony_ci}; 7033d0407baSopenharmony_ci 7043d0407baSopenharmony_cistatic struct regmap_irq_chip rk816_irq_chip = { 7053d0407baSopenharmony_ci .name = "rk816", 7063d0407baSopenharmony_ci .irqs = rk816_irqs, 7073d0407baSopenharmony_ci .num_irqs = ARRAY_SIZE(rk816_irqs), 7083d0407baSopenharmony_ci .num_regs = 2, 7093d0407baSopenharmony_ci .irq_reg_stride = 3, 7103d0407baSopenharmony_ci .status_base = RK816_INT_STS_REG1, 7113d0407baSopenharmony_ci .mask_base = RK816_INT_STS_MSK_REG1, 7123d0407baSopenharmony_ci .ack_base = RK816_INT_STS_REG1, 7133d0407baSopenharmony_ci .init_ack_masked = true, 7143d0407baSopenharmony_ci}; 7153d0407baSopenharmony_ci 7163d0407baSopenharmony_cistatic struct regmap_irq_chip rk816_battery_irq_chip = { 7173d0407baSopenharmony_ci .name = "rk816_battery", 7183d0407baSopenharmony_ci .irqs = rk816_battery_irqs, 7193d0407baSopenharmony_ci .num_irqs = ARRAY_SIZE(rk816_battery_irqs), 7203d0407baSopenharmony_ci .num_regs = 1, 7213d0407baSopenharmony_ci .status_base = RK816_INT_STS_REG3, 7223d0407baSopenharmony_ci .mask_base = RK816_INT_STS_MSK_REG3, 7233d0407baSopenharmony_ci .ack_base = RK816_INT_STS_REG3, 7243d0407baSopenharmony_ci .init_ack_masked = true, 7253d0407baSopenharmony_ci}; 7263d0407baSopenharmony_ci 7273d0407baSopenharmony_cistatic struct regmap_irq_chip rk817_irq_chip = { 7283d0407baSopenharmony_ci .name = "rk817", 7293d0407baSopenharmony_ci .irqs = rk817_irqs, 7303d0407baSopenharmony_ci .num_irqs = ARRAY_SIZE(rk817_irqs), 7313d0407baSopenharmony_ci .num_regs = 3, 7323d0407baSopenharmony_ci .irq_reg_stride = 2, 7333d0407baSopenharmony_ci .status_base = RK817_INT_STS_REG0, 7343d0407baSopenharmony_ci .mask_base = RK817_INT_STS_MSK_REG0, 7353d0407baSopenharmony_ci .ack_base = RK817_INT_STS_REG0, 7363d0407baSopenharmony_ci .init_ack_masked = true, 7373d0407baSopenharmony_ci}; 7383d0407baSopenharmony_ci 7393d0407baSopenharmony_cistatic const struct regmap_irq_chip rk818_irq_chip = { 7403d0407baSopenharmony_ci .name = "rk818", 7413d0407baSopenharmony_ci .irqs = rk818_irqs, 7423d0407baSopenharmony_ci .num_irqs = ARRAY_SIZE(rk818_irqs), 7433d0407baSopenharmony_ci .num_regs = 2, 7443d0407baSopenharmony_ci .irq_reg_stride = 2, 7453d0407baSopenharmony_ci .status_base = RK818_INT_STS_REG1, 7463d0407baSopenharmony_ci .mask_base = RK818_INT_STS_MSK_REG1, 7473d0407baSopenharmony_ci .ack_base = RK818_INT_STS_REG1, 7483d0407baSopenharmony_ci .init_ack_masked = true, 7493d0407baSopenharmony_ci}; 7503d0407baSopenharmony_ci 7513d0407baSopenharmony_cistatic struct i2c_client *rk808_i2c_client; 7523d0407baSopenharmony_cistatic struct rk808_reg_data *suspend_reg, *resume_reg; 7533d0407baSopenharmony_cistatic int suspend_reg_num, resume_reg_num; 7543d0407baSopenharmony_ci 7553d0407baSopenharmony_cistatic void rk805_device_shutdown_prepare(void) 7563d0407baSopenharmony_ci{ 7573d0407baSopenharmony_ci int ret; 7583d0407baSopenharmony_ci struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); 7593d0407baSopenharmony_ci 7603d0407baSopenharmony_ci if (!rk808) { 7613d0407baSopenharmony_ci return; 7623d0407baSopenharmony_ci } 7633d0407baSopenharmony_ci 7643d0407baSopenharmony_ci ret = regmap_update_bits(rk808->regmap, RK805_GPIO_IO_POL_REG, SLP_SD_MSK, SHUTDOWN_FUN); 7653d0407baSopenharmony_ci if (ret) { 7663d0407baSopenharmony_ci dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n"); 7673d0407baSopenharmony_ci } 7683d0407baSopenharmony_ci} 7693d0407baSopenharmony_ci 7703d0407baSopenharmony_cistatic void rk817_shutdown_prepare(void) 7713d0407baSopenharmony_ci{ 7723d0407baSopenharmony_ci int ret; 7733d0407baSopenharmony_ci struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); 7743d0407baSopenharmony_ci 7753d0407baSopenharmony_ci /* close rtc int when power off */ 7763d0407baSopenharmony_ci regmap_update_bits(rk808->regmap, RK817_INT_STS_MSK_REG0, (RK_REG_VAL_THREE << RK_REG_SHIFT_MASK_FIVE), 7773d0407baSopenharmony_ci (RK_REG_VAL_THREE << RK_REG_SHIFT_MASK_FIVE)); 7783d0407baSopenharmony_ci regmap_update_bits(rk808->regmap, RK817_RTC_INT_REG, (RK_REG_VAL_THREE << RK_REG_SHIFT_MASK_TWO), 7793d0407baSopenharmony_ci (RK_REG_VAL_ZERO << RK_REG_SHIFT_MASK_TWO)); 7803d0407baSopenharmony_ci 7813d0407baSopenharmony_ci if (rk808->pins && rk808->pins->p && rk808->pins->power_off) { 7823d0407baSopenharmony_ci ret = 7833d0407baSopenharmony_ci regmap_update_bits(rk808->regmap, RK817_SYS_CFG(RK_REG_VAL_THREE), RK817_SLPPIN_FUNC_MSK, SLPPIN_NULL_FUN); 7843d0407baSopenharmony_ci if (ret) { 7853d0407baSopenharmony_ci pr_err("shutdown: config SLPPIN_NULL_FUN error!\n"); 7863d0407baSopenharmony_ci } 7873d0407baSopenharmony_ci 7883d0407baSopenharmony_ci ret = regmap_update_bits(rk808->regmap, RK817_SYS_CFG(RK_REG_VAL_THREE), RK817_SLPPOL_MSK, RK817_SLPPOL_H); 7893d0407baSopenharmony_ci if (ret) { 7903d0407baSopenharmony_ci pr_err("shutdown: config RK817_SLPPOL_H error!\n"); 7913d0407baSopenharmony_ci } 7923d0407baSopenharmony_ci 7933d0407baSopenharmony_ci ret = pinctrl_select_state(rk808->pins->p, rk808->pins->power_off); 7943d0407baSopenharmony_ci if (ret) { 7953d0407baSopenharmony_ci pr_info("%s:failed to activate pwroff state\n", __func__); 7963d0407baSopenharmony_ci } 7973d0407baSopenharmony_ci } 7983d0407baSopenharmony_ci 7993d0407baSopenharmony_ci /* pmic sleep shutdown function */ 8003d0407baSopenharmony_ci ret = regmap_update_bits(rk808->regmap, RK817_SYS_CFG(RK_REG_VAL_THREE), RK817_SLPPIN_FUNC_MSK, SLPPIN_DN_FUN); 8013d0407baSopenharmony_ci if (ret) { 8023d0407baSopenharmony_ci dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n"); 8033d0407baSopenharmony_ci } 8043d0407baSopenharmony_ci /* pmic need the SCL clock to synchronize register */ 8053d0407baSopenharmony_ci mdelay(RK_DELAY_COUNT_TWO_MS); 8063d0407baSopenharmony_ci} 8073d0407baSopenharmony_ci 8083d0407baSopenharmony_cistatic void rk8xx_device_shutdown(void) 8093d0407baSopenharmony_ci{ 8103d0407baSopenharmony_ci int ret; 8113d0407baSopenharmony_ci unsigned int reg, bit; 8123d0407baSopenharmony_ci struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); 8133d0407baSopenharmony_ci 8143d0407baSopenharmony_ci switch (rk808->variant) { 8153d0407baSopenharmony_ci case RK805_ID: 8163d0407baSopenharmony_ci reg = RK805_DEV_CTRL_REG; 8173d0407baSopenharmony_ci bit = DEV_OFF; 8183d0407baSopenharmony_ci break; 8193d0407baSopenharmony_ci case RK808_ID: 8203d0407baSopenharmony_ci reg = RK808_DEVCTRL_REG, bit = DEV_OFF_RST; 8213d0407baSopenharmony_ci break; 8223d0407baSopenharmony_ci case RK816_ID: 8233d0407baSopenharmony_ci reg = RK816_DEV_CTRL_REG; 8243d0407baSopenharmony_ci bit = DEV_OFF; 8253d0407baSopenharmony_ci break; 8263d0407baSopenharmony_ci case RK818_ID: 8273d0407baSopenharmony_ci reg = RK818_DEVCTRL_REG; 8283d0407baSopenharmony_ci bit = DEV_OFF; 8293d0407baSopenharmony_ci break; 8303d0407baSopenharmony_ci default: 8313d0407baSopenharmony_ci return; 8323d0407baSopenharmony_ci } 8333d0407baSopenharmony_ci 8343d0407baSopenharmony_ci ret = regmap_update_bits(rk808->regmap, reg, bit, bit); 8353d0407baSopenharmony_ci if (ret) { 8363d0407baSopenharmony_ci dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n"); 8373d0407baSopenharmony_ci } 8383d0407baSopenharmony_ci} 8393d0407baSopenharmony_ci 8403d0407baSopenharmony_ci/* Called in syscore shutdown */ 8413d0407baSopenharmony_cistatic void (*pm_shutdown)(void); 8423d0407baSopenharmony_ci 8433d0407baSopenharmony_cistatic void rk8xx_syscore_shutdown(void) 8443d0407baSopenharmony_ci{ 8453d0407baSopenharmony_ci int ret; 8463d0407baSopenharmony_ci struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); 8473d0407baSopenharmony_ci 8483d0407baSopenharmony_ci if (!rk808) { 8493d0407baSopenharmony_ci dev_warn(&rk808_i2c_client->dev, "have no rk808, so do nothing here\n"); 8503d0407baSopenharmony_ci return; 8513d0407baSopenharmony_ci } 8523d0407baSopenharmony_ci 8533d0407baSopenharmony_ci /* close rtc int when power off */ 8543d0407baSopenharmony_ci regmap_update_bits(rk808->regmap, RK808_INT_STS_MSK_REG1, (RK_REG_VAL_THREE << RK_REG_SHIFT_MASK_FIVE), 8553d0407baSopenharmony_ci (RK_REG_VAL_THREE << RK_REG_SHIFT_MASK_FIVE)); 8563d0407baSopenharmony_ci regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG, (RK_REG_VAL_THREE << RK_REG_SHIFT_MASK_TWO), 8573d0407baSopenharmony_ci (RK_REG_VAL_ZERO << RK_REG_SHIFT_MASK_TWO)); 8583d0407baSopenharmony_ci /* 8593d0407baSopenharmony_ci * For PMIC that power off supplies by write register via i2c bus, 8603d0407baSopenharmony_ci * it's better to do power off at syscore shutdown here. 8613d0407baSopenharmony_ci * 8623d0407baSopenharmony_ci * Because when run to kernel's "pm_power_off" call, i2c may has 8633d0407baSopenharmony_ci * been stopped or PMIC may not be able to get i2c transfer while 8643d0407baSopenharmony_ci * there are too many devices are competiting. 8653d0407baSopenharmony_ci */ 8663d0407baSopenharmony_ci if (system_state == SYSTEM_POWER_OFF) { 8673d0407baSopenharmony_ci if (rk808->variant == RK809_ID || rk808->variant == RK817_ID) { 8683d0407baSopenharmony_ci ret = regmap_update_bits(rk808->regmap, RK817_SYS_CFG(RK_REG_VAL_THREE), RK817_SLPPIN_FUNC_MSK, 8693d0407baSopenharmony_ci SLPPIN_DN_FUN); 8703d0407baSopenharmony_ci if (ret) { 8713d0407baSopenharmony_ci dev_warn(&rk808_i2c_client->dev, "Cannot switch to power down function\n"); 8723d0407baSopenharmony_ci } 8733d0407baSopenharmony_ci } 8743d0407baSopenharmony_ci 8753d0407baSopenharmony_ci if (pm_shutdown) { 8763d0407baSopenharmony_ci dev_info(&rk808_i2c_client->dev, "System power off\n"); 8773d0407baSopenharmony_ci pm_shutdown(); 8783d0407baSopenharmony_ci mdelay(RK_DELAY_COUNT_TEN_MS); 8793d0407baSopenharmony_ci dev_info(&rk808_i2c_client->dev, "Power off failed !\n"); 8803d0407baSopenharmony_ci while (1) { 8813d0407baSopenharmony_ci ; 8823d0407baSopenharmony_ci } 8833d0407baSopenharmony_ci } 8843d0407baSopenharmony_ci } 8853d0407baSopenharmony_ci} 8863d0407baSopenharmony_ci 8873d0407baSopenharmony_cistatic struct syscore_ops rk808_syscore_ops = { 8883d0407baSopenharmony_ci .shutdown = rk8xx_syscore_shutdown, 8893d0407baSopenharmony_ci}; 8903d0407baSopenharmony_ci 8913d0407baSopenharmony_ci/* 8923d0407baSopenharmony_ci * RK8xx PMICs would do real power off in syscore shutdown, if "pm_power_off" 8933d0407baSopenharmony_ci * is not assigned(e.g. PSCI is not enabled), we have to provide a dummy 8943d0407baSopenharmony_ci * callback for it, otherwise there comes a halt in Reboot system call: 8953d0407baSopenharmony_ci * 8963d0407baSopenharmony_ci * if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off) 8973d0407baSopenharmony_ci * cmd = LINUX_REBOOT_CMD_HALT; 8983d0407baSopenharmony_ci */ 8993d0407baSopenharmony_cistatic void rk808_pm_power_off_dummy(void) 9003d0407baSopenharmony_ci{ 9013d0407baSopenharmony_ci pr_info("Dummy power off for RK8xx PMICs, should never reach here!\n"); 9023d0407baSopenharmony_ci 9033d0407baSopenharmony_ci while (1) { 9043d0407baSopenharmony_ci ; 9053d0407baSopenharmony_ci } 9063d0407baSopenharmony_ci} 9073d0407baSopenharmony_ci 9083d0407baSopenharmony_cistatic ssize_t rk8xx_dbg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 9093d0407baSopenharmony_ci{ 9103d0407baSopenharmony_ci int ret; 9113d0407baSopenharmony_ci char cmd; 9123d0407baSopenharmony_ci u32 input[2], addr, data; 9133d0407baSopenharmony_ci struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); 9143d0407baSopenharmony_ci 9153d0407baSopenharmony_ci ret = sscanf(buf, "%c ", &cmd); 9163d0407baSopenharmony_ci if (ret != RK_SSCAN_RET_RESULT_ONE) { 9173d0407baSopenharmony_ci pr_err("Unknown command\n"); 9183d0407baSopenharmony_ci goto out; 9193d0407baSopenharmony_ci } 9203d0407baSopenharmony_ci switch (cmd) { 9213d0407baSopenharmony_ci case 'w': 9223d0407baSopenharmony_ci ret = sscanf(buf, "%c %x %x ", &cmd, &input[0], &input[1]); 9233d0407baSopenharmony_ci if (ret != RK_SSCAN_RET_RESULT_THREE) { 9243d0407baSopenharmony_ci pr_err("error! cmd format: echo w [addr] [value]\n"); 9253d0407baSopenharmony_ci goto out; 9263d0407baSopenharmony_ci }; 9273d0407baSopenharmony_ci addr = input[0] & RK_INPUT_MASK; 9283d0407baSopenharmony_ci data = input[1] & RK_INPUT_MASK; 9293d0407baSopenharmony_ci pr_info("cmd : %c %x %x\n\n", cmd, input[0], input[1]); 9303d0407baSopenharmony_ci regmap_write(rk808->regmap, addr, data); 9313d0407baSopenharmony_ci regmap_read(rk808->regmap, addr, &data); 9323d0407baSopenharmony_ci pr_info("new: %x %x\n", addr, data); 9333d0407baSopenharmony_ci break; 9343d0407baSopenharmony_ci case 'r': 9353d0407baSopenharmony_ci ret = sscanf(buf, "%c %x ", &cmd, &input[0]); 9363d0407baSopenharmony_ci if (ret != RK_SSCAN_RET_RESULT_TWO) { 9373d0407baSopenharmony_ci pr_err("error! cmd format: echo r [addr]\n"); 9383d0407baSopenharmony_ci goto out; 9393d0407baSopenharmony_ci }; 9403d0407baSopenharmony_ci pr_info("cmd : %c %x\n\n", cmd, input[0]); 9413d0407baSopenharmony_ci addr = input[0] & RK_INPUT_MASK; 9423d0407baSopenharmony_ci regmap_read(rk808->regmap, addr, &data); 9433d0407baSopenharmony_ci pr_info("%x %x\n", input[0], data); 9443d0407baSopenharmony_ci break; 9453d0407baSopenharmony_ci default: 9463d0407baSopenharmony_ci pr_err("Unknown command\n"); 9473d0407baSopenharmony_ci break; 9483d0407baSopenharmony_ci } 9493d0407baSopenharmony_ci 9503d0407baSopenharmony_ciout: 9513d0407baSopenharmony_ci return count; 9523d0407baSopenharmony_ci} 9533d0407baSopenharmony_ci 9543d0407baSopenharmony_cistatic int rk817_pinctrl_init(struct device *dev, struct rk808 *rk808) 9553d0407baSopenharmony_ci{ 9563d0407baSopenharmony_ci int ret; 9573d0407baSopenharmony_ci struct platform_device *pinctrl_dev; 9583d0407baSopenharmony_ci struct pinctrl_state *default_st; 9593d0407baSopenharmony_ci 9603d0407baSopenharmony_ci pinctrl_dev = platform_device_alloc("rk805-pinctrl", -1); 9613d0407baSopenharmony_ci if (!pinctrl_dev) { 9623d0407baSopenharmony_ci dev_err(dev, "Alloc pinctrl dev failed!\n"); 9633d0407baSopenharmony_ci return -ENOMEM; 9643d0407baSopenharmony_ci } 9653d0407baSopenharmony_ci 9663d0407baSopenharmony_ci pinctrl_dev->dev.parent = dev; 9673d0407baSopenharmony_ci ret = platform_device_add(pinctrl_dev); 9683d0407baSopenharmony_ci if (ret) { 9693d0407baSopenharmony_ci platform_device_put(pinctrl_dev); 9703d0407baSopenharmony_ci dev_err(dev, "Add rk805-pinctrl dev failed!\n"); 9713d0407baSopenharmony_ci return ret; 9723d0407baSopenharmony_ci } 9733d0407baSopenharmony_ci if (dev->pins && !IS_ERR(dev->pins->p)) { 9743d0407baSopenharmony_ci dev_info(dev, "had get a pinctrl!\n"); 9753d0407baSopenharmony_ci return 0; 9763d0407baSopenharmony_ci } 9773d0407baSopenharmony_ci 9783d0407baSopenharmony_ci rk808->pins = devm_kzalloc(dev, sizeof(struct rk808_pin_info), GFP_KERNEL); 9793d0407baSopenharmony_ci if (!rk808->pins) { 9803d0407baSopenharmony_ci return -ENOMEM; 9813d0407baSopenharmony_ci } 9823d0407baSopenharmony_ci 9833d0407baSopenharmony_ci rk808->pins->p = devm_pinctrl_get(dev); 9843d0407baSopenharmony_ci if (IS_ERR(rk808->pins->p)) { 9853d0407baSopenharmony_ci rk808->pins->p = NULL; 9863d0407baSopenharmony_ci dev_err(dev, "no pinctrl handle\n"); 9873d0407baSopenharmony_ci return 0; 9883d0407baSopenharmony_ci } 9893d0407baSopenharmony_ci default_st = pinctrl_lookup_state(rk808->pins->p, PINCTRL_STATE_DEFAULT); 9903d0407baSopenharmony_ci if (IS_ERR(default_st)) { 9913d0407baSopenharmony_ci dev_dbg(dev, "no default pinctrl state\n"); 9923d0407baSopenharmony_ci return -EINVAL; 9933d0407baSopenharmony_ci } 9943d0407baSopenharmony_ci 9953d0407baSopenharmony_ci ret = pinctrl_select_state(rk808->pins->p, default_st); 9963d0407baSopenharmony_ci if (ret) { 9973d0407baSopenharmony_ci dev_dbg(dev, "failed to activate default pinctrl state\n"); 9983d0407baSopenharmony_ci return -EINVAL; 9993d0407baSopenharmony_ci } 10003d0407baSopenharmony_ci 10013d0407baSopenharmony_ci rk808->pins->power_off = pinctrl_lookup_state(rk808->pins->p, "pmic-power-off"); 10023d0407baSopenharmony_ci if (IS_ERR(rk808->pins->power_off)) { 10033d0407baSopenharmony_ci rk808->pins->power_off = NULL; 10043d0407baSopenharmony_ci dev_dbg(dev, "no power-off pinctrl state\n"); 10053d0407baSopenharmony_ci } 10063d0407baSopenharmony_ci 10073d0407baSopenharmony_ci rk808->pins->sleep = pinctrl_lookup_state(rk808->pins->p, "pmic-sleep"); 10083d0407baSopenharmony_ci if (IS_ERR(rk808->pins->sleep)) { 10093d0407baSopenharmony_ci rk808->pins->sleep = NULL; 10103d0407baSopenharmony_ci dev_dbg(dev, "no sleep-setting state\n"); 10113d0407baSopenharmony_ci } 10123d0407baSopenharmony_ci 10133d0407baSopenharmony_ci rk808->pins->reset = pinctrl_lookup_state(rk808->pins->p, "pmic-reset"); 10143d0407baSopenharmony_ci if (IS_ERR(rk808->pins->reset)) { 10153d0407baSopenharmony_ci rk808->pins->reset = NULL; 10163d0407baSopenharmony_ci dev_dbg(dev, "no reset-setting pinctrl state\n"); 10173d0407baSopenharmony_ci return 0; 10183d0407baSopenharmony_ci } 10193d0407baSopenharmony_ci ret = pinctrl_select_state(rk808->pins->p, rk808->pins->reset); 10203d0407baSopenharmony_ci if (ret) { 10213d0407baSopenharmony_ci dev_dbg(dev, "failed to activate reset-setting pinctrl state\n"); 10223d0407baSopenharmony_ci } 10233d0407baSopenharmony_ci 10243d0407baSopenharmony_ci return 0; 10253d0407baSopenharmony_ci} 10263d0407baSopenharmony_ci 10273d0407baSopenharmony_cistruct rk817_reboot_data_t { 10283d0407baSopenharmony_ci struct rk808 *rk808; 10293d0407baSopenharmony_ci struct notifier_block reboot_notifier; 10303d0407baSopenharmony_ci}; 10313d0407baSopenharmony_ci 10323d0407baSopenharmony_cistatic struct rk817_reboot_data_t rk817_reboot_data; 10333d0407baSopenharmony_ci 10343d0407baSopenharmony_cistatic int rk817_reboot_notifier_handler(struct notifier_block *nb, unsigned long action, void *cmd) 10353d0407baSopenharmony_ci{ 10363d0407baSopenharmony_ci struct rk817_reboot_data_t *data; 10373d0407baSopenharmony_ci struct device *dev; 10383d0407baSopenharmony_ci int value, power_en_active0, power_en_active1; 10393d0407baSopenharmony_ci int ret, i; 10403d0407baSopenharmony_ci static const char *const pmic_rst_reg_only_cmd[] = { 10413d0407baSopenharmony_ci "loader", "bootloader", "fastboot", "recovery", "ums", "panic", "watchdog", "charge", 10423d0407baSopenharmony_ci }; 10433d0407baSopenharmony_ci 10443d0407baSopenharmony_ci data = container_of(nb, struct rk817_reboot_data_t, reboot_notifier); 10453d0407baSopenharmony_ci dev = &data->rk808->i2c->dev; 10463d0407baSopenharmony_ci 10473d0407baSopenharmony_ci regmap_read(data->rk808->regmap, RK817_POWER_EN_SAVE0, &power_en_active0); 10483d0407baSopenharmony_ci if (power_en_active0 != 0) { 10493d0407baSopenharmony_ci regmap_read(data->rk808->regmap, RK817_POWER_EN_SAVE1, &power_en_active1); 10503d0407baSopenharmony_ci value = power_en_active0 & RK_BYTE_LOW_FOUR_BIT_MASK; 10513d0407baSopenharmony_ci regmap_write(data->rk808->regmap, RK817_POWER_EN_REG(RK_POWER_EN_REG_VALUE_ZERO), 10523d0407baSopenharmony_ci value | RK_BYTE_HIGH_FOUR_BIT_MASK); 10533d0407baSopenharmony_ci value = (power_en_active0 & RK_BYTE_HIGH_FOUR_BIT_MASK) >> RK_BYTE_FOUR_BIT_SHIFT_MASK; 10543d0407baSopenharmony_ci regmap_write(data->rk808->regmap, RK817_POWER_EN_REG(RK_POWER_EN_REG_VALUE_ONE), 10553d0407baSopenharmony_ci value | RK_BYTE_HIGH_FOUR_BIT_MASK); 10563d0407baSopenharmony_ci value = power_en_active1 & RK_BYTE_LOW_FOUR_BIT_MASK; 10573d0407baSopenharmony_ci regmap_write(data->rk808->regmap, RK817_POWER_EN_REG(RK_POWER_EN_REG_VALUE_TWO), 10583d0407baSopenharmony_ci value | RK_BYTE_HIGH_FOUR_BIT_MASK); 10593d0407baSopenharmony_ci value = (power_en_active1 & RK_BYTE_HIGH_FOUR_BIT_MASK) >> RK_BYTE_FOUR_BIT_SHIFT_MASK; 10603d0407baSopenharmony_ci regmap_write(data->rk808->regmap, RK817_POWER_EN_REG(RK_POWER_EN_REG_VALUE_THREE), 10613d0407baSopenharmony_ci value | RK_BYTE_HIGH_FOUR_BIT_MASK); 10623d0407baSopenharmony_ci } else { 10633d0407baSopenharmony_ci dev_info(dev, "reboot: not restore POWER_EN\n"); 10643d0407baSopenharmony_ci } 10653d0407baSopenharmony_ci 10663d0407baSopenharmony_ci if (action != SYS_RESTART || !cmd) { 10673d0407baSopenharmony_ci return NOTIFY_OK; 10683d0407baSopenharmony_ci } 10693d0407baSopenharmony_ci 10703d0407baSopenharmony_ci /* 10713d0407baSopenharmony_ci * When system restart, there are two rst actions of PMIC sleep if 10723d0407baSopenharmony_ci * board hardware support: 10733d0407baSopenharmony_ci * 10743d0407baSopenharmony_ci * 0b'00: reset the PMIC itself completely. 10753d0407baSopenharmony_ci * 0b'01: reset the 'RST' related register only. 10763d0407baSopenharmony_ci * 10773d0407baSopenharmony_ci * In the case of 0b'00, PMIC reset itself which triggers SoC NPOR-reset 10783d0407baSopenharmony_ci * at the same time, so the command: reboot load/bootload/recovery, etc 10793d0407baSopenharmony_ci * is not effect any more. 10803d0407baSopenharmony_ci * 10813d0407baSopenharmony_ci * Here we check if this reboot cmd is what we expect for 0b'01. 10823d0407baSopenharmony_ci */ 10833d0407baSopenharmony_ci for (i = 0; i < ARRAY_SIZE(pmic_rst_reg_only_cmd); i++) { 10843d0407baSopenharmony_ci if (!strcmp(cmd, pmic_rst_reg_only_cmd[i])) { 10853d0407baSopenharmony_ci ret = regmap_update_bits(data->rk808->regmap, RK817_SYS_CFG(RK_REG_VAL_THREE), RK817_RST_FUNC_MSK, 10863d0407baSopenharmony_ci RK817_RST_FUNC_REG); 10873d0407baSopenharmony_ci if (ret) { 10883d0407baSopenharmony_ci dev_err(dev, "reboot: force RK817_RST_FUNC_REG error!\n"); 10893d0407baSopenharmony_ci } else { 10903d0407baSopenharmony_ci dev_info(dev, "reboot: force RK817_RST_FUNC_REG ok!\n"); 10913d0407baSopenharmony_ci } 10923d0407baSopenharmony_ci break; 10933d0407baSopenharmony_ci } 10943d0407baSopenharmony_ci } 10953d0407baSopenharmony_ci 10963d0407baSopenharmony_ci return NOTIFY_OK; 10973d0407baSopenharmony_ci} 10983d0407baSopenharmony_ci 10993d0407baSopenharmony_cistatic void rk817_of_property_prepare(struct rk808 *rk808, struct device *dev) 11003d0407baSopenharmony_ci{ 11013d0407baSopenharmony_ci u32 inner; 11023d0407baSopenharmony_ci int ret, func, msk, val; 11033d0407baSopenharmony_ci struct device_node *np = dev->of_node; 11043d0407baSopenharmony_ci 11053d0407baSopenharmony_ci ret = of_property_read_u32_index(np, "fb-inner-reg-idxs", 0, &inner); 11063d0407baSopenharmony_ci if (!ret && inner == RK817_ID_DCDC3) { 11073d0407baSopenharmony_ci regmap_update_bits(rk808->regmap, RK817_POWER_CONFIG, RK817_BUCK3_FB_RES_MSK, RK817_BUCK3_FB_RES_INTER); 11083d0407baSopenharmony_ci } else { 11093d0407baSopenharmony_ci regmap_update_bits(rk808->regmap, RK817_POWER_CONFIG, RK817_BUCK3_FB_RES_MSK, RK817_BUCK3_FB_RES_EXT); 11103d0407baSopenharmony_ci } 11113d0407baSopenharmony_ci dev_info(dev, "support dcdc3 fb mode:%d, %d\n", ret, inner); 11123d0407baSopenharmony_ci 11133d0407baSopenharmony_ci ret = of_property_read_u32(np, "pmic-reset-func", &func); 11143d0407baSopenharmony_ci 11153d0407baSopenharmony_ci msk = RK817_SLPPIN_FUNC_MSK | RK817_RST_FUNC_MSK; 11163d0407baSopenharmony_ci val = SLPPIN_NULL_FUN; 11173d0407baSopenharmony_ci 11183d0407baSopenharmony_ci if (!ret && func < RK817_RST_FUNC_CNT) { 11193d0407baSopenharmony_ci val |= RK817_RST_FUNC_MSK & (func << RK817_RST_FUNC_SFT); 11203d0407baSopenharmony_ci } else { 11213d0407baSopenharmony_ci val |= RK817_RST_FUNC_REG; 11223d0407baSopenharmony_ci } 11233d0407baSopenharmony_ci 11243d0407baSopenharmony_ci regmap_update_bits(rk808->regmap, RK817_SYS_CFG(RK_REG_VAL_THREE), msk, val); 11253d0407baSopenharmony_ci 11263d0407baSopenharmony_ci dev_info(dev, "support pmic reset mode:%d,%d\n", ret, func); 11273d0407baSopenharmony_ci 11283d0407baSopenharmony_ci rk817_reboot_data.rk808 = rk808; 11293d0407baSopenharmony_ci rk817_reboot_data.reboot_notifier.notifier_call = rk817_reboot_notifier_handler; 11303d0407baSopenharmony_ci ret = register_reboot_notifier(&rk817_reboot_data.reboot_notifier); 11313d0407baSopenharmony_ci if (ret) { 11323d0407baSopenharmony_ci dev_err(dev, "failed to register reboot nb\n"); 11333d0407baSopenharmony_ci } 11343d0407baSopenharmony_ci} 11353d0407baSopenharmony_ci 11363d0407baSopenharmony_cistatic struct kobject *rk8xx_kobj; 11373d0407baSopenharmony_cistatic struct device_attribute rk8xx_attrs = __ATTR(rk8xx_dbg, 0200, NULL, rk8xx_dbg_store); 11383d0407baSopenharmony_ci 11393d0407baSopenharmony_cistatic const struct of_device_id rk808_of_match[] = { 11403d0407baSopenharmony_ci {.compatible = "rockchip,rk805"}, 11413d0407baSopenharmony_ci {.compatible = "rockchip,rk808"}, 11423d0407baSopenharmony_ci {.compatible = "rockchip,rk809"}, 11433d0407baSopenharmony_ci {.compatible = "rockchip,rk816"}, 11443d0407baSopenharmony_ci {.compatible = "rockchip,rk817"}, 11453d0407baSopenharmony_ci {.compatible = "rockchip,rk818"}, 11463d0407baSopenharmony_ci {}, 11473d0407baSopenharmony_ci}; 11483d0407baSopenharmony_ciMODULE_DEVICE_TABLE(of, rk808_of_match); 11493d0407baSopenharmony_ci 11503d0407baSopenharmony_cistatic int rk808_probe(struct i2c_client *client, const struct i2c_device_id *id) 11513d0407baSopenharmony_ci{ 11523d0407baSopenharmony_ci struct device_node *np = client->dev.of_node; 11533d0407baSopenharmony_ci struct rk808 *rk808; 11543d0407baSopenharmony_ci const struct rk808_reg_data *pre_init_reg; 11553d0407baSopenharmony_ci const struct regmap_irq_chip *battery_irq_chip = NULL; 11563d0407baSopenharmony_ci const struct mfd_cell *cells; 11573d0407baSopenharmony_ci unsigned char pmic_id_msb, pmic_id_lsb; 11583d0407baSopenharmony_ci u8 on_source = 0, off_source = 0; 11593d0407baSopenharmony_ci unsigned int on, off; 11603d0407baSopenharmony_ci int pm_off = 0, msb, lsb; 11613d0407baSopenharmony_ci int nr_pre_init_regs; 11623d0407baSopenharmony_ci int nr_cells; 11633d0407baSopenharmony_ci int ret; 11643d0407baSopenharmony_ci int i; 11653d0407baSopenharmony_ci void (*of_property_prepare_fn)(struct rk808 * rk808, struct device * dev) = NULL; 11663d0407baSopenharmony_ci int (*pinctrl_init)(struct device * dev, struct rk808 * rk808) = NULL; 11673d0407baSopenharmony_ci void (*device_shutdown_fn)(void) = NULL; 11683d0407baSopenharmony_ci 11693d0407baSopenharmony_ci rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL); 11703d0407baSopenharmony_ci if (!rk808) { 11713d0407baSopenharmony_ci return -ENOMEM; 11723d0407baSopenharmony_ci } 11733d0407baSopenharmony_ci 11743d0407baSopenharmony_ci if (of_device_is_compatible(np, "rockchip,rk817") || of_device_is_compatible(np, "rockchip,rk809")) { 11753d0407baSopenharmony_ci pmic_id_msb = RK817_ID_MSB; 11763d0407baSopenharmony_ci pmic_id_lsb = RK817_ID_LSB; 11773d0407baSopenharmony_ci } else { 11783d0407baSopenharmony_ci pmic_id_msb = RK808_ID_MSB; 11793d0407baSopenharmony_ci pmic_id_lsb = RK808_ID_LSB; 11803d0407baSopenharmony_ci } 11813d0407baSopenharmony_ci 11823d0407baSopenharmony_ci /* Read chip variant */ 11833d0407baSopenharmony_ci msb = i2c_smbus_read_byte_data(client, pmic_id_msb); 11843d0407baSopenharmony_ci if (msb < 0) { 11853d0407baSopenharmony_ci dev_err(&client->dev, "failed to read the chip id at 0x%x\n", RK808_ID_MSB); 11863d0407baSopenharmony_ci return msb; 11873d0407baSopenharmony_ci } 11883d0407baSopenharmony_ci 11893d0407baSopenharmony_ci lsb = i2c_smbus_read_byte_data(client, pmic_id_lsb); 11903d0407baSopenharmony_ci if (lsb < 0) { 11913d0407baSopenharmony_ci dev_err(&client->dev, "failed to read the chip id at 0x%x\n", RK808_ID_LSB); 11923d0407baSopenharmony_ci return lsb; 11933d0407baSopenharmony_ci } 11943d0407baSopenharmony_ci 11953d0407baSopenharmony_ci rk808->variant = ((msb << RK_REG_SHIFT_MASK_EIGHT) | lsb) & RK8XX_ID_MSK; 11963d0407baSopenharmony_ci dev_info(&client->dev, "chip id: 0x%x\n", (unsigned int)rk808->variant); 11973d0407baSopenharmony_ci 11983d0407baSopenharmony_ci switch (rk808->variant) { 11993d0407baSopenharmony_ci case RK805_ID: 12003d0407baSopenharmony_ci rk808->regmap_cfg = &rk805_regmap_config; 12013d0407baSopenharmony_ci rk808->regmap_irq_chip = &rk805_irq_chip; 12023d0407baSopenharmony_ci pre_init_reg = rk805_pre_init_reg; 12033d0407baSopenharmony_ci nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg); 12043d0407baSopenharmony_ci cells = rk805s; 12053d0407baSopenharmony_ci nr_cells = ARRAY_SIZE(rk805s); 12063d0407baSopenharmony_ci on_source = RK805_ON_SOURCE_REG; 12073d0407baSopenharmony_ci off_source = RK805_OFF_SOURCE_REG; 12083d0407baSopenharmony_ci suspend_reg = rk805_suspend_reg; 12093d0407baSopenharmony_ci suspend_reg_num = ARRAY_SIZE(rk805_suspend_reg); 12103d0407baSopenharmony_ci resume_reg = rk805_resume_reg; 12113d0407baSopenharmony_ci resume_reg_num = ARRAY_SIZE(rk805_resume_reg); 12123d0407baSopenharmony_ci device_shutdown_fn = rk8xx_device_shutdown; 12133d0407baSopenharmony_ci rk808->pm_pwroff_prep_fn = rk805_device_shutdown_prepare; 12143d0407baSopenharmony_ci break; 12153d0407baSopenharmony_ci case RK808_ID: 12163d0407baSopenharmony_ci rk808->regmap_cfg = &rk808_regmap_config; 12173d0407baSopenharmony_ci rk808->regmap_irq_chip = &rk808_irq_chip; 12183d0407baSopenharmony_ci pre_init_reg = rk808_pre_init_reg; 12193d0407baSopenharmony_ci nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg); 12203d0407baSopenharmony_ci cells = rk808s; 12213d0407baSopenharmony_ci nr_cells = ARRAY_SIZE(rk808s); 12223d0407baSopenharmony_ci device_shutdown_fn = rk8xx_device_shutdown; 12233d0407baSopenharmony_ci break; 12243d0407baSopenharmony_ci case RK816_ID: 12253d0407baSopenharmony_ci rk808->regmap_cfg = &rk816_regmap_config; 12263d0407baSopenharmony_ci rk808->regmap_irq_chip = &rk816_irq_chip; 12273d0407baSopenharmony_ci battery_irq_chip = &rk816_battery_irq_chip; 12283d0407baSopenharmony_ci pre_init_reg = rk816_pre_init_reg; 12293d0407baSopenharmony_ci nr_pre_init_regs = ARRAY_SIZE(rk816_pre_init_reg); 12303d0407baSopenharmony_ci cells = rk816s; 12313d0407baSopenharmony_ci nr_cells = ARRAY_SIZE(rk816s); 12323d0407baSopenharmony_ci on_source = RK816_ON_SOURCE_REG; 12333d0407baSopenharmony_ci off_source = RK816_OFF_SOURCE_REG; 12343d0407baSopenharmony_ci suspend_reg = rk816_suspend_reg; 12353d0407baSopenharmony_ci suspend_reg_num = ARRAY_SIZE(rk816_suspend_reg); 12363d0407baSopenharmony_ci resume_reg = rk816_resume_reg; 12373d0407baSopenharmony_ci resume_reg_num = ARRAY_SIZE(rk816_resume_reg); 12383d0407baSopenharmony_ci device_shutdown_fn = rk8xx_device_shutdown; 12393d0407baSopenharmony_ci break; 12403d0407baSopenharmony_ci case RK818_ID: 12413d0407baSopenharmony_ci rk808->regmap_cfg = &rk818_regmap_config; 12423d0407baSopenharmony_ci rk808->regmap_irq_chip = &rk818_irq_chip; 12433d0407baSopenharmony_ci pre_init_reg = rk818_pre_init_reg; 12443d0407baSopenharmony_ci nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg); 12453d0407baSopenharmony_ci cells = rk818s; 12463d0407baSopenharmony_ci nr_cells = ARRAY_SIZE(rk818s); 12473d0407baSopenharmony_ci on_source = RK818_ON_SOURCE_REG; 12483d0407baSopenharmony_ci off_source = RK818_OFF_SOURCE_REG; 12493d0407baSopenharmony_ci suspend_reg = rk818_suspend_reg; 12503d0407baSopenharmony_ci suspend_reg_num = ARRAY_SIZE(rk818_suspend_reg); 12513d0407baSopenharmony_ci resume_reg = rk818_resume_reg; 12523d0407baSopenharmony_ci resume_reg_num = ARRAY_SIZE(rk818_resume_reg); 12533d0407baSopenharmony_ci device_shutdown_fn = rk8xx_device_shutdown; 12543d0407baSopenharmony_ci break; 12553d0407baSopenharmony_ci case RK809_ID: 12563d0407baSopenharmony_ci case RK817_ID: 12573d0407baSopenharmony_ci rk808->regmap_cfg = &rk817_regmap_config; 12583d0407baSopenharmony_ci rk808->regmap_irq_chip = &rk817_irq_chip; 12593d0407baSopenharmony_ci pre_init_reg = rk817_pre_init_reg; 12603d0407baSopenharmony_ci nr_pre_init_regs = ARRAY_SIZE(rk817_pre_init_reg); 12613d0407baSopenharmony_ci cells = rk817s; 12623d0407baSopenharmony_ci nr_cells = ARRAY_SIZE(rk817s); 12633d0407baSopenharmony_ci on_source = RK817_ON_SOURCE_REG; 12643d0407baSopenharmony_ci off_source = RK817_OFF_SOURCE_REG; 12653d0407baSopenharmony_ci rk808->pm_pwroff_prep_fn = rk817_shutdown_prepare; 12663d0407baSopenharmony_ci of_property_prepare_fn = rk817_of_property_prepare; 12673d0407baSopenharmony_ci pinctrl_init = rk817_pinctrl_init; 12683d0407baSopenharmony_ci break; 12693d0407baSopenharmony_ci default: 12703d0407baSopenharmony_ci dev_err(&client->dev, "Unsupported RK8XX ID %lu\n", rk808->variant); 12713d0407baSopenharmony_ci return -EINVAL; 12723d0407baSopenharmony_ci } 12733d0407baSopenharmony_ci 12743d0407baSopenharmony_ci rk808->i2c = client; 12753d0407baSopenharmony_ci rk808_i2c_client = client; 12763d0407baSopenharmony_ci i2c_set_clientdata(client, rk808); 12773d0407baSopenharmony_ci 12783d0407baSopenharmony_ci rk808->regmap = devm_regmap_init_i2c(client, rk808->regmap_cfg); 12793d0407baSopenharmony_ci if (IS_ERR(rk808->regmap)) { 12803d0407baSopenharmony_ci dev_err(&client->dev, "regmap initialization failed\n"); 12813d0407baSopenharmony_ci return PTR_ERR(rk808->regmap); 12823d0407baSopenharmony_ci } 12833d0407baSopenharmony_ci 12843d0407baSopenharmony_ci if (on_source && off_source) { 12853d0407baSopenharmony_ci ret = regmap_read(rk808->regmap, on_source, &on); 12863d0407baSopenharmony_ci if (ret) { 12873d0407baSopenharmony_ci dev_err(&client->dev, "read 0x%x failed\n", on_source); 12883d0407baSopenharmony_ci return ret; 12893d0407baSopenharmony_ci } 12903d0407baSopenharmony_ci 12913d0407baSopenharmony_ci ret = regmap_read(rk808->regmap, off_source, &off); 12923d0407baSopenharmony_ci if (ret) { 12933d0407baSopenharmony_ci dev_err(&client->dev, "read 0x%x failed\n", off_source); 12943d0407baSopenharmony_ci return ret; 12953d0407baSopenharmony_ci } 12963d0407baSopenharmony_ci 12973d0407baSopenharmony_ci dev_info(&client->dev, "source: on=0x%02x, off=0x%02x\n", on, off); 12983d0407baSopenharmony_ci } 12993d0407baSopenharmony_ci 13003d0407baSopenharmony_ci if (!client->irq) { 13013d0407baSopenharmony_ci dev_err(&client->dev, "No interrupt support, no core IRQ\n"); 13023d0407baSopenharmony_ci return -EINVAL; 13033d0407baSopenharmony_ci } 13043d0407baSopenharmony_ci 13053d0407baSopenharmony_ci if (of_property_prepare_fn) { 13063d0407baSopenharmony_ci of_property_prepare_fn(rk808, &client->dev); 13073d0407baSopenharmony_ci } 13083d0407baSopenharmony_ci 13093d0407baSopenharmony_ci for (i = 0; i < nr_pre_init_regs; i++) { 13103d0407baSopenharmony_ci ret = regmap_update_bits(rk808->regmap, pre_init_reg[i].addr, pre_init_reg[i].mask, pre_init_reg[i].value); 13113d0407baSopenharmony_ci if (ret) { 13123d0407baSopenharmony_ci dev_err(&client->dev, "0x%x write err\n", pre_init_reg[i].addr); 13133d0407baSopenharmony_ci return ret; 13143d0407baSopenharmony_ci } 13153d0407baSopenharmony_ci } 13163d0407baSopenharmony_ci 13173d0407baSopenharmony_ci if (pinctrl_init) { 13183d0407baSopenharmony_ci ret = pinctrl_init(&client->dev, rk808); 13193d0407baSopenharmony_ci if (ret) { 13203d0407baSopenharmony_ci return ret; 13213d0407baSopenharmony_ci } 13223d0407baSopenharmony_ci } 13233d0407baSopenharmony_ci 13243d0407baSopenharmony_ci ret = regmap_add_irq_chip(rk808->regmap, client->irq, IRQF_ONESHOT, -1, rk808->regmap_irq_chip, &rk808->irq_data); 13253d0407baSopenharmony_ci if (ret) { 13263d0407baSopenharmony_ci dev_err(&client->dev, "Failed to add irq_chip %d\n", ret); 13273d0407baSopenharmony_ci return ret; 13283d0407baSopenharmony_ci } 13293d0407baSopenharmony_ci 13303d0407baSopenharmony_ci if (battery_irq_chip) { 13313d0407baSopenharmony_ci ret = regmap_add_irq_chip(rk808->regmap, client->irq, IRQF_ONESHOT | IRQF_SHARED, -1, battery_irq_chip, 13323d0407baSopenharmony_ci &rk808->battery_irq_data); 13333d0407baSopenharmony_ci if (ret) { 13343d0407baSopenharmony_ci dev_err(&client->dev, "Failed to add batterry irq_chip %d\n", ret); 13353d0407baSopenharmony_ci regmap_del_irq_chip(client->irq, rk808->irq_data); 13363d0407baSopenharmony_ci return ret; 13373d0407baSopenharmony_ci } 13383d0407baSopenharmony_ci } 13393d0407baSopenharmony_ci 13403d0407baSopenharmony_ci ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, cells, nr_cells, NULL, 0, 13413d0407baSopenharmony_ci regmap_irq_get_domain(rk808->irq_data)); 13423d0407baSopenharmony_ci if (ret) { 13433d0407baSopenharmony_ci dev_err(&client->dev, "failed to add MFD devices %d\n", ret); 13443d0407baSopenharmony_ci goto err_irq; 13453d0407baSopenharmony_ci } 13463d0407baSopenharmony_ci 13473d0407baSopenharmony_ci pm_off = of_property_read_bool(np, "rockchip,system-power-controller"); 13483d0407baSopenharmony_ci if (pm_off) { 13493d0407baSopenharmony_ci if (!pm_power_off_prepare) { 13503d0407baSopenharmony_ci pm_power_off_prepare = rk808->pm_pwroff_prep_fn; 13513d0407baSopenharmony_ci } 13523d0407baSopenharmony_ci 13533d0407baSopenharmony_ci if (device_shutdown_fn) { 13543d0407baSopenharmony_ci register_syscore_ops(&rk808_syscore_ops); 13553d0407baSopenharmony_ci /* power off system in the syscore shutdown ! */ 13563d0407baSopenharmony_ci pm_shutdown = device_shutdown_fn; 13573d0407baSopenharmony_ci } 13583d0407baSopenharmony_ci } 13593d0407baSopenharmony_ci 13603d0407baSopenharmony_ci rk8xx_kobj = kobject_create_and_add("rk8xx", NULL); 13613d0407baSopenharmony_ci if (rk8xx_kobj) { 13623d0407baSopenharmony_ci ret = sysfs_create_file(rk8xx_kobj, &rk8xx_attrs.attr); 13633d0407baSopenharmony_ci if (ret) { 13643d0407baSopenharmony_ci dev_err(&client->dev, "create rk8xx sysfs error\n"); 13653d0407baSopenharmony_ci } 13663d0407baSopenharmony_ci } 13673d0407baSopenharmony_ci 13683d0407baSopenharmony_ci if (!pm_power_off) { 13693d0407baSopenharmony_ci pm_power_off = rk808_pm_power_off_dummy; 13703d0407baSopenharmony_ci } 13713d0407baSopenharmony_ci 13723d0407baSopenharmony_ci return 0; 13733d0407baSopenharmony_ci 13743d0407baSopenharmony_cierr_irq: 13753d0407baSopenharmony_ci regmap_del_irq_chip(client->irq, rk808->irq_data); 13763d0407baSopenharmony_ci if (battery_irq_chip) { 13773d0407baSopenharmony_ci regmap_del_irq_chip(client->irq, rk808->battery_irq_data); 13783d0407baSopenharmony_ci } 13793d0407baSopenharmony_ci return ret; 13803d0407baSopenharmony_ci} 13813d0407baSopenharmony_ci 13823d0407baSopenharmony_cistatic int rk808_remove(struct i2c_client *client) 13833d0407baSopenharmony_ci{ 13843d0407baSopenharmony_ci struct rk808 *rk808 = i2c_get_clientdata(client); 13853d0407baSopenharmony_ci 13863d0407baSopenharmony_ci regmap_del_irq_chip(client->irq, rk808->irq_data); 13873d0407baSopenharmony_ci mfd_remove_devices(&client->dev); 13883d0407baSopenharmony_ci 13893d0407baSopenharmony_ci /** 13903d0407baSopenharmony_ci * pm_power_off may points to a function from another module. 13913d0407baSopenharmony_ci * Check if the pointer is set by us and only then overwrite it. 13923d0407baSopenharmony_ci */ 13933d0407baSopenharmony_ci if (pm_power_off == rk808_pm_power_off_dummy) { 13943d0407baSopenharmony_ci pm_power_off = NULL; 13953d0407baSopenharmony_ci } 13963d0407baSopenharmony_ci 13973d0407baSopenharmony_ci /** 13983d0407baSopenharmony_ci * As above, check if the pointer is set by us before overwrite. 13993d0407baSopenharmony_ci */ 14003d0407baSopenharmony_ci if (rk808->pm_pwroff_prep_fn && pm_power_off_prepare == rk808->pm_pwroff_prep_fn) { 14013d0407baSopenharmony_ci pm_power_off_prepare = NULL; 14023d0407baSopenharmony_ci } 14033d0407baSopenharmony_ci 14043d0407baSopenharmony_ci if (pm_shutdown) { 14053d0407baSopenharmony_ci unregister_syscore_ops(&rk808_syscore_ops); 14063d0407baSopenharmony_ci } 14073d0407baSopenharmony_ci 14083d0407baSopenharmony_ci return 0; 14093d0407baSopenharmony_ci} 14103d0407baSopenharmony_ci 14113d0407baSopenharmony_cistatic int __maybe_unused rk8xx_suspend(struct device *dev) 14123d0407baSopenharmony_ci{ 14133d0407baSopenharmony_ci struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); 14143d0407baSopenharmony_ci int i, ret = 0; 14153d0407baSopenharmony_ci int value; 14163d0407baSopenharmony_ci 14173d0407baSopenharmony_ci for (i = 0; i < suspend_reg_num; i++) { 14183d0407baSopenharmony_ci ret = regmap_update_bits(rk808->regmap, suspend_reg[i].addr, suspend_reg[i].mask, suspend_reg[i].value); 14193d0407baSopenharmony_ci if (ret) { 14203d0407baSopenharmony_ci dev_err(dev, "0x%x write err\n", suspend_reg[i].addr); 14213d0407baSopenharmony_ci return ret; 14223d0407baSopenharmony_ci } 14233d0407baSopenharmony_ci } 14243d0407baSopenharmony_ci 14253d0407baSopenharmony_ci switch (rk808->variant) { 14263d0407baSopenharmony_ci case RK805_ID: 14273d0407baSopenharmony_ci ret = regmap_update_bits(rk808->regmap, RK805_GPIO_IO_POL_REG, SLP_SD_MSK, SLEEP_FUN); 14283d0407baSopenharmony_ci break; 14293d0407baSopenharmony_ci case RK809_ID: 14303d0407baSopenharmony_ci case RK817_ID: 14313d0407baSopenharmony_ci if (rk808->pins && rk808->pins->p && rk808->pins->sleep) { 14323d0407baSopenharmony_ci ret = regmap_update_bits(rk808->regmap, RK817_SYS_CFG(3), RK817_SLPPIN_FUNC_MSK, SLPPIN_NULL_FUN); 14333d0407baSopenharmony_ci if (ret) { 14343d0407baSopenharmony_ci dev_err(dev, "suspend: config SLPPIN_NULL_FUN error!\n"); 14353d0407baSopenharmony_ci return ret; 14363d0407baSopenharmony_ci } 14373d0407baSopenharmony_ci 14383d0407baSopenharmony_ci ret = regmap_update_bits(rk808->regmap, RK817_SYS_CFG(3), RK817_SLPPOL_MSK, RK817_SLPPOL_H); 14393d0407baSopenharmony_ci if (ret) { 14403d0407baSopenharmony_ci dev_err(dev, "suspend: config RK817_SLPPOL_H error!\n"); 14413d0407baSopenharmony_ci return ret; 14423d0407baSopenharmony_ci } 14433d0407baSopenharmony_ci 14443d0407baSopenharmony_ci /* pmic need the SCL clock to synchronize register */ 14453d0407baSopenharmony_ci regmap_read(rk808->regmap, RK817_SYS_STS, &value); 14463d0407baSopenharmony_ci mdelay(2); 14473d0407baSopenharmony_ci ret = pinctrl_select_state(rk808->pins->p, rk808->pins->sleep); 14483d0407baSopenharmony_ci if (ret) { 14493d0407baSopenharmony_ci dev_err(dev, "failed to act slp pinctrl state\n"); 14503d0407baSopenharmony_ci return ret; 14513d0407baSopenharmony_ci } 14523d0407baSopenharmony_ci } 14533d0407baSopenharmony_ci break; 14543d0407baSopenharmony_ci default: 14553d0407baSopenharmony_ci break; 14563d0407baSopenharmony_ci } 14573d0407baSopenharmony_ci 14583d0407baSopenharmony_ci return ret; 14593d0407baSopenharmony_ci} 14603d0407baSopenharmony_ci 14613d0407baSopenharmony_cistatic int __maybe_unused rk8xx_resume(struct device *dev) 14623d0407baSopenharmony_ci{ 14633d0407baSopenharmony_ci struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); 14643d0407baSopenharmony_ci int i, ret = 0; 14653d0407baSopenharmony_ci int value; 14663d0407baSopenharmony_ci 14673d0407baSopenharmony_ci for (i = 0; i < resume_reg_num; i++) { 14683d0407baSopenharmony_ci ret = regmap_update_bits(rk808->regmap, resume_reg[i].addr, resume_reg[i].mask, resume_reg[i].value); 14693d0407baSopenharmony_ci if (ret) { 14703d0407baSopenharmony_ci dev_err(dev, "0x%x write err\n", resume_reg[i].addr); 14713d0407baSopenharmony_ci return ret; 14723d0407baSopenharmony_ci } 14733d0407baSopenharmony_ci } 14743d0407baSopenharmony_ci 14753d0407baSopenharmony_ci switch (rk808->variant) { 14763d0407baSopenharmony_ci case RK809_ID: 14773d0407baSopenharmony_ci case RK817_ID: 14783d0407baSopenharmony_ci if (rk808->pins && rk808->pins->p && rk808->pins->reset) { 14793d0407baSopenharmony_ci ret = regmap_update_bits(rk808->regmap, RK817_SYS_CFG(3), RK817_SLPPIN_FUNC_MSK, SLPPIN_NULL_FUN); 14803d0407baSopenharmony_ci if (ret) { 14813d0407baSopenharmony_ci dev_err(dev, "resume: config SLPPIN_NULL_FUN error!\n"); 14823d0407baSopenharmony_ci return ret; 14833d0407baSopenharmony_ci } 14843d0407baSopenharmony_ci 14853d0407baSopenharmony_ci ret = regmap_update_bits(rk808->regmap, RK817_SYS_CFG(3), RK817_SLPPOL_MSK, RK817_SLPPOL_L); 14863d0407baSopenharmony_ci if (ret) { 14873d0407baSopenharmony_ci dev_err(dev, "resume: config RK817_SLPPOL_L error!\n"); 14883d0407baSopenharmony_ci return ret; 14893d0407baSopenharmony_ci } 14903d0407baSopenharmony_ci 14913d0407baSopenharmony_ci /* pmic need the SCL clock to synchronize register */ 14923d0407baSopenharmony_ci regmap_read(rk808->regmap, RK817_SYS_STS, &value); 14933d0407baSopenharmony_ci mdelay(2); 14943d0407baSopenharmony_ci ret = pinctrl_select_state(rk808->pins->p, rk808->pins->reset); 14953d0407baSopenharmony_ci if (ret) { 14963d0407baSopenharmony_ci dev_dbg(dev, "failed to act reset pinctrl state\n"); 14973d0407baSopenharmony_ci } 14983d0407baSopenharmony_ci } 14993d0407baSopenharmony_ci break; 15003d0407baSopenharmony_ci default: 15013d0407baSopenharmony_ci break; 15023d0407baSopenharmony_ci } 15033d0407baSopenharmony_ci 15043d0407baSopenharmony_ci return ret; 15053d0407baSopenharmony_ci} 15063d0407baSopenharmony_ciSIMPLE_DEV_PM_OPS(rk8xx_pm_ops, rk8xx_suspend, rk8xx_resume); 15073d0407baSopenharmony_ci 15083d0407baSopenharmony_cistatic struct i2c_driver rk808_i2c_driver = { 15093d0407baSopenharmony_ci .driver = 15103d0407baSopenharmony_ci { 15113d0407baSopenharmony_ci .name = "rk808", 15123d0407baSopenharmony_ci .of_match_table = rk808_of_match, 15133d0407baSopenharmony_ci .pm = &rk8xx_pm_ops, 15143d0407baSopenharmony_ci }, 15153d0407baSopenharmony_ci .probe = rk808_probe, 15163d0407baSopenharmony_ci .remove = rk808_remove, 15173d0407baSopenharmony_ci}; 15183d0407baSopenharmony_ci 15193d0407baSopenharmony_ci#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT 15203d0407baSopenharmony_cistatic int __init rk808_i2c_driver_init(void) 15213d0407baSopenharmony_ci{ 15223d0407baSopenharmony_ci return i2c_add_driver(&rk808_i2c_driver); 15233d0407baSopenharmony_ci} 15243d0407baSopenharmony_cisubsys_initcall(rk808_i2c_driver_init); 15253d0407baSopenharmony_ci 15263d0407baSopenharmony_cistatic void __exit rk808_i2c_driver_exit(void) 15273d0407baSopenharmony_ci{ 15283d0407baSopenharmony_ci i2c_del_driver(&rk808_i2c_driver); 15293d0407baSopenharmony_ci} 15303d0407baSopenharmony_cimodule_exit(rk808_i2c_driver_exit); 15313d0407baSopenharmony_ci#else 15323d0407baSopenharmony_cimodule_i2c_driver(rk808_i2c_driver); 15333d0407baSopenharmony_ci#endif 15343d0407baSopenharmony_ci 15353d0407baSopenharmony_ciMODULE_LICENSE("GPL"); 15363d0407baSopenharmony_ciMODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>"); 15373d0407baSopenharmony_ciMODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>"); 15383d0407baSopenharmony_ciMODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>"); 15393d0407baSopenharmony_ciMODULE_DESCRIPTION("RK808/RK818 PMIC driver"); 1540