1*c20e8c5bSSebastian Reichel // SPDX-License-Identifier: GPL-2.0-only 2*c20e8c5bSSebastian Reichel /* 3*c20e8c5bSSebastian Reichel * MFD core driver for Rockchip RK8XX 4*c20e8c5bSSebastian Reichel * 5*c20e8c5bSSebastian Reichel * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd 6*c20e8c5bSSebastian Reichel * Copyright (C) 2016 PHYTEC Messtechnik GmbH 7*c20e8c5bSSebastian Reichel * 8*c20e8c5bSSebastian Reichel * Author: Chris Zhong <zyw@rock-chips.com> 9*c20e8c5bSSebastian Reichel * Author: Zhang Qing <zhangqing@rock-chips.com> 10*c20e8c5bSSebastian Reichel * Author: Wadim Egorov <w.egorov@phytec.de> 11*c20e8c5bSSebastian Reichel */ 12*c20e8c5bSSebastian Reichel 13*c20e8c5bSSebastian Reichel #include <linux/interrupt.h> 14*c20e8c5bSSebastian Reichel #include <linux/mfd/rk808.h> 15*c20e8c5bSSebastian Reichel #include <linux/mfd/core.h> 16*c20e8c5bSSebastian Reichel #include <linux/module.h> 17*c20e8c5bSSebastian Reichel #include <linux/of_device.h> 18*c20e8c5bSSebastian Reichel #include <linux/regmap.h> 19*c20e8c5bSSebastian Reichel #include <linux/reboot.h> 20*c20e8c5bSSebastian Reichel 21*c20e8c5bSSebastian Reichel struct rk808_reg_data { 22*c20e8c5bSSebastian Reichel int addr; 23*c20e8c5bSSebastian Reichel int mask; 24*c20e8c5bSSebastian Reichel int value; 25*c20e8c5bSSebastian Reichel }; 26*c20e8c5bSSebastian Reichel 27*c20e8c5bSSebastian Reichel static const struct resource rtc_resources[] = { 28*c20e8c5bSSebastian Reichel DEFINE_RES_IRQ(RK808_IRQ_RTC_ALARM), 29*c20e8c5bSSebastian Reichel }; 30*c20e8c5bSSebastian Reichel 31*c20e8c5bSSebastian Reichel static const struct resource rk817_rtc_resources[] = { 32*c20e8c5bSSebastian Reichel DEFINE_RES_IRQ(RK817_IRQ_RTC_ALARM), 33*c20e8c5bSSebastian Reichel }; 34*c20e8c5bSSebastian Reichel 35*c20e8c5bSSebastian Reichel static const struct resource rk805_key_resources[] = { 36*c20e8c5bSSebastian Reichel DEFINE_RES_IRQ(RK805_IRQ_PWRON_RISE), 37*c20e8c5bSSebastian Reichel DEFINE_RES_IRQ(RK805_IRQ_PWRON_FALL), 38*c20e8c5bSSebastian Reichel }; 39*c20e8c5bSSebastian Reichel 40*c20e8c5bSSebastian Reichel static const struct resource rk817_pwrkey_resources[] = { 41*c20e8c5bSSebastian Reichel DEFINE_RES_IRQ(RK817_IRQ_PWRON_RISE), 42*c20e8c5bSSebastian Reichel DEFINE_RES_IRQ(RK817_IRQ_PWRON_FALL), 43*c20e8c5bSSebastian Reichel }; 44*c20e8c5bSSebastian Reichel 45*c20e8c5bSSebastian Reichel static const struct resource rk817_charger_resources[] = { 46*c20e8c5bSSebastian Reichel DEFINE_RES_IRQ(RK817_IRQ_PLUG_IN), 47*c20e8c5bSSebastian Reichel DEFINE_RES_IRQ(RK817_IRQ_PLUG_OUT), 48*c20e8c5bSSebastian Reichel }; 49*c20e8c5bSSebastian Reichel 50*c20e8c5bSSebastian Reichel static const struct mfd_cell rk805s[] = { 51*c20e8c5bSSebastian Reichel { .name = "rk808-clkout", .id = PLATFORM_DEVID_NONE, }, 52*c20e8c5bSSebastian Reichel { .name = "rk808-regulator", .id = PLATFORM_DEVID_NONE, }, 53*c20e8c5bSSebastian Reichel { .name = "rk805-pinctrl", .id = PLATFORM_DEVID_NONE, }, 54*c20e8c5bSSebastian Reichel { 55*c20e8c5bSSebastian Reichel .name = "rk808-rtc", 56*c20e8c5bSSebastian Reichel .num_resources = ARRAY_SIZE(rtc_resources), 57*c20e8c5bSSebastian Reichel .resources = &rtc_resources[0], 58*c20e8c5bSSebastian Reichel .id = PLATFORM_DEVID_NONE, 59*c20e8c5bSSebastian Reichel }, 60*c20e8c5bSSebastian Reichel { .name = "rk805-pwrkey", 61*c20e8c5bSSebastian Reichel .num_resources = ARRAY_SIZE(rk805_key_resources), 62*c20e8c5bSSebastian Reichel .resources = &rk805_key_resources[0], 63*c20e8c5bSSebastian Reichel .id = PLATFORM_DEVID_NONE, 64*c20e8c5bSSebastian Reichel }, 65*c20e8c5bSSebastian Reichel }; 66*c20e8c5bSSebastian Reichel 67*c20e8c5bSSebastian Reichel static const struct mfd_cell rk808s[] = { 68*c20e8c5bSSebastian Reichel { .name = "rk808-clkout", .id = PLATFORM_DEVID_NONE, }, 69*c20e8c5bSSebastian Reichel { .name = "rk808-regulator", .id = PLATFORM_DEVID_NONE, }, 70*c20e8c5bSSebastian Reichel { 71*c20e8c5bSSebastian Reichel .name = "rk808-rtc", 72*c20e8c5bSSebastian Reichel .num_resources = ARRAY_SIZE(rtc_resources), 73*c20e8c5bSSebastian Reichel .resources = rtc_resources, 74*c20e8c5bSSebastian Reichel .id = PLATFORM_DEVID_NONE, 75*c20e8c5bSSebastian Reichel }, 76*c20e8c5bSSebastian Reichel }; 77*c20e8c5bSSebastian Reichel 78*c20e8c5bSSebastian Reichel static const struct mfd_cell rk817s[] = { 79*c20e8c5bSSebastian Reichel { .name = "rk808-clkout", .id = PLATFORM_DEVID_NONE, }, 80*c20e8c5bSSebastian Reichel { .name = "rk808-regulator", .id = PLATFORM_DEVID_NONE, }, 81*c20e8c5bSSebastian Reichel { 82*c20e8c5bSSebastian Reichel .name = "rk805-pwrkey", 83*c20e8c5bSSebastian Reichel .num_resources = ARRAY_SIZE(rk817_pwrkey_resources), 84*c20e8c5bSSebastian Reichel .resources = &rk817_pwrkey_resources[0], 85*c20e8c5bSSebastian Reichel .id = PLATFORM_DEVID_NONE, 86*c20e8c5bSSebastian Reichel }, 87*c20e8c5bSSebastian Reichel { 88*c20e8c5bSSebastian Reichel .name = "rk808-rtc", 89*c20e8c5bSSebastian Reichel .num_resources = ARRAY_SIZE(rk817_rtc_resources), 90*c20e8c5bSSebastian Reichel .resources = &rk817_rtc_resources[0], 91*c20e8c5bSSebastian Reichel .id = PLATFORM_DEVID_NONE, 92*c20e8c5bSSebastian Reichel }, 93*c20e8c5bSSebastian Reichel { .name = "rk817-codec", .id = PLATFORM_DEVID_NONE, }, 94*c20e8c5bSSebastian Reichel { 95*c20e8c5bSSebastian Reichel .name = "rk817-charger", 96*c20e8c5bSSebastian Reichel .num_resources = ARRAY_SIZE(rk817_charger_resources), 97*c20e8c5bSSebastian Reichel .resources = &rk817_charger_resources[0], 98*c20e8c5bSSebastian Reichel .id = PLATFORM_DEVID_NONE, 99*c20e8c5bSSebastian Reichel }, 100*c20e8c5bSSebastian Reichel }; 101*c20e8c5bSSebastian Reichel 102*c20e8c5bSSebastian Reichel static const struct mfd_cell rk818s[] = { 103*c20e8c5bSSebastian Reichel { .name = "rk808-clkout", .id = PLATFORM_DEVID_NONE, }, 104*c20e8c5bSSebastian Reichel { .name = "rk808-regulator", .id = PLATFORM_DEVID_NONE, }, 105*c20e8c5bSSebastian Reichel { 106*c20e8c5bSSebastian Reichel .name = "rk808-rtc", 107*c20e8c5bSSebastian Reichel .num_resources = ARRAY_SIZE(rtc_resources), 108*c20e8c5bSSebastian Reichel .resources = rtc_resources, 109*c20e8c5bSSebastian Reichel .id = PLATFORM_DEVID_NONE, 110*c20e8c5bSSebastian Reichel }, 111*c20e8c5bSSebastian Reichel }; 112*c20e8c5bSSebastian Reichel 113*c20e8c5bSSebastian Reichel static const struct rk808_reg_data rk805_pre_init_reg[] = { 114*c20e8c5bSSebastian Reichel {RK805_BUCK1_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK, 115*c20e8c5bSSebastian Reichel RK805_BUCK1_2_ILMAX_4000MA}, 116*c20e8c5bSSebastian Reichel {RK805_BUCK2_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK, 117*c20e8c5bSSebastian Reichel RK805_BUCK1_2_ILMAX_4000MA}, 118*c20e8c5bSSebastian Reichel {RK805_BUCK3_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK, 119*c20e8c5bSSebastian Reichel RK805_BUCK3_ILMAX_3000MA}, 120*c20e8c5bSSebastian Reichel {RK805_BUCK4_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK, 121*c20e8c5bSSebastian Reichel RK805_BUCK4_ILMAX_3500MA}, 122*c20e8c5bSSebastian Reichel {RK805_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_400MA}, 123*c20e8c5bSSebastian Reichel {RK805_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP115C}, 124*c20e8c5bSSebastian Reichel }; 125*c20e8c5bSSebastian Reichel 126*c20e8c5bSSebastian Reichel static const struct rk808_reg_data rk808_pre_init_reg[] = { 127*c20e8c5bSSebastian Reichel { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA }, 128*c20e8c5bSSebastian Reichel { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA }, 129*c20e8c5bSSebastian Reichel { RK808_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA }, 130*c20e8c5bSSebastian Reichel { RK808_BUCK1_CONFIG_REG, BUCK1_RATE_MASK, BUCK_ILMIN_200MA }, 131*c20e8c5bSSebastian Reichel { RK808_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_200MA }, 132*c20e8c5bSSebastian Reichel { RK808_DCDC_UV_ACT_REG, BUCK_UV_ACT_MASK, BUCK_UV_ACT_DISABLE}, 133*c20e8c5bSSebastian Reichel { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT | 134*c20e8c5bSSebastian Reichel VB_LO_SEL_3500MV }, 135*c20e8c5bSSebastian Reichel }; 136*c20e8c5bSSebastian Reichel 137*c20e8c5bSSebastian Reichel static const struct rk808_reg_data rk817_pre_init_reg[] = { 138*c20e8c5bSSebastian Reichel {RK817_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, 139*c20e8c5bSSebastian Reichel /* Codec specific registers */ 140*c20e8c5bSSebastian Reichel { RK817_CODEC_DTOP_VUCTL, MASK_ALL, 0x03 }, 141*c20e8c5bSSebastian Reichel { RK817_CODEC_DTOP_VUCTIME, MASK_ALL, 0x00 }, 142*c20e8c5bSSebastian Reichel { RK817_CODEC_DTOP_LPT_SRST, MASK_ALL, 0x00 }, 143*c20e8c5bSSebastian Reichel { RK817_CODEC_DTOP_DIGEN_CLKE, MASK_ALL, 0x00 }, 144*c20e8c5bSSebastian Reichel /* from vendor driver, CODEC_AREF_RTCFG0 not defined in data sheet */ 145*c20e8c5bSSebastian Reichel { RK817_CODEC_AREF_RTCFG0, MASK_ALL, 0x00 }, 146*c20e8c5bSSebastian Reichel { RK817_CODEC_AREF_RTCFG1, MASK_ALL, 0x06 }, 147*c20e8c5bSSebastian Reichel { RK817_CODEC_AADC_CFG0, MASK_ALL, 0xc8 }, 148*c20e8c5bSSebastian Reichel /* from vendor driver, CODEC_AADC_CFG1 not defined in data sheet */ 149*c20e8c5bSSebastian Reichel { RK817_CODEC_AADC_CFG1, MASK_ALL, 0x00 }, 150*c20e8c5bSSebastian Reichel { RK817_CODEC_DADC_VOLL, MASK_ALL, 0x00 }, 151*c20e8c5bSSebastian Reichel { RK817_CODEC_DADC_VOLR, MASK_ALL, 0x00 }, 152*c20e8c5bSSebastian Reichel { RK817_CODEC_DADC_SR_ACL0, MASK_ALL, 0x00 }, 153*c20e8c5bSSebastian Reichel { RK817_CODEC_DADC_ALC1, MASK_ALL, 0x00 }, 154*c20e8c5bSSebastian Reichel { RK817_CODEC_DADC_ALC2, MASK_ALL, 0x00 }, 155*c20e8c5bSSebastian Reichel { RK817_CODEC_DADC_NG, MASK_ALL, 0x00 }, 156*c20e8c5bSSebastian Reichel { RK817_CODEC_DADC_HPF, MASK_ALL, 0x00 }, 157*c20e8c5bSSebastian Reichel { RK817_CODEC_DADC_RVOLL, MASK_ALL, 0xff }, 158*c20e8c5bSSebastian Reichel { RK817_CODEC_DADC_RVOLR, MASK_ALL, 0xff }, 159*c20e8c5bSSebastian Reichel { RK817_CODEC_AMIC_CFG0, MASK_ALL, 0x70 }, 160*c20e8c5bSSebastian Reichel { RK817_CODEC_AMIC_CFG1, MASK_ALL, 0x00 }, 161*c20e8c5bSSebastian Reichel { RK817_CODEC_DMIC_PGA_GAIN, MASK_ALL, 0x66 }, 162*c20e8c5bSSebastian Reichel { RK817_CODEC_DMIC_LMT1, MASK_ALL, 0x00 }, 163*c20e8c5bSSebastian Reichel { RK817_CODEC_DMIC_LMT2, MASK_ALL, 0x00 }, 164*c20e8c5bSSebastian Reichel { RK817_CODEC_DMIC_NG1, MASK_ALL, 0x00 }, 165*c20e8c5bSSebastian Reichel { RK817_CODEC_DMIC_NG2, MASK_ALL, 0x00 }, 166*c20e8c5bSSebastian Reichel /* from vendor driver, CODEC_ADAC_CFG0 not defined in data sheet */ 167*c20e8c5bSSebastian Reichel { RK817_CODEC_ADAC_CFG0, MASK_ALL, 0x00 }, 168*c20e8c5bSSebastian Reichel { RK817_CODEC_ADAC_CFG1, MASK_ALL, 0x07 }, 169*c20e8c5bSSebastian Reichel { RK817_CODEC_DDAC_POPD_DACST, MASK_ALL, 0x82 }, 170*c20e8c5bSSebastian Reichel { RK817_CODEC_DDAC_VOLL, MASK_ALL, 0x00 }, 171*c20e8c5bSSebastian Reichel { RK817_CODEC_DDAC_VOLR, MASK_ALL, 0x00 }, 172*c20e8c5bSSebastian Reichel { RK817_CODEC_DDAC_SR_LMT0, MASK_ALL, 0x00 }, 173*c20e8c5bSSebastian Reichel { RK817_CODEC_DDAC_LMT1, MASK_ALL, 0x00 }, 174*c20e8c5bSSebastian Reichel { RK817_CODEC_DDAC_LMT2, MASK_ALL, 0x00 }, 175*c20e8c5bSSebastian Reichel { RK817_CODEC_DDAC_MUTE_MIXCTL, MASK_ALL, 0xa0 }, 176*c20e8c5bSSebastian Reichel { RK817_CODEC_DDAC_RVOLL, MASK_ALL, 0xff }, 177*c20e8c5bSSebastian Reichel { RK817_CODEC_DADC_RVOLR, MASK_ALL, 0xff }, 178*c20e8c5bSSebastian Reichel { RK817_CODEC_AMIC_CFG0, MASK_ALL, 0x70 }, 179*c20e8c5bSSebastian Reichel { RK817_CODEC_AMIC_CFG1, MASK_ALL, 0x00 }, 180*c20e8c5bSSebastian Reichel { RK817_CODEC_DMIC_PGA_GAIN, MASK_ALL, 0x66 }, 181*c20e8c5bSSebastian Reichel { RK817_CODEC_DMIC_LMT1, MASK_ALL, 0x00 }, 182*c20e8c5bSSebastian Reichel { RK817_CODEC_DMIC_LMT2, MASK_ALL, 0x00 }, 183*c20e8c5bSSebastian Reichel { RK817_CODEC_DMIC_NG1, MASK_ALL, 0x00 }, 184*c20e8c5bSSebastian Reichel { RK817_CODEC_DMIC_NG2, MASK_ALL, 0x00 }, 185*c20e8c5bSSebastian Reichel /* from vendor driver, CODEC_ADAC_CFG0 not defined in data sheet */ 186*c20e8c5bSSebastian Reichel { RK817_CODEC_ADAC_CFG0, MASK_ALL, 0x00 }, 187*c20e8c5bSSebastian Reichel { RK817_CODEC_ADAC_CFG1, MASK_ALL, 0x07 }, 188*c20e8c5bSSebastian Reichel { RK817_CODEC_DDAC_POPD_DACST, MASK_ALL, 0x82 }, 189*c20e8c5bSSebastian Reichel { RK817_CODEC_DDAC_VOLL, MASK_ALL, 0x00 }, 190*c20e8c5bSSebastian Reichel { RK817_CODEC_DDAC_VOLR, MASK_ALL, 0x00 }, 191*c20e8c5bSSebastian Reichel { RK817_CODEC_DDAC_SR_LMT0, MASK_ALL, 0x00 }, 192*c20e8c5bSSebastian Reichel { RK817_CODEC_DDAC_LMT1, MASK_ALL, 0x00 }, 193*c20e8c5bSSebastian Reichel { RK817_CODEC_DDAC_LMT2, MASK_ALL, 0x00 }, 194*c20e8c5bSSebastian Reichel { RK817_CODEC_DDAC_MUTE_MIXCTL, MASK_ALL, 0xa0 }, 195*c20e8c5bSSebastian Reichel { RK817_CODEC_DDAC_RVOLL, MASK_ALL, 0xff }, 196*c20e8c5bSSebastian Reichel { RK817_CODEC_DDAC_RVOLR, MASK_ALL, 0xff }, 197*c20e8c5bSSebastian Reichel { RK817_CODEC_AHP_ANTI0, MASK_ALL, 0x00 }, 198*c20e8c5bSSebastian Reichel { RK817_CODEC_AHP_ANTI1, MASK_ALL, 0x00 }, 199*c20e8c5bSSebastian Reichel { RK817_CODEC_AHP_CFG0, MASK_ALL, 0xe0 }, 200*c20e8c5bSSebastian Reichel { RK817_CODEC_AHP_CFG1, MASK_ALL, 0x1f }, 201*c20e8c5bSSebastian Reichel { RK817_CODEC_AHP_CP, MASK_ALL, 0x09 }, 202*c20e8c5bSSebastian Reichel { RK817_CODEC_ACLASSD_CFG1, MASK_ALL, 0x69 }, 203*c20e8c5bSSebastian Reichel { RK817_CODEC_ACLASSD_CFG2, MASK_ALL, 0x44 }, 204*c20e8c5bSSebastian Reichel { RK817_CODEC_APLL_CFG0, MASK_ALL, 0x04 }, 205*c20e8c5bSSebastian Reichel { RK817_CODEC_APLL_CFG1, MASK_ALL, 0x00 }, 206*c20e8c5bSSebastian Reichel { RK817_CODEC_APLL_CFG2, MASK_ALL, 0x30 }, 207*c20e8c5bSSebastian Reichel { RK817_CODEC_APLL_CFG3, MASK_ALL, 0x19 }, 208*c20e8c5bSSebastian Reichel { RK817_CODEC_APLL_CFG4, MASK_ALL, 0x65 }, 209*c20e8c5bSSebastian Reichel { RK817_CODEC_APLL_CFG5, MASK_ALL, 0x01 }, 210*c20e8c5bSSebastian Reichel { RK817_CODEC_DI2S_CKM, MASK_ALL, 0x01 }, 211*c20e8c5bSSebastian Reichel { RK817_CODEC_DI2S_RSD, MASK_ALL, 0x00 }, 212*c20e8c5bSSebastian Reichel { RK817_CODEC_DI2S_RXCR1, MASK_ALL, 0x00 }, 213*c20e8c5bSSebastian Reichel { RK817_CODEC_DI2S_RXCR2, MASK_ALL, 0x17 }, 214*c20e8c5bSSebastian Reichel { RK817_CODEC_DI2S_RXCMD_TSD, MASK_ALL, 0x00 }, 215*c20e8c5bSSebastian Reichel { RK817_CODEC_DI2S_TXCR1, MASK_ALL, 0x00 }, 216*c20e8c5bSSebastian Reichel { RK817_CODEC_DI2S_TXCR2, MASK_ALL, 0x17 }, 217*c20e8c5bSSebastian Reichel { RK817_CODEC_DI2S_TXCR3_TXCMD, MASK_ALL, 0x00 }, 218*c20e8c5bSSebastian Reichel {RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_L}, 219*c20e8c5bSSebastian Reichel {RK817_SYS_CFG(1), RK817_HOTDIE_TEMP_MSK | RK817_TSD_TEMP_MSK, 220*c20e8c5bSSebastian Reichel RK817_HOTDIE_105 | RK817_TSD_140}, 221*c20e8c5bSSebastian Reichel }; 222*c20e8c5bSSebastian Reichel 223*c20e8c5bSSebastian Reichel static const struct rk808_reg_data rk818_pre_init_reg[] = { 224*c20e8c5bSSebastian Reichel /* improve efficiency */ 225*c20e8c5bSSebastian Reichel { RK818_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_250MA }, 226*c20e8c5bSSebastian Reichel { RK818_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_250MA }, 227*c20e8c5bSSebastian Reichel { RK818_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA }, 228*c20e8c5bSSebastian Reichel { RK818_USB_CTRL_REG, RK818_USB_ILIM_SEL_MASK, 229*c20e8c5bSSebastian Reichel RK818_USB_ILMIN_2000MA }, 230*c20e8c5bSSebastian Reichel /* close charger when usb lower then 3.4V */ 231*c20e8c5bSSebastian Reichel { RK818_USB_CTRL_REG, RK818_USB_CHG_SD_VSEL_MASK, 232*c20e8c5bSSebastian Reichel (0x7 << 4) }, 233*c20e8c5bSSebastian Reichel /* no action when vref */ 234*c20e8c5bSSebastian Reichel { RK818_H5V_EN_REG, BIT(1), RK818_REF_RDY_CTRL }, 235*c20e8c5bSSebastian Reichel /* enable HDMI 5V */ 236*c20e8c5bSSebastian Reichel { RK818_H5V_EN_REG, BIT(0), RK818_H5V_EN }, 237*c20e8c5bSSebastian Reichel { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT | 238*c20e8c5bSSebastian Reichel VB_LO_SEL_3500MV }, 239*c20e8c5bSSebastian Reichel }; 240*c20e8c5bSSebastian Reichel 241*c20e8c5bSSebastian Reichel static const struct regmap_irq rk805_irqs[] = { 242*c20e8c5bSSebastian Reichel [RK805_IRQ_PWRON_RISE] = { 243*c20e8c5bSSebastian Reichel .mask = RK805_IRQ_PWRON_RISE_MSK, 244*c20e8c5bSSebastian Reichel .reg_offset = 0, 245*c20e8c5bSSebastian Reichel }, 246*c20e8c5bSSebastian Reichel [RK805_IRQ_VB_LOW] = { 247*c20e8c5bSSebastian Reichel .mask = RK805_IRQ_VB_LOW_MSK, 248*c20e8c5bSSebastian Reichel .reg_offset = 0, 249*c20e8c5bSSebastian Reichel }, 250*c20e8c5bSSebastian Reichel [RK805_IRQ_PWRON] = { 251*c20e8c5bSSebastian Reichel .mask = RK805_IRQ_PWRON_MSK, 252*c20e8c5bSSebastian Reichel .reg_offset = 0, 253*c20e8c5bSSebastian Reichel }, 254*c20e8c5bSSebastian Reichel [RK805_IRQ_PWRON_LP] = { 255*c20e8c5bSSebastian Reichel .mask = RK805_IRQ_PWRON_LP_MSK, 256*c20e8c5bSSebastian Reichel .reg_offset = 0, 257*c20e8c5bSSebastian Reichel }, 258*c20e8c5bSSebastian Reichel [RK805_IRQ_HOTDIE] = { 259*c20e8c5bSSebastian Reichel .mask = RK805_IRQ_HOTDIE_MSK, 260*c20e8c5bSSebastian Reichel .reg_offset = 0, 261*c20e8c5bSSebastian Reichel }, 262*c20e8c5bSSebastian Reichel [RK805_IRQ_RTC_ALARM] = { 263*c20e8c5bSSebastian Reichel .mask = RK805_IRQ_RTC_ALARM_MSK, 264*c20e8c5bSSebastian Reichel .reg_offset = 0, 265*c20e8c5bSSebastian Reichel }, 266*c20e8c5bSSebastian Reichel [RK805_IRQ_RTC_PERIOD] = { 267*c20e8c5bSSebastian Reichel .mask = RK805_IRQ_RTC_PERIOD_MSK, 268*c20e8c5bSSebastian Reichel .reg_offset = 0, 269*c20e8c5bSSebastian Reichel }, 270*c20e8c5bSSebastian Reichel [RK805_IRQ_PWRON_FALL] = { 271*c20e8c5bSSebastian Reichel .mask = RK805_IRQ_PWRON_FALL_MSK, 272*c20e8c5bSSebastian Reichel .reg_offset = 0, 273*c20e8c5bSSebastian Reichel }, 274*c20e8c5bSSebastian Reichel }; 275*c20e8c5bSSebastian Reichel 276*c20e8c5bSSebastian Reichel static const struct regmap_irq rk808_irqs[] = { 277*c20e8c5bSSebastian Reichel /* INT_STS */ 278*c20e8c5bSSebastian Reichel [RK808_IRQ_VOUT_LO] = { 279*c20e8c5bSSebastian Reichel .mask = RK808_IRQ_VOUT_LO_MSK, 280*c20e8c5bSSebastian Reichel .reg_offset = 0, 281*c20e8c5bSSebastian Reichel }, 282*c20e8c5bSSebastian Reichel [RK808_IRQ_VB_LO] = { 283*c20e8c5bSSebastian Reichel .mask = RK808_IRQ_VB_LO_MSK, 284*c20e8c5bSSebastian Reichel .reg_offset = 0, 285*c20e8c5bSSebastian Reichel }, 286*c20e8c5bSSebastian Reichel [RK808_IRQ_PWRON] = { 287*c20e8c5bSSebastian Reichel .mask = RK808_IRQ_PWRON_MSK, 288*c20e8c5bSSebastian Reichel .reg_offset = 0, 289*c20e8c5bSSebastian Reichel }, 290*c20e8c5bSSebastian Reichel [RK808_IRQ_PWRON_LP] = { 291*c20e8c5bSSebastian Reichel .mask = RK808_IRQ_PWRON_LP_MSK, 292*c20e8c5bSSebastian Reichel .reg_offset = 0, 293*c20e8c5bSSebastian Reichel }, 294*c20e8c5bSSebastian Reichel [RK808_IRQ_HOTDIE] = { 295*c20e8c5bSSebastian Reichel .mask = RK808_IRQ_HOTDIE_MSK, 296*c20e8c5bSSebastian Reichel .reg_offset = 0, 297*c20e8c5bSSebastian Reichel }, 298*c20e8c5bSSebastian Reichel [RK808_IRQ_RTC_ALARM] = { 299*c20e8c5bSSebastian Reichel .mask = RK808_IRQ_RTC_ALARM_MSK, 300*c20e8c5bSSebastian Reichel .reg_offset = 0, 301*c20e8c5bSSebastian Reichel }, 302*c20e8c5bSSebastian Reichel [RK808_IRQ_RTC_PERIOD] = { 303*c20e8c5bSSebastian Reichel .mask = RK808_IRQ_RTC_PERIOD_MSK, 304*c20e8c5bSSebastian Reichel .reg_offset = 0, 305*c20e8c5bSSebastian Reichel }, 306*c20e8c5bSSebastian Reichel 307*c20e8c5bSSebastian Reichel /* INT_STS2 */ 308*c20e8c5bSSebastian Reichel [RK808_IRQ_PLUG_IN_INT] = { 309*c20e8c5bSSebastian Reichel .mask = RK808_IRQ_PLUG_IN_INT_MSK, 310*c20e8c5bSSebastian Reichel .reg_offset = 1, 311*c20e8c5bSSebastian Reichel }, 312*c20e8c5bSSebastian Reichel [RK808_IRQ_PLUG_OUT_INT] = { 313*c20e8c5bSSebastian Reichel .mask = RK808_IRQ_PLUG_OUT_INT_MSK, 314*c20e8c5bSSebastian Reichel .reg_offset = 1, 315*c20e8c5bSSebastian Reichel }, 316*c20e8c5bSSebastian Reichel }; 317*c20e8c5bSSebastian Reichel 318*c20e8c5bSSebastian Reichel static const struct regmap_irq rk818_irqs[] = { 319*c20e8c5bSSebastian Reichel /* INT_STS */ 320*c20e8c5bSSebastian Reichel [RK818_IRQ_VOUT_LO] = { 321*c20e8c5bSSebastian Reichel .mask = RK818_IRQ_VOUT_LO_MSK, 322*c20e8c5bSSebastian Reichel .reg_offset = 0, 323*c20e8c5bSSebastian Reichel }, 324*c20e8c5bSSebastian Reichel [RK818_IRQ_VB_LO] = { 325*c20e8c5bSSebastian Reichel .mask = RK818_IRQ_VB_LO_MSK, 326*c20e8c5bSSebastian Reichel .reg_offset = 0, 327*c20e8c5bSSebastian Reichel }, 328*c20e8c5bSSebastian Reichel [RK818_IRQ_PWRON] = { 329*c20e8c5bSSebastian Reichel .mask = RK818_IRQ_PWRON_MSK, 330*c20e8c5bSSebastian Reichel .reg_offset = 0, 331*c20e8c5bSSebastian Reichel }, 332*c20e8c5bSSebastian Reichel [RK818_IRQ_PWRON_LP] = { 333*c20e8c5bSSebastian Reichel .mask = RK818_IRQ_PWRON_LP_MSK, 334*c20e8c5bSSebastian Reichel .reg_offset = 0, 335*c20e8c5bSSebastian Reichel }, 336*c20e8c5bSSebastian Reichel [RK818_IRQ_HOTDIE] = { 337*c20e8c5bSSebastian Reichel .mask = RK818_IRQ_HOTDIE_MSK, 338*c20e8c5bSSebastian Reichel .reg_offset = 0, 339*c20e8c5bSSebastian Reichel }, 340*c20e8c5bSSebastian Reichel [RK818_IRQ_RTC_ALARM] = { 341*c20e8c5bSSebastian Reichel .mask = RK818_IRQ_RTC_ALARM_MSK, 342*c20e8c5bSSebastian Reichel .reg_offset = 0, 343*c20e8c5bSSebastian Reichel }, 344*c20e8c5bSSebastian Reichel [RK818_IRQ_RTC_PERIOD] = { 345*c20e8c5bSSebastian Reichel .mask = RK818_IRQ_RTC_PERIOD_MSK, 346*c20e8c5bSSebastian Reichel .reg_offset = 0, 347*c20e8c5bSSebastian Reichel }, 348*c20e8c5bSSebastian Reichel [RK818_IRQ_USB_OV] = { 349*c20e8c5bSSebastian Reichel .mask = RK818_IRQ_USB_OV_MSK, 350*c20e8c5bSSebastian Reichel .reg_offset = 0, 351*c20e8c5bSSebastian Reichel }, 352*c20e8c5bSSebastian Reichel 353*c20e8c5bSSebastian Reichel /* INT_STS2 */ 354*c20e8c5bSSebastian Reichel [RK818_IRQ_PLUG_IN] = { 355*c20e8c5bSSebastian Reichel .mask = RK818_IRQ_PLUG_IN_MSK, 356*c20e8c5bSSebastian Reichel .reg_offset = 1, 357*c20e8c5bSSebastian Reichel }, 358*c20e8c5bSSebastian Reichel [RK818_IRQ_PLUG_OUT] = { 359*c20e8c5bSSebastian Reichel .mask = RK818_IRQ_PLUG_OUT_MSK, 360*c20e8c5bSSebastian Reichel .reg_offset = 1, 361*c20e8c5bSSebastian Reichel }, 362*c20e8c5bSSebastian Reichel [RK818_IRQ_CHG_OK] = { 363*c20e8c5bSSebastian Reichel .mask = RK818_IRQ_CHG_OK_MSK, 364*c20e8c5bSSebastian Reichel .reg_offset = 1, 365*c20e8c5bSSebastian Reichel }, 366*c20e8c5bSSebastian Reichel [RK818_IRQ_CHG_TE] = { 367*c20e8c5bSSebastian Reichel .mask = RK818_IRQ_CHG_TE_MSK, 368*c20e8c5bSSebastian Reichel .reg_offset = 1, 369*c20e8c5bSSebastian Reichel }, 370*c20e8c5bSSebastian Reichel [RK818_IRQ_CHG_TS1] = { 371*c20e8c5bSSebastian Reichel .mask = RK818_IRQ_CHG_TS1_MSK, 372*c20e8c5bSSebastian Reichel .reg_offset = 1, 373*c20e8c5bSSebastian Reichel }, 374*c20e8c5bSSebastian Reichel [RK818_IRQ_TS2] = { 375*c20e8c5bSSebastian Reichel .mask = RK818_IRQ_TS2_MSK, 376*c20e8c5bSSebastian Reichel .reg_offset = 1, 377*c20e8c5bSSebastian Reichel }, 378*c20e8c5bSSebastian Reichel [RK818_IRQ_CHG_CVTLIM] = { 379*c20e8c5bSSebastian Reichel .mask = RK818_IRQ_CHG_CVTLIM_MSK, 380*c20e8c5bSSebastian Reichel .reg_offset = 1, 381*c20e8c5bSSebastian Reichel }, 382*c20e8c5bSSebastian Reichel [RK818_IRQ_DISCHG_ILIM] = { 383*c20e8c5bSSebastian Reichel .mask = RK818_IRQ_DISCHG_ILIM_MSK, 384*c20e8c5bSSebastian Reichel .reg_offset = 1, 385*c20e8c5bSSebastian Reichel }, 386*c20e8c5bSSebastian Reichel }; 387*c20e8c5bSSebastian Reichel 388*c20e8c5bSSebastian Reichel static const struct regmap_irq rk817_irqs[RK817_IRQ_END] = { 389*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(0, 8), 390*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(1, 8), 391*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(2, 8), 392*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(3, 8), 393*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(4, 8), 394*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(5, 8), 395*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(6, 8), 396*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(7, 8), 397*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(8, 8), 398*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(9, 8), 399*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(10, 8), 400*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(11, 8), 401*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(12, 8), 402*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(13, 8), 403*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(14, 8), 404*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(15, 8), 405*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(16, 8), 406*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(17, 8), 407*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(18, 8), 408*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(19, 8), 409*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(20, 8), 410*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(21, 8), 411*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(22, 8), 412*c20e8c5bSSebastian Reichel REGMAP_IRQ_REG_LINE(23, 8) 413*c20e8c5bSSebastian Reichel }; 414*c20e8c5bSSebastian Reichel 415*c20e8c5bSSebastian Reichel static struct regmap_irq_chip rk805_irq_chip = { 416*c20e8c5bSSebastian Reichel .name = "rk805", 417*c20e8c5bSSebastian Reichel .irqs = rk805_irqs, 418*c20e8c5bSSebastian Reichel .num_irqs = ARRAY_SIZE(rk805_irqs), 419*c20e8c5bSSebastian Reichel .num_regs = 1, 420*c20e8c5bSSebastian Reichel .status_base = RK805_INT_STS_REG, 421*c20e8c5bSSebastian Reichel .mask_base = RK805_INT_STS_MSK_REG, 422*c20e8c5bSSebastian Reichel .ack_base = RK805_INT_STS_REG, 423*c20e8c5bSSebastian Reichel .init_ack_masked = true, 424*c20e8c5bSSebastian Reichel }; 425*c20e8c5bSSebastian Reichel 426*c20e8c5bSSebastian Reichel static const struct regmap_irq_chip rk808_irq_chip = { 427*c20e8c5bSSebastian Reichel .name = "rk808", 428*c20e8c5bSSebastian Reichel .irqs = rk808_irqs, 429*c20e8c5bSSebastian Reichel .num_irqs = ARRAY_SIZE(rk808_irqs), 430*c20e8c5bSSebastian Reichel .num_regs = 2, 431*c20e8c5bSSebastian Reichel .irq_reg_stride = 2, 432*c20e8c5bSSebastian Reichel .status_base = RK808_INT_STS_REG1, 433*c20e8c5bSSebastian Reichel .mask_base = RK808_INT_STS_MSK_REG1, 434*c20e8c5bSSebastian Reichel .ack_base = RK808_INT_STS_REG1, 435*c20e8c5bSSebastian Reichel .init_ack_masked = true, 436*c20e8c5bSSebastian Reichel }; 437*c20e8c5bSSebastian Reichel 438*c20e8c5bSSebastian Reichel static struct regmap_irq_chip rk817_irq_chip = { 439*c20e8c5bSSebastian Reichel .name = "rk817", 440*c20e8c5bSSebastian Reichel .irqs = rk817_irqs, 441*c20e8c5bSSebastian Reichel .num_irqs = ARRAY_SIZE(rk817_irqs), 442*c20e8c5bSSebastian Reichel .num_regs = 3, 443*c20e8c5bSSebastian Reichel .irq_reg_stride = 2, 444*c20e8c5bSSebastian Reichel .status_base = RK817_INT_STS_REG0, 445*c20e8c5bSSebastian Reichel .mask_base = RK817_INT_STS_MSK_REG0, 446*c20e8c5bSSebastian Reichel .ack_base = RK817_INT_STS_REG0, 447*c20e8c5bSSebastian Reichel .init_ack_masked = true, 448*c20e8c5bSSebastian Reichel }; 449*c20e8c5bSSebastian Reichel 450*c20e8c5bSSebastian Reichel static const struct regmap_irq_chip rk818_irq_chip = { 451*c20e8c5bSSebastian Reichel .name = "rk818", 452*c20e8c5bSSebastian Reichel .irqs = rk818_irqs, 453*c20e8c5bSSebastian Reichel .num_irqs = ARRAY_SIZE(rk818_irqs), 454*c20e8c5bSSebastian Reichel .num_regs = 2, 455*c20e8c5bSSebastian Reichel .irq_reg_stride = 2, 456*c20e8c5bSSebastian Reichel .status_base = RK818_INT_STS_REG1, 457*c20e8c5bSSebastian Reichel .mask_base = RK818_INT_STS_MSK_REG1, 458*c20e8c5bSSebastian Reichel .ack_base = RK818_INT_STS_REG1, 459*c20e8c5bSSebastian Reichel .init_ack_masked = true, 460*c20e8c5bSSebastian Reichel }; 461*c20e8c5bSSebastian Reichel 462*c20e8c5bSSebastian Reichel static int rk808_power_off(struct sys_off_data *data) 463*c20e8c5bSSebastian Reichel { 464*c20e8c5bSSebastian Reichel struct rk808 *rk808 = data->cb_data; 465*c20e8c5bSSebastian Reichel int ret; 466*c20e8c5bSSebastian Reichel unsigned int reg, bit; 467*c20e8c5bSSebastian Reichel 468*c20e8c5bSSebastian Reichel switch (rk808->variant) { 469*c20e8c5bSSebastian Reichel case RK805_ID: 470*c20e8c5bSSebastian Reichel reg = RK805_DEV_CTRL_REG; 471*c20e8c5bSSebastian Reichel bit = DEV_OFF; 472*c20e8c5bSSebastian Reichel break; 473*c20e8c5bSSebastian Reichel case RK808_ID: 474*c20e8c5bSSebastian Reichel reg = RK808_DEVCTRL_REG, 475*c20e8c5bSSebastian Reichel bit = DEV_OFF_RST; 476*c20e8c5bSSebastian Reichel break; 477*c20e8c5bSSebastian Reichel case RK809_ID: 478*c20e8c5bSSebastian Reichel case RK817_ID: 479*c20e8c5bSSebastian Reichel reg = RK817_SYS_CFG(3); 480*c20e8c5bSSebastian Reichel bit = DEV_OFF; 481*c20e8c5bSSebastian Reichel break; 482*c20e8c5bSSebastian Reichel case RK818_ID: 483*c20e8c5bSSebastian Reichel reg = RK818_DEVCTRL_REG; 484*c20e8c5bSSebastian Reichel bit = DEV_OFF; 485*c20e8c5bSSebastian Reichel break; 486*c20e8c5bSSebastian Reichel default: 487*c20e8c5bSSebastian Reichel return NOTIFY_DONE; 488*c20e8c5bSSebastian Reichel } 489*c20e8c5bSSebastian Reichel ret = regmap_update_bits(rk808->regmap, reg, bit, bit); 490*c20e8c5bSSebastian Reichel if (ret) 491*c20e8c5bSSebastian Reichel dev_err(rk808->dev, "Failed to shutdown device!\n"); 492*c20e8c5bSSebastian Reichel 493*c20e8c5bSSebastian Reichel return NOTIFY_DONE; 494*c20e8c5bSSebastian Reichel } 495*c20e8c5bSSebastian Reichel 496*c20e8c5bSSebastian Reichel static int rk808_restart(struct sys_off_data *data) 497*c20e8c5bSSebastian Reichel { 498*c20e8c5bSSebastian Reichel struct rk808 *rk808 = data->cb_data; 499*c20e8c5bSSebastian Reichel unsigned int reg, bit; 500*c20e8c5bSSebastian Reichel int ret; 501*c20e8c5bSSebastian Reichel 502*c20e8c5bSSebastian Reichel switch (rk808->variant) { 503*c20e8c5bSSebastian Reichel case RK809_ID: 504*c20e8c5bSSebastian Reichel case RK817_ID: 505*c20e8c5bSSebastian Reichel reg = RK817_SYS_CFG(3); 506*c20e8c5bSSebastian Reichel bit = DEV_RST; 507*c20e8c5bSSebastian Reichel break; 508*c20e8c5bSSebastian Reichel 509*c20e8c5bSSebastian Reichel default: 510*c20e8c5bSSebastian Reichel return NOTIFY_DONE; 511*c20e8c5bSSebastian Reichel } 512*c20e8c5bSSebastian Reichel ret = regmap_update_bits(rk808->regmap, reg, bit, bit); 513*c20e8c5bSSebastian Reichel if (ret) 514*c20e8c5bSSebastian Reichel dev_err(rk808->dev, "Failed to restart device!\n"); 515*c20e8c5bSSebastian Reichel 516*c20e8c5bSSebastian Reichel return NOTIFY_DONE; 517*c20e8c5bSSebastian Reichel } 518*c20e8c5bSSebastian Reichel 519*c20e8c5bSSebastian Reichel void rk8xx_shutdown(struct device *dev) 520*c20e8c5bSSebastian Reichel { 521*c20e8c5bSSebastian Reichel struct rk808 *rk808 = dev_get_drvdata(dev); 522*c20e8c5bSSebastian Reichel int ret; 523*c20e8c5bSSebastian Reichel 524*c20e8c5bSSebastian Reichel switch (rk808->variant) { 525*c20e8c5bSSebastian Reichel case RK805_ID: 526*c20e8c5bSSebastian Reichel ret = regmap_update_bits(rk808->regmap, 527*c20e8c5bSSebastian Reichel RK805_GPIO_IO_POL_REG, 528*c20e8c5bSSebastian Reichel SLP_SD_MSK, 529*c20e8c5bSSebastian Reichel SHUTDOWN_FUN); 530*c20e8c5bSSebastian Reichel break; 531*c20e8c5bSSebastian Reichel case RK809_ID: 532*c20e8c5bSSebastian Reichel case RK817_ID: 533*c20e8c5bSSebastian Reichel ret = regmap_update_bits(rk808->regmap, 534*c20e8c5bSSebastian Reichel RK817_SYS_CFG(3), 535*c20e8c5bSSebastian Reichel RK817_SLPPIN_FUNC_MSK, 536*c20e8c5bSSebastian Reichel SLPPIN_DN_FUN); 537*c20e8c5bSSebastian Reichel break; 538*c20e8c5bSSebastian Reichel default: 539*c20e8c5bSSebastian Reichel return; 540*c20e8c5bSSebastian Reichel } 541*c20e8c5bSSebastian Reichel if (ret) 542*c20e8c5bSSebastian Reichel dev_warn(dev, 543*c20e8c5bSSebastian Reichel "Cannot switch to power down function\n"); 544*c20e8c5bSSebastian Reichel } 545*c20e8c5bSSebastian Reichel EXPORT_SYMBOL_GPL(rk8xx_shutdown); 546*c20e8c5bSSebastian Reichel 547*c20e8c5bSSebastian Reichel int rk8xx_probe(struct device *dev, int variant, unsigned int irq, struct regmap *regmap) 548*c20e8c5bSSebastian Reichel { 549*c20e8c5bSSebastian Reichel struct rk808 *rk808; 550*c20e8c5bSSebastian Reichel const struct rk808_reg_data *pre_init_reg; 551*c20e8c5bSSebastian Reichel const struct mfd_cell *cells; 552*c20e8c5bSSebastian Reichel int nr_pre_init_regs; 553*c20e8c5bSSebastian Reichel int nr_cells; 554*c20e8c5bSSebastian Reichel int ret; 555*c20e8c5bSSebastian Reichel int i; 556*c20e8c5bSSebastian Reichel 557*c20e8c5bSSebastian Reichel rk808 = devm_kzalloc(dev, sizeof(*rk808), GFP_KERNEL); 558*c20e8c5bSSebastian Reichel if (!rk808) 559*c20e8c5bSSebastian Reichel return -ENOMEM; 560*c20e8c5bSSebastian Reichel rk808->dev = dev; 561*c20e8c5bSSebastian Reichel rk808->variant = variant; 562*c20e8c5bSSebastian Reichel rk808->regmap = regmap; 563*c20e8c5bSSebastian Reichel dev_set_drvdata(dev, rk808); 564*c20e8c5bSSebastian Reichel 565*c20e8c5bSSebastian Reichel switch (rk808->variant) { 566*c20e8c5bSSebastian Reichel case RK805_ID: 567*c20e8c5bSSebastian Reichel rk808->regmap_irq_chip = &rk805_irq_chip; 568*c20e8c5bSSebastian Reichel pre_init_reg = rk805_pre_init_reg; 569*c20e8c5bSSebastian Reichel nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg); 570*c20e8c5bSSebastian Reichel cells = rk805s; 571*c20e8c5bSSebastian Reichel nr_cells = ARRAY_SIZE(rk805s); 572*c20e8c5bSSebastian Reichel break; 573*c20e8c5bSSebastian Reichel case RK808_ID: 574*c20e8c5bSSebastian Reichel rk808->regmap_irq_chip = &rk808_irq_chip; 575*c20e8c5bSSebastian Reichel pre_init_reg = rk808_pre_init_reg; 576*c20e8c5bSSebastian Reichel nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg); 577*c20e8c5bSSebastian Reichel cells = rk808s; 578*c20e8c5bSSebastian Reichel nr_cells = ARRAY_SIZE(rk808s); 579*c20e8c5bSSebastian Reichel break; 580*c20e8c5bSSebastian Reichel case RK818_ID: 581*c20e8c5bSSebastian Reichel rk808->regmap_irq_chip = &rk818_irq_chip; 582*c20e8c5bSSebastian Reichel pre_init_reg = rk818_pre_init_reg; 583*c20e8c5bSSebastian Reichel nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg); 584*c20e8c5bSSebastian Reichel cells = rk818s; 585*c20e8c5bSSebastian Reichel nr_cells = ARRAY_SIZE(rk818s); 586*c20e8c5bSSebastian Reichel break; 587*c20e8c5bSSebastian Reichel case RK809_ID: 588*c20e8c5bSSebastian Reichel case RK817_ID: 589*c20e8c5bSSebastian Reichel rk808->regmap_irq_chip = &rk817_irq_chip; 590*c20e8c5bSSebastian Reichel pre_init_reg = rk817_pre_init_reg; 591*c20e8c5bSSebastian Reichel nr_pre_init_regs = ARRAY_SIZE(rk817_pre_init_reg); 592*c20e8c5bSSebastian Reichel cells = rk817s; 593*c20e8c5bSSebastian Reichel nr_cells = ARRAY_SIZE(rk817s); 594*c20e8c5bSSebastian Reichel break; 595*c20e8c5bSSebastian Reichel default: 596*c20e8c5bSSebastian Reichel dev_err(dev, "Unsupported RK8XX ID %lu\n", rk808->variant); 597*c20e8c5bSSebastian Reichel return -EINVAL; 598*c20e8c5bSSebastian Reichel } 599*c20e8c5bSSebastian Reichel 600*c20e8c5bSSebastian Reichel dev_info(dev, "chip id: 0x%x\n", (unsigned int)rk808->variant); 601*c20e8c5bSSebastian Reichel 602*c20e8c5bSSebastian Reichel if (!irq) 603*c20e8c5bSSebastian Reichel return dev_err_probe(dev, -EINVAL, "No interrupt support, no core IRQ\n"); 604*c20e8c5bSSebastian Reichel 605*c20e8c5bSSebastian Reichel ret = devm_regmap_add_irq_chip(dev, rk808->regmap, irq, 606*c20e8c5bSSebastian Reichel IRQF_ONESHOT, -1, 607*c20e8c5bSSebastian Reichel rk808->regmap_irq_chip, &rk808->irq_data); 608*c20e8c5bSSebastian Reichel if (ret) 609*c20e8c5bSSebastian Reichel return dev_err_probe(dev, ret, "Failed to add irq_chip\n"); 610*c20e8c5bSSebastian Reichel 611*c20e8c5bSSebastian Reichel for (i = 0; i < nr_pre_init_regs; i++) { 612*c20e8c5bSSebastian Reichel ret = regmap_update_bits(rk808->regmap, 613*c20e8c5bSSebastian Reichel pre_init_reg[i].addr, 614*c20e8c5bSSebastian Reichel pre_init_reg[i].mask, 615*c20e8c5bSSebastian Reichel pre_init_reg[i].value); 616*c20e8c5bSSebastian Reichel if (ret) 617*c20e8c5bSSebastian Reichel return dev_err_probe(dev, ret, "0x%x write err\n", 618*c20e8c5bSSebastian Reichel pre_init_reg[i].addr); 619*c20e8c5bSSebastian Reichel } 620*c20e8c5bSSebastian Reichel 621*c20e8c5bSSebastian Reichel ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, 622*c20e8c5bSSebastian Reichel cells, nr_cells, NULL, 0, 623*c20e8c5bSSebastian Reichel regmap_irq_get_domain(rk808->irq_data)); 624*c20e8c5bSSebastian Reichel if (ret) 625*c20e8c5bSSebastian Reichel return dev_err_probe(dev, ret, "failed to add MFD devices\n"); 626*c20e8c5bSSebastian Reichel 627*c20e8c5bSSebastian Reichel if (device_property_read_bool(dev, "rockchip,system-power-controller")) { 628*c20e8c5bSSebastian Reichel ret = devm_register_sys_off_handler(dev, 629*c20e8c5bSSebastian Reichel SYS_OFF_MODE_POWER_OFF_PREPARE, SYS_OFF_PRIO_HIGH, 630*c20e8c5bSSebastian Reichel &rk808_power_off, rk808); 631*c20e8c5bSSebastian Reichel if (ret) 632*c20e8c5bSSebastian Reichel return dev_err_probe(dev, ret, 633*c20e8c5bSSebastian Reichel "failed to register poweroff handler\n"); 634*c20e8c5bSSebastian Reichel 635*c20e8c5bSSebastian Reichel switch (rk808->variant) { 636*c20e8c5bSSebastian Reichel case RK809_ID: 637*c20e8c5bSSebastian Reichel case RK817_ID: 638*c20e8c5bSSebastian Reichel ret = devm_register_sys_off_handler(dev, 639*c20e8c5bSSebastian Reichel SYS_OFF_MODE_RESTART, SYS_OFF_PRIO_HIGH, 640*c20e8c5bSSebastian Reichel &rk808_restart, rk808); 641*c20e8c5bSSebastian Reichel if (ret) 642*c20e8c5bSSebastian Reichel dev_warn(dev, "failed to register rst handler, %d\n", ret); 643*c20e8c5bSSebastian Reichel break; 644*c20e8c5bSSebastian Reichel default: 645*c20e8c5bSSebastian Reichel dev_dbg(dev, "pmic controlled board reset not supported\n"); 646*c20e8c5bSSebastian Reichel break; 647*c20e8c5bSSebastian Reichel } 648*c20e8c5bSSebastian Reichel } 649*c20e8c5bSSebastian Reichel 650*c20e8c5bSSebastian Reichel return 0; 651*c20e8c5bSSebastian Reichel } 652*c20e8c5bSSebastian Reichel EXPORT_SYMBOL_GPL(rk8xx_probe); 653*c20e8c5bSSebastian Reichel 654*c20e8c5bSSebastian Reichel int rk8xx_suspend(struct device *dev) 655*c20e8c5bSSebastian Reichel { 656*c20e8c5bSSebastian Reichel struct rk808 *rk808 = dev_get_drvdata(dev); 657*c20e8c5bSSebastian Reichel int ret = 0; 658*c20e8c5bSSebastian Reichel 659*c20e8c5bSSebastian Reichel switch (rk808->variant) { 660*c20e8c5bSSebastian Reichel case RK805_ID: 661*c20e8c5bSSebastian Reichel ret = regmap_update_bits(rk808->regmap, 662*c20e8c5bSSebastian Reichel RK805_GPIO_IO_POL_REG, 663*c20e8c5bSSebastian Reichel SLP_SD_MSK, 664*c20e8c5bSSebastian Reichel SLEEP_FUN); 665*c20e8c5bSSebastian Reichel break; 666*c20e8c5bSSebastian Reichel case RK809_ID: 667*c20e8c5bSSebastian Reichel case RK817_ID: 668*c20e8c5bSSebastian Reichel ret = regmap_update_bits(rk808->regmap, 669*c20e8c5bSSebastian Reichel RK817_SYS_CFG(3), 670*c20e8c5bSSebastian Reichel RK817_SLPPIN_FUNC_MSK, 671*c20e8c5bSSebastian Reichel SLPPIN_SLP_FUN); 672*c20e8c5bSSebastian Reichel break; 673*c20e8c5bSSebastian Reichel default: 674*c20e8c5bSSebastian Reichel break; 675*c20e8c5bSSebastian Reichel } 676*c20e8c5bSSebastian Reichel 677*c20e8c5bSSebastian Reichel return ret; 678*c20e8c5bSSebastian Reichel } 679*c20e8c5bSSebastian Reichel EXPORT_SYMBOL_GPL(rk8xx_suspend); 680*c20e8c5bSSebastian Reichel 681*c20e8c5bSSebastian Reichel int rk8xx_resume(struct device *dev) 682*c20e8c5bSSebastian Reichel { 683*c20e8c5bSSebastian Reichel struct rk808 *rk808 = dev_get_drvdata(dev); 684*c20e8c5bSSebastian Reichel int ret = 0; 685*c20e8c5bSSebastian Reichel 686*c20e8c5bSSebastian Reichel switch (rk808->variant) { 687*c20e8c5bSSebastian Reichel case RK809_ID: 688*c20e8c5bSSebastian Reichel case RK817_ID: 689*c20e8c5bSSebastian Reichel ret = regmap_update_bits(rk808->regmap, 690*c20e8c5bSSebastian Reichel RK817_SYS_CFG(3), 691*c20e8c5bSSebastian Reichel RK817_SLPPIN_FUNC_MSK, 692*c20e8c5bSSebastian Reichel SLPPIN_NULL_FUN); 693*c20e8c5bSSebastian Reichel break; 694*c20e8c5bSSebastian Reichel default: 695*c20e8c5bSSebastian Reichel break; 696*c20e8c5bSSebastian Reichel } 697*c20e8c5bSSebastian Reichel 698*c20e8c5bSSebastian Reichel return ret; 699*c20e8c5bSSebastian Reichel } 700*c20e8c5bSSebastian Reichel EXPORT_SYMBOL_GPL(rk8xx_resume); 701*c20e8c5bSSebastian Reichel 702*c20e8c5bSSebastian Reichel MODULE_LICENSE("GPL"); 703*c20e8c5bSSebastian Reichel MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>"); 704*c20e8c5bSSebastian Reichel MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>"); 705*c20e8c5bSSebastian Reichel MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>"); 706*c20e8c5bSSebastian Reichel MODULE_DESCRIPTION("RK8xx PMIC core"); 707