869 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * MFD core driver for Rockchip RK8XX4 *5 * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd6 * Copyright (C) 2016 PHYTEC Messtechnik GmbH7 *8 * Author: Chris Zhong <zyw@rock-chips.com>9 * Author: Zhang Qing <zhangqing@rock-chips.com>10 * Author: Wadim Egorov <w.egorov@phytec.de>11 */12 13#include <linux/interrupt.h>14#include <linux/mfd/rk808.h>15#include <linux/mfd/core.h>16#include <linux/module.h>17#include <linux/property.h>18#include <linux/regmap.h>19#include <linux/reboot.h>20 21struct rk808_reg_data {22 int addr;23 int mask;24 int value;25};26 27static const struct resource rtc_resources[] = {28 DEFINE_RES_IRQ(RK808_IRQ_RTC_ALARM),29};30 31static const struct resource rk816_rtc_resources[] = {32 DEFINE_RES_IRQ(RK816_IRQ_RTC_ALARM),33};34 35static const struct resource rk817_rtc_resources[] = {36 DEFINE_RES_IRQ(RK817_IRQ_RTC_ALARM),37};38 39static const struct resource rk805_key_resources[] = {40 DEFINE_RES_IRQ(RK805_IRQ_PWRON_RISE),41 DEFINE_RES_IRQ(RK805_IRQ_PWRON_FALL),42};43 44static struct resource rk806_pwrkey_resources[] = {45 DEFINE_RES_IRQ(RK806_IRQ_PWRON_FALL),46 DEFINE_RES_IRQ(RK806_IRQ_PWRON_RISE),47};48 49static const struct resource rk817_pwrkey_resources[] = {50 DEFINE_RES_IRQ(RK817_IRQ_PWRON_FALL),51 DEFINE_RES_IRQ(RK817_IRQ_PWRON_RISE),52};53 54static const struct resource rk817_charger_resources[] = {55 DEFINE_RES_IRQ(RK817_IRQ_PLUG_IN),56 DEFINE_RES_IRQ(RK817_IRQ_PLUG_OUT),57};58 59static const struct mfd_cell rk805s[] = {60 { .name = "rk808-clkout", },61 { .name = "rk808-regulator", },62 { .name = "rk805-pinctrl", },63 {64 .name = "rk808-rtc",65 .num_resources = ARRAY_SIZE(rtc_resources),66 .resources = &rtc_resources[0],67 },68 { .name = "rk805-pwrkey",69 .num_resources = ARRAY_SIZE(rk805_key_resources),70 .resources = &rk805_key_resources[0],71 },72};73 74static const struct mfd_cell rk806s[] = {75 { .name = "rk805-pinctrl", },76 { .name = "rk808-regulator", },77 {78 .name = "rk805-pwrkey",79 .resources = rk806_pwrkey_resources,80 .num_resources = ARRAY_SIZE(rk806_pwrkey_resources),81 },82};83 84static const struct mfd_cell rk808s[] = {85 { .name = "rk808-clkout", },86 { .name = "rk808-regulator", },87 {88 .name = "rk808-rtc",89 .num_resources = ARRAY_SIZE(rtc_resources),90 .resources = rtc_resources,91 },92};93 94static const struct mfd_cell rk816s[] = {95 { .name = "rk805-pinctrl", },96 { .name = "rk808-clkout", },97 { .name = "rk808-regulator", },98 {99 .name = "rk805-pwrkey",100 .num_resources = ARRAY_SIZE(rk805_key_resources),101 .resources = rk805_key_resources,102 },103 {104 .name = "rk808-rtc",105 .num_resources = ARRAY_SIZE(rk816_rtc_resources),106 .resources = rk816_rtc_resources,107 },108};109 110static const struct mfd_cell rk817s[] = {111 { .name = "rk808-clkout", },112 { .name = "rk808-regulator", },113 {114 .name = "rk805-pwrkey",115 .num_resources = ARRAY_SIZE(rk817_pwrkey_resources),116 .resources = &rk817_pwrkey_resources[0],117 },118 {119 .name = "rk808-rtc",120 .num_resources = ARRAY_SIZE(rk817_rtc_resources),121 .resources = &rk817_rtc_resources[0],122 },123 { .name = "rk817-codec", },124 {125 .name = "rk817-charger",126 .num_resources = ARRAY_SIZE(rk817_charger_resources),127 .resources = &rk817_charger_resources[0],128 },129};130 131static const struct mfd_cell rk818s[] = {132 { .name = "rk808-clkout", },133 { .name = "rk808-regulator", },134 {135 .name = "rk808-rtc",136 .num_resources = ARRAY_SIZE(rtc_resources),137 .resources = rtc_resources,138 },139};140 141static const struct rk808_reg_data rk805_pre_init_reg[] = {142 {RK805_BUCK1_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK,143 RK805_BUCK1_2_ILMAX_4000MA},144 {RK805_BUCK2_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK,145 RK805_BUCK1_2_ILMAX_4000MA},146 {RK805_BUCK3_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK,147 RK805_BUCK3_ILMAX_3000MA},148 {RK805_BUCK4_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK,149 RK805_BUCK4_ILMAX_3500MA},150 {RK805_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_400MA},151 {RK805_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP115C},152};153 154static const struct rk808_reg_data rk806_pre_init_reg[] = {155 { RK806_GPIO_INT_CONFIG, RK806_INT_POL_MSK, RK806_INT_POL_L },156 { RK806_SYS_CFG3, RK806_SLAVE_RESTART_FUN_MSK, RK806_SLAVE_RESTART_FUN_EN },157 { RK806_SYS_OPTION, RK806_SYS_ENB2_2M_MSK, RK806_SYS_ENB2_2M_EN },158};159 160static const struct rk808_reg_data rk808_pre_init_reg[] = {161 { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA },162 { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA },163 { RK808_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA },164 { RK808_BUCK1_CONFIG_REG, BUCK1_RATE_MASK, BUCK_ILMIN_200MA },165 { RK808_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_200MA },166 { RK808_DCDC_UV_ACT_REG, BUCK_UV_ACT_MASK, BUCK_UV_ACT_DISABLE},167 { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT |168 VB_LO_SEL_3500MV },169};170 171static const struct rk808_reg_data rk816_pre_init_reg[] = {172 { RK818_BUCK1_CONFIG_REG, RK817_RAMP_RATE_MASK,173 RK817_RAMP_RATE_12_5MV_PER_US },174 { RK818_BUCK2_CONFIG_REG, RK817_RAMP_RATE_MASK,175 RK817_RAMP_RATE_12_5MV_PER_US },176 { RK818_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_250MA },177 { RK808_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP105C},178 { RK808_VB_MON_REG, VBAT_LOW_VOL_MASK | VBAT_LOW_ACT_MASK,179 RK808_VBAT_LOW_3V0 | EN_VABT_LOW_SHUT_DOWN },180};181 182static const struct rk808_reg_data rk817_pre_init_reg[] = {183 {RK817_RTC_CTRL_REG, RTC_STOP, RTC_STOP},184 /* Codec specific registers */185 { RK817_CODEC_DTOP_VUCTL, MASK_ALL, 0x03 },186 { RK817_CODEC_DTOP_VUCTIME, MASK_ALL, 0x00 },187 { RK817_CODEC_DTOP_LPT_SRST, MASK_ALL, 0x00 },188 { RK817_CODEC_DTOP_DIGEN_CLKE, MASK_ALL, 0x00 },189 /* from vendor driver, CODEC_AREF_RTCFG0 not defined in data sheet */190 { RK817_CODEC_AREF_RTCFG0, MASK_ALL, 0x00 },191 { RK817_CODEC_AREF_RTCFG1, MASK_ALL, 0x06 },192 { RK817_CODEC_AADC_CFG0, MASK_ALL, 0xc8 },193 /* from vendor driver, CODEC_AADC_CFG1 not defined in data sheet */194 { RK817_CODEC_AADC_CFG1, MASK_ALL, 0x00 },195 { RK817_CODEC_DADC_VOLL, MASK_ALL, 0x00 },196 { RK817_CODEC_DADC_VOLR, MASK_ALL, 0x00 },197 { RK817_CODEC_DADC_SR_ACL0, MASK_ALL, 0x00 },198 { RK817_CODEC_DADC_ALC1, MASK_ALL, 0x00 },199 { RK817_CODEC_DADC_ALC2, MASK_ALL, 0x00 },200 { RK817_CODEC_DADC_NG, MASK_ALL, 0x00 },201 { RK817_CODEC_DADC_HPF, MASK_ALL, 0x00 },202 { RK817_CODEC_DADC_RVOLL, MASK_ALL, 0xff },203 { RK817_CODEC_DADC_RVOLR, MASK_ALL, 0xff },204 { RK817_CODEC_AMIC_CFG0, MASK_ALL, 0x70 },205 { RK817_CODEC_AMIC_CFG1, MASK_ALL, 0x00 },206 { RK817_CODEC_DMIC_PGA_GAIN, MASK_ALL, 0x66 },207 { RK817_CODEC_DMIC_LMT1, MASK_ALL, 0x00 },208 { RK817_CODEC_DMIC_LMT2, MASK_ALL, 0x00 },209 { RK817_CODEC_DMIC_NG1, MASK_ALL, 0x00 },210 { RK817_CODEC_DMIC_NG2, MASK_ALL, 0x00 },211 /* from vendor driver, CODEC_ADAC_CFG0 not defined in data sheet */212 { RK817_CODEC_ADAC_CFG0, MASK_ALL, 0x00 },213 { RK817_CODEC_ADAC_CFG1, MASK_ALL, 0x07 },214 { RK817_CODEC_DDAC_POPD_DACST, MASK_ALL, 0x82 },215 { RK817_CODEC_DDAC_VOLL, MASK_ALL, 0x00 },216 { RK817_CODEC_DDAC_VOLR, MASK_ALL, 0x00 },217 { RK817_CODEC_DDAC_SR_LMT0, MASK_ALL, 0x00 },218 { RK817_CODEC_DDAC_LMT1, MASK_ALL, 0x00 },219 { RK817_CODEC_DDAC_LMT2, MASK_ALL, 0x00 },220 { RK817_CODEC_DDAC_MUTE_MIXCTL, MASK_ALL, 0xa0 },221 { RK817_CODEC_DDAC_RVOLL, MASK_ALL, 0xff },222 { RK817_CODEC_DADC_RVOLR, MASK_ALL, 0xff },223 { RK817_CODEC_AMIC_CFG0, MASK_ALL, 0x70 },224 { RK817_CODEC_AMIC_CFG1, MASK_ALL, 0x00 },225 { RK817_CODEC_DMIC_PGA_GAIN, MASK_ALL, 0x66 },226 { RK817_CODEC_DMIC_LMT1, MASK_ALL, 0x00 },227 { RK817_CODEC_DMIC_LMT2, MASK_ALL, 0x00 },228 { RK817_CODEC_DMIC_NG1, MASK_ALL, 0x00 },229 { RK817_CODEC_DMIC_NG2, MASK_ALL, 0x00 },230 /* from vendor driver, CODEC_ADAC_CFG0 not defined in data sheet */231 { RK817_CODEC_ADAC_CFG0, MASK_ALL, 0x00 },232 { RK817_CODEC_ADAC_CFG1, MASK_ALL, 0x07 },233 { RK817_CODEC_DDAC_POPD_DACST, MASK_ALL, 0x82 },234 { RK817_CODEC_DDAC_VOLL, MASK_ALL, 0x00 },235 { RK817_CODEC_DDAC_VOLR, MASK_ALL, 0x00 },236 { RK817_CODEC_DDAC_SR_LMT0, MASK_ALL, 0x00 },237 { RK817_CODEC_DDAC_LMT1, MASK_ALL, 0x00 },238 { RK817_CODEC_DDAC_LMT2, MASK_ALL, 0x00 },239 { RK817_CODEC_DDAC_MUTE_MIXCTL, MASK_ALL, 0xa0 },240 { RK817_CODEC_DDAC_RVOLL, MASK_ALL, 0xff },241 { RK817_CODEC_DDAC_RVOLR, MASK_ALL, 0xff },242 { RK817_CODEC_AHP_ANTI0, MASK_ALL, 0x00 },243 { RK817_CODEC_AHP_ANTI1, MASK_ALL, 0x00 },244 { RK817_CODEC_AHP_CFG0, MASK_ALL, 0xe0 },245 { RK817_CODEC_AHP_CFG1, MASK_ALL, 0x1f },246 { RK817_CODEC_AHP_CP, MASK_ALL, 0x09 },247 { RK817_CODEC_ACLASSD_CFG1, MASK_ALL, 0x69 },248 { RK817_CODEC_ACLASSD_CFG2, MASK_ALL, 0x44 },249 { RK817_CODEC_APLL_CFG0, MASK_ALL, 0x04 },250 { RK817_CODEC_APLL_CFG1, MASK_ALL, 0x00 },251 { RK817_CODEC_APLL_CFG2, MASK_ALL, 0x30 },252 { RK817_CODEC_APLL_CFG3, MASK_ALL, 0x19 },253 { RK817_CODEC_APLL_CFG4, MASK_ALL, 0x65 },254 { RK817_CODEC_APLL_CFG5, MASK_ALL, 0x01 },255 { RK817_CODEC_DI2S_CKM, MASK_ALL, 0x01 },256 { RK817_CODEC_DI2S_RSD, MASK_ALL, 0x00 },257 { RK817_CODEC_DI2S_RXCR1, MASK_ALL, 0x00 },258 { RK817_CODEC_DI2S_RXCR2, MASK_ALL, 0x17 },259 { RK817_CODEC_DI2S_RXCMD_TSD, MASK_ALL, 0x00 },260 { RK817_CODEC_DI2S_TXCR1, MASK_ALL, 0x00 },261 { RK817_CODEC_DI2S_TXCR2, MASK_ALL, 0x17 },262 { RK817_CODEC_DI2S_TXCR3_TXCMD, MASK_ALL, 0x00 },263 {RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_L},264 {RK817_SYS_CFG(1), RK817_HOTDIE_TEMP_MSK | RK817_TSD_TEMP_MSK,265 RK817_HOTDIE_105 | RK817_TSD_140},266};267 268static const struct rk808_reg_data rk818_pre_init_reg[] = {269 /* improve efficiency */270 { RK818_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_250MA },271 { RK818_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_250MA },272 { RK818_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA },273 { RK818_USB_CTRL_REG, RK818_USB_ILIM_SEL_MASK,274 RK818_USB_ILMIN_2000MA },275 /* close charger when usb lower then 3.4V */276 { RK818_USB_CTRL_REG, RK818_USB_CHG_SD_VSEL_MASK,277 (0x7 << 4) },278 /* no action when vref */279 { RK818_H5V_EN_REG, BIT(1), RK818_REF_RDY_CTRL },280 /* enable HDMI 5V */281 { RK818_H5V_EN_REG, BIT(0), RK818_H5V_EN },282 { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT |283 VB_LO_SEL_3500MV },284};285 286static const struct regmap_irq rk805_irqs[] = {287 [RK805_IRQ_PWRON_RISE] = {288 .mask = RK805_IRQ_PWRON_RISE_MSK,289 .reg_offset = 0,290 },291 [RK805_IRQ_VB_LOW] = {292 .mask = RK805_IRQ_VB_LOW_MSK,293 .reg_offset = 0,294 },295 [RK805_IRQ_PWRON] = {296 .mask = RK805_IRQ_PWRON_MSK,297 .reg_offset = 0,298 },299 [RK805_IRQ_PWRON_LP] = {300 .mask = RK805_IRQ_PWRON_LP_MSK,301 .reg_offset = 0,302 },303 [RK805_IRQ_HOTDIE] = {304 .mask = RK805_IRQ_HOTDIE_MSK,305 .reg_offset = 0,306 },307 [RK805_IRQ_RTC_ALARM] = {308 .mask = RK805_IRQ_RTC_ALARM_MSK,309 .reg_offset = 0,310 },311 [RK805_IRQ_RTC_PERIOD] = {312 .mask = RK805_IRQ_RTC_PERIOD_MSK,313 .reg_offset = 0,314 },315 [RK805_IRQ_PWRON_FALL] = {316 .mask = RK805_IRQ_PWRON_FALL_MSK,317 .reg_offset = 0,318 },319};320 321static const struct regmap_irq rk806_irqs[] = {322 /* INT_STS0 IRQs */323 REGMAP_IRQ_REG(RK806_IRQ_PWRON_FALL, 0, RK806_INT_STS_PWRON_FALL),324 REGMAP_IRQ_REG(RK806_IRQ_PWRON_RISE, 0, RK806_INT_STS_PWRON_RISE),325 REGMAP_IRQ_REG(RK806_IRQ_PWRON, 0, RK806_INT_STS_PWRON),326 REGMAP_IRQ_REG(RK806_IRQ_PWRON_LP, 0, RK806_INT_STS_PWRON_LP),327 REGMAP_IRQ_REG(RK806_IRQ_HOTDIE, 0, RK806_INT_STS_HOTDIE),328 REGMAP_IRQ_REG(RK806_IRQ_VDC_RISE, 0, RK806_INT_STS_VDC_RISE),329 REGMAP_IRQ_REG(RK806_IRQ_VDC_FALL, 0, RK806_INT_STS_VDC_FALL),330 REGMAP_IRQ_REG(RK806_IRQ_VB_LO, 0, RK806_INT_STS_VB_LO),331 /* INT_STS1 IRQs */332 REGMAP_IRQ_REG(RK806_IRQ_REV0, 1, RK806_INT_STS_REV0),333 REGMAP_IRQ_REG(RK806_IRQ_REV1, 1, RK806_INT_STS_REV1),334 REGMAP_IRQ_REG(RK806_IRQ_REV2, 1, RK806_INT_STS_REV2),335 REGMAP_IRQ_REG(RK806_IRQ_CRC_ERROR, 1, RK806_INT_STS_CRC_ERROR),336 REGMAP_IRQ_REG(RK806_IRQ_SLP3_GPIO, 1, RK806_INT_STS_SLP3_GPIO),337 REGMAP_IRQ_REG(RK806_IRQ_SLP2_GPIO, 1, RK806_INT_STS_SLP2_GPIO),338 REGMAP_IRQ_REG(RK806_IRQ_SLP1_GPIO, 1, RK806_INT_STS_SLP1_GPIO),339 REGMAP_IRQ_REG(RK806_IRQ_WDT, 1, RK806_INT_STS_WDT),340};341 342static const struct regmap_irq rk808_irqs[] = {343 /* INT_STS */344 [RK808_IRQ_VOUT_LO] = {345 .mask = RK808_IRQ_VOUT_LO_MSK,346 .reg_offset = 0,347 },348 [RK808_IRQ_VB_LO] = {349 .mask = RK808_IRQ_VB_LO_MSK,350 .reg_offset = 0,351 },352 [RK808_IRQ_PWRON] = {353 .mask = RK808_IRQ_PWRON_MSK,354 .reg_offset = 0,355 },356 [RK808_IRQ_PWRON_LP] = {357 .mask = RK808_IRQ_PWRON_LP_MSK,358 .reg_offset = 0,359 },360 [RK808_IRQ_HOTDIE] = {361 .mask = RK808_IRQ_HOTDIE_MSK,362 .reg_offset = 0,363 },364 [RK808_IRQ_RTC_ALARM] = {365 .mask = RK808_IRQ_RTC_ALARM_MSK,366 .reg_offset = 0,367 },368 [RK808_IRQ_RTC_PERIOD] = {369 .mask = RK808_IRQ_RTC_PERIOD_MSK,370 .reg_offset = 0,371 },372 373 /* INT_STS2 */374 [RK808_IRQ_PLUG_IN_INT] = {375 .mask = RK808_IRQ_PLUG_IN_INT_MSK,376 .reg_offset = 1,377 },378 [RK808_IRQ_PLUG_OUT_INT] = {379 .mask = RK808_IRQ_PLUG_OUT_INT_MSK,380 .reg_offset = 1,381 },382};383 384static const unsigned int rk816_irq_status_offsets[] = {385 RK816_IRQ_STS_OFFSET(RK816_INT_STS_REG1),386 RK816_IRQ_STS_OFFSET(RK816_INT_STS_REG2),387 RK816_IRQ_STS_OFFSET(RK816_INT_STS_REG3),388};389 390static const unsigned int rk816_irq_mask_offsets[] = {391 RK816_IRQ_MSK_OFFSET(RK816_INT_STS_MSK_REG1),392 RK816_IRQ_MSK_OFFSET(RK816_INT_STS_MSK_REG2),393 RK816_IRQ_MSK_OFFSET(RK816_INT_STS_MSK_REG3),394};395 396static unsigned int rk816_get_irq_reg(struct regmap_irq_chip_data *data,397 unsigned int base, int index)398{399 unsigned int irq_reg = base;400 401 switch (base) {402 case RK816_INT_STS_REG1:403 irq_reg += rk816_irq_status_offsets[index];404 break;405 case RK816_INT_STS_MSK_REG1:406 irq_reg += rk816_irq_mask_offsets[index];407 break;408 }409 410 return irq_reg;411};412 413static const struct regmap_irq rk816_irqs[] = {414 /* INT_STS_REG1 IRQs */415 REGMAP_IRQ_REG(RK816_IRQ_PWRON_FALL, 0, RK816_INT_STS_PWRON_FALL),416 REGMAP_IRQ_REG(RK816_IRQ_PWRON_RISE, 0, RK816_INT_STS_PWRON_RISE),417 418 /* INT_STS_REG2 IRQs */419 REGMAP_IRQ_REG(RK816_IRQ_VB_LOW, 1, RK816_INT_STS_VB_LOW),420 REGMAP_IRQ_REG(RK816_IRQ_PWRON, 1, RK816_INT_STS_PWRON),421 REGMAP_IRQ_REG(RK816_IRQ_PWRON_LP, 1, RK816_INT_STS_PWRON_LP),422 REGMAP_IRQ_REG(RK816_IRQ_HOTDIE, 1, RK816_INT_STS_HOTDIE),423 REGMAP_IRQ_REG(RK816_IRQ_RTC_ALARM, 1, RK816_INT_STS_RTC_ALARM),424 REGMAP_IRQ_REG(RK816_IRQ_RTC_PERIOD, 1, RK816_INT_STS_RTC_PERIOD),425 REGMAP_IRQ_REG(RK816_IRQ_USB_OV, 1, RK816_INT_STS_USB_OV),426 427 /* INT_STS3 IRQs */428 REGMAP_IRQ_REG(RK816_IRQ_PLUG_IN, 2, RK816_INT_STS_PLUG_IN),429 REGMAP_IRQ_REG(RK816_IRQ_PLUG_OUT, 2, RK816_INT_STS_PLUG_OUT),430 REGMAP_IRQ_REG(RK816_IRQ_CHG_OK, 2, RK816_INT_STS_CHG_OK),431 REGMAP_IRQ_REG(RK816_IRQ_CHG_TE, 2, RK816_INT_STS_CHG_TE),432 REGMAP_IRQ_REG(RK816_IRQ_CHG_TS, 2, RK816_INT_STS_CHG_TS),433 REGMAP_IRQ_REG(RK816_IRQ_CHG_CVTLIM, 2, RK816_INT_STS_CHG_CVTLIM),434 REGMAP_IRQ_REG(RK816_IRQ_DISCHG_ILIM, 2, RK816_INT_STS_DISCHG_ILIM),435};436 437static const struct regmap_irq rk818_irqs[] = {438 /* INT_STS */439 [RK818_IRQ_VOUT_LO] = {440 .mask = RK818_IRQ_VOUT_LO_MSK,441 .reg_offset = 0,442 },443 [RK818_IRQ_VB_LO] = {444 .mask = RK818_IRQ_VB_LO_MSK,445 .reg_offset = 0,446 },447 [RK818_IRQ_PWRON] = {448 .mask = RK818_IRQ_PWRON_MSK,449 .reg_offset = 0,450 },451 [RK818_IRQ_PWRON_LP] = {452 .mask = RK818_IRQ_PWRON_LP_MSK,453 .reg_offset = 0,454 },455 [RK818_IRQ_HOTDIE] = {456 .mask = RK818_IRQ_HOTDIE_MSK,457 .reg_offset = 0,458 },459 [RK818_IRQ_RTC_ALARM] = {460 .mask = RK818_IRQ_RTC_ALARM_MSK,461 .reg_offset = 0,462 },463 [RK818_IRQ_RTC_PERIOD] = {464 .mask = RK818_IRQ_RTC_PERIOD_MSK,465 .reg_offset = 0,466 },467 [RK818_IRQ_USB_OV] = {468 .mask = RK818_IRQ_USB_OV_MSK,469 .reg_offset = 0,470 },471 472 /* INT_STS2 */473 [RK818_IRQ_PLUG_IN] = {474 .mask = RK818_IRQ_PLUG_IN_MSK,475 .reg_offset = 1,476 },477 [RK818_IRQ_PLUG_OUT] = {478 .mask = RK818_IRQ_PLUG_OUT_MSK,479 .reg_offset = 1,480 },481 [RK818_IRQ_CHG_OK] = {482 .mask = RK818_IRQ_CHG_OK_MSK,483 .reg_offset = 1,484 },485 [RK818_IRQ_CHG_TE] = {486 .mask = RK818_IRQ_CHG_TE_MSK,487 .reg_offset = 1,488 },489 [RK818_IRQ_CHG_TS1] = {490 .mask = RK818_IRQ_CHG_TS1_MSK,491 .reg_offset = 1,492 },493 [RK818_IRQ_TS2] = {494 .mask = RK818_IRQ_TS2_MSK,495 .reg_offset = 1,496 },497 [RK818_IRQ_CHG_CVTLIM] = {498 .mask = RK818_IRQ_CHG_CVTLIM_MSK,499 .reg_offset = 1,500 },501 [RK818_IRQ_DISCHG_ILIM] = {502 .mask = RK818_IRQ_DISCHG_ILIM_MSK,503 .reg_offset = 1,504 },505};506 507static const struct regmap_irq rk817_irqs[RK817_IRQ_END] = {508 REGMAP_IRQ_REG_LINE(0, 8),509 REGMAP_IRQ_REG_LINE(1, 8),510 REGMAP_IRQ_REG_LINE(2, 8),511 REGMAP_IRQ_REG_LINE(3, 8),512 REGMAP_IRQ_REG_LINE(4, 8),513 REGMAP_IRQ_REG_LINE(5, 8),514 REGMAP_IRQ_REG_LINE(6, 8),515 REGMAP_IRQ_REG_LINE(7, 8),516 REGMAP_IRQ_REG_LINE(8, 8),517 REGMAP_IRQ_REG_LINE(9, 8),518 REGMAP_IRQ_REG_LINE(10, 8),519 REGMAP_IRQ_REG_LINE(11, 8),520 REGMAP_IRQ_REG_LINE(12, 8),521 REGMAP_IRQ_REG_LINE(13, 8),522 REGMAP_IRQ_REG_LINE(14, 8),523 REGMAP_IRQ_REG_LINE(15, 8),524 REGMAP_IRQ_REG_LINE(16, 8),525 REGMAP_IRQ_REG_LINE(17, 8),526 REGMAP_IRQ_REG_LINE(18, 8),527 REGMAP_IRQ_REG_LINE(19, 8),528 REGMAP_IRQ_REG_LINE(20, 8),529 REGMAP_IRQ_REG_LINE(21, 8),530 REGMAP_IRQ_REG_LINE(22, 8),531 REGMAP_IRQ_REG_LINE(23, 8)532};533 534static const struct regmap_irq_chip rk805_irq_chip = {535 .name = "rk805",536 .irqs = rk805_irqs,537 .num_irqs = ARRAY_SIZE(rk805_irqs),538 .num_regs = 1,539 .status_base = RK805_INT_STS_REG,540 .mask_base = RK805_INT_STS_MSK_REG,541 .ack_base = RK805_INT_STS_REG,542 .init_ack_masked = true,543};544 545static const struct regmap_irq_chip rk806_irq_chip = {546 .name = "rk806",547 .irqs = rk806_irqs,548 .num_irqs = ARRAY_SIZE(rk806_irqs),549 .num_regs = 2,550 .irq_reg_stride = 2,551 .mask_base = RK806_INT_MSK0,552 .status_base = RK806_INT_STS0,553 .ack_base = RK806_INT_STS0,554 .init_ack_masked = true,555};556 557static const struct regmap_irq_chip rk808_irq_chip = {558 .name = "rk808",559 .irqs = rk808_irqs,560 .num_irqs = ARRAY_SIZE(rk808_irqs),561 .num_regs = 2,562 .irq_reg_stride = 2,563 .status_base = RK808_INT_STS_REG1,564 .mask_base = RK808_INT_STS_MSK_REG1,565 .ack_base = RK808_INT_STS_REG1,566 .init_ack_masked = true,567};568 569static const struct regmap_irq_chip rk816_irq_chip = {570 .name = "rk816",571 .irqs = rk816_irqs,572 .num_irqs = ARRAY_SIZE(rk816_irqs),573 .num_regs = 3,574 .get_irq_reg = rk816_get_irq_reg,575 .status_base = RK816_INT_STS_REG1,576 .mask_base = RK816_INT_STS_MSK_REG1,577 .ack_base = RK816_INT_STS_REG1,578 .init_ack_masked = true,579};580 581static const struct regmap_irq_chip rk817_irq_chip = {582 .name = "rk817",583 .irqs = rk817_irqs,584 .num_irqs = ARRAY_SIZE(rk817_irqs),585 .num_regs = 3,586 .irq_reg_stride = 2,587 .status_base = RK817_INT_STS_REG0,588 .mask_base = RK817_INT_STS_MSK_REG0,589 .ack_base = RK817_INT_STS_REG0,590 .init_ack_masked = true,591};592 593static const struct regmap_irq_chip rk818_irq_chip = {594 .name = "rk818",595 .irqs = rk818_irqs,596 .num_irqs = ARRAY_SIZE(rk818_irqs),597 .num_regs = 2,598 .irq_reg_stride = 2,599 .status_base = RK818_INT_STS_REG1,600 .mask_base = RK818_INT_STS_MSK_REG1,601 .ack_base = RK818_INT_STS_REG1,602 .init_ack_masked = true,603};604 605static int rk808_power_off(struct sys_off_data *data)606{607 struct rk808 *rk808 = data->cb_data;608 int ret;609 unsigned int reg, bit;610 611 switch (rk808->variant) {612 case RK805_ID:613 reg = RK805_DEV_CTRL_REG;614 bit = DEV_OFF;615 break;616 case RK806_ID:617 reg = RK806_SYS_CFG3;618 bit = DEV_OFF;619 break;620 case RK808_ID:621 reg = RK808_DEVCTRL_REG,622 bit = DEV_OFF_RST;623 break;624 case RK809_ID:625 case RK817_ID:626 reg = RK817_SYS_CFG(3);627 bit = DEV_OFF;628 break;629 case RK816_ID:630 case RK818_ID:631 reg = RK818_DEVCTRL_REG;632 bit = DEV_OFF;633 break;634 default:635 return NOTIFY_DONE;636 }637 ret = regmap_update_bits(rk808->regmap, reg, bit, bit);638 if (ret)639 dev_err(rk808->dev, "Failed to shutdown device!\n");640 641 return NOTIFY_DONE;642}643 644static int rk808_restart(struct sys_off_data *data)645{646 struct rk808 *rk808 = data->cb_data;647 unsigned int reg, bit;648 int ret;649 650 switch (rk808->variant) {651 case RK809_ID:652 case RK817_ID:653 reg = RK817_SYS_CFG(3);654 bit = DEV_RST;655 break;656 657 default:658 return NOTIFY_DONE;659 }660 ret = regmap_update_bits(rk808->regmap, reg, bit, bit);661 if (ret)662 dev_err(rk808->dev, "Failed to restart device!\n");663 664 return NOTIFY_DONE;665}666 667void rk8xx_shutdown(struct device *dev)668{669 struct rk808 *rk808 = dev_get_drvdata(dev);670 int ret;671 672 switch (rk808->variant) {673 case RK805_ID:674 ret = regmap_update_bits(rk808->regmap,675 RK805_GPIO_IO_POL_REG,676 SLP_SD_MSK,677 SHUTDOWN_FUN);678 break;679 case RK809_ID:680 case RK817_ID:681 ret = regmap_update_bits(rk808->regmap,682 RK817_SYS_CFG(3),683 RK817_SLPPIN_FUNC_MSK,684 SLPPIN_DN_FUN);685 break;686 default:687 return;688 }689 if (ret)690 dev_warn(dev,691 "Cannot switch to power down function\n");692}693EXPORT_SYMBOL_GPL(rk8xx_shutdown);694 695int rk8xx_probe(struct device *dev, int variant, unsigned int irq, struct regmap *regmap)696{697 struct rk808 *rk808;698 const struct rk808_reg_data *pre_init_reg;699 const struct mfd_cell *cells;700 int dual_support = 0;701 int nr_pre_init_regs;702 int nr_cells;703 int ret;704 int i;705 706 rk808 = devm_kzalloc(dev, sizeof(*rk808), GFP_KERNEL);707 if (!rk808)708 return -ENOMEM;709 rk808->dev = dev;710 rk808->variant = variant;711 rk808->regmap = regmap;712 dev_set_drvdata(dev, rk808);713 714 switch (rk808->variant) {715 case RK805_ID:716 rk808->regmap_irq_chip = &rk805_irq_chip;717 pre_init_reg = rk805_pre_init_reg;718 nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg);719 cells = rk805s;720 nr_cells = ARRAY_SIZE(rk805s);721 break;722 case RK806_ID:723 rk808->regmap_irq_chip = &rk806_irq_chip;724 pre_init_reg = rk806_pre_init_reg;725 nr_pre_init_regs = ARRAY_SIZE(rk806_pre_init_reg);726 cells = rk806s;727 nr_cells = ARRAY_SIZE(rk806s);728 dual_support = IRQF_SHARED;729 break;730 case RK808_ID:731 rk808->regmap_irq_chip = &rk808_irq_chip;732 pre_init_reg = rk808_pre_init_reg;733 nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg);734 cells = rk808s;735 nr_cells = ARRAY_SIZE(rk808s);736 break;737 case RK816_ID:738 rk808->regmap_irq_chip = &rk816_irq_chip;739 pre_init_reg = rk816_pre_init_reg;740 nr_pre_init_regs = ARRAY_SIZE(rk816_pre_init_reg);741 cells = rk816s;742 nr_cells = ARRAY_SIZE(rk816s);743 break;744 case RK818_ID:745 rk808->regmap_irq_chip = &rk818_irq_chip;746 pre_init_reg = rk818_pre_init_reg;747 nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg);748 cells = rk818s;749 nr_cells = ARRAY_SIZE(rk818s);750 break;751 case RK809_ID:752 case RK817_ID:753 rk808->regmap_irq_chip = &rk817_irq_chip;754 pre_init_reg = rk817_pre_init_reg;755 nr_pre_init_regs = ARRAY_SIZE(rk817_pre_init_reg);756 cells = rk817s;757 nr_cells = ARRAY_SIZE(rk817s);758 break;759 default:760 dev_err(dev, "Unsupported RK8XX ID %lu\n", rk808->variant);761 return -EINVAL;762 }763 764 if (!irq)765 return dev_err_probe(dev, -EINVAL, "No interrupt support, no core IRQ\n");766 767 ret = devm_regmap_add_irq_chip(dev, rk808->regmap, irq,768 IRQF_ONESHOT | dual_support, -1,769 rk808->regmap_irq_chip, &rk808->irq_data);770 if (ret)771 return dev_err_probe(dev, ret, "Failed to add irq_chip\n");772 773 for (i = 0; i < nr_pre_init_regs; i++) {774 ret = regmap_update_bits(rk808->regmap,775 pre_init_reg[i].addr,776 pre_init_reg[i].mask,777 pre_init_reg[i].value);778 if (ret)779 return dev_err_probe(dev, ret, "0x%x write err\n",780 pre_init_reg[i].addr);781 }782 783 ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, cells, nr_cells, NULL, 0,784 regmap_irq_get_domain(rk808->irq_data));785 if (ret)786 return dev_err_probe(dev, ret, "failed to add MFD devices\n");787 788 if (device_property_read_bool(dev, "rockchip,system-power-controller") ||789 device_property_read_bool(dev, "system-power-controller")) {790 ret = devm_register_sys_off_handler(dev,791 SYS_OFF_MODE_POWER_OFF_PREPARE, SYS_OFF_PRIO_HIGH,792 &rk808_power_off, rk808);793 if (ret)794 return dev_err_probe(dev, ret,795 "failed to register poweroff handler\n");796 797 switch (rk808->variant) {798 case RK809_ID:799 case RK817_ID:800 ret = devm_register_sys_off_handler(dev,801 SYS_OFF_MODE_RESTART, SYS_OFF_PRIO_HIGH,802 &rk808_restart, rk808);803 if (ret)804 dev_warn(dev, "failed to register rst handler, %d\n", ret);805 break;806 default:807 dev_dbg(dev, "pmic controlled board reset not supported\n");808 break;809 }810 }811 812 return 0;813}814EXPORT_SYMBOL_GPL(rk8xx_probe);815 816int rk8xx_suspend(struct device *dev)817{818 struct rk808 *rk808 = dev_get_drvdata(dev);819 int ret = 0;820 821 switch (rk808->variant) {822 case RK805_ID:823 ret = regmap_update_bits(rk808->regmap,824 RK805_GPIO_IO_POL_REG,825 SLP_SD_MSK,826 SLEEP_FUN);827 break;828 case RK809_ID:829 case RK817_ID:830 ret = regmap_update_bits(rk808->regmap,831 RK817_SYS_CFG(3),832 RK817_SLPPIN_FUNC_MSK,833 SLPPIN_SLP_FUN);834 break;835 default:836 break;837 }838 839 return ret;840}841EXPORT_SYMBOL_GPL(rk8xx_suspend);842 843int rk8xx_resume(struct device *dev)844{845 struct rk808 *rk808 = dev_get_drvdata(dev);846 int ret = 0;847 848 switch (rk808->variant) {849 case RK809_ID:850 case RK817_ID:851 ret = regmap_update_bits(rk808->regmap,852 RK817_SYS_CFG(3),853 RK817_SLPPIN_FUNC_MSK,854 SLPPIN_NULL_FUN);855 break;856 default:857 break;858 }859 860 return ret;861}862EXPORT_SYMBOL_GPL(rk8xx_resume);863 864MODULE_LICENSE("GPL");865MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");866MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");867MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");868MODULE_DESCRIPTION("RK8xx PMIC core");869