From ce4e02a88b73f7e5828153811cc52b1c5539dcbf Mon Sep 17 00:00:00 2001 From: shengfei Xu Date: Fri, 7 Jul 2017 17:18:10 +0800 Subject: [PATCH] mfd: rk808: add rk816 support include sub modules: regulator, rtc, gpio, pwrkey Change-Id: I59cc4b943403f1e0b1210a314cfcbf61fc193bdf Signed-off-by: shengfei Xu --- .../devicetree/bindings/mfd/rk816.txt | 217 ++++++++++++++++++ drivers/clk/Kconfig | 4 +- drivers/gpio/gpio-rk8xx.c | 17 ++ drivers/mfd/rk808.c | 148 +++++++++++- drivers/regulator/Kconfig | 4 +- drivers/regulator/rk808-regulator.c | 214 ++++++++++++++++- drivers/rtc/Kconfig | 4 +- include/linux/mfd/rk808.h | 155 +++++++++++++ 8 files changed, 750 insertions(+), 13 deletions(-) create mode 100644 Documentation/devicetree/bindings/mfd/rk816.txt diff --git a/Documentation/devicetree/bindings/mfd/rk816.txt b/Documentation/devicetree/bindings/mfd/rk816.txt new file mode 100644 index 000000000000..75b1ecf547b0 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/rk816.txt @@ -0,0 +1,217 @@ +RK816 Power Management Integrated Circuit + +Required properties: +- compatible: "rockchip,rk816" +- reg: I2C slave address +- interrupt-parent: The parent interrupt controller. +- interrupts: the interrupt outputs of the controller. +- #clock-cells: from common clock binding; shall be set to 1 (multiple clock + outputs). + +Optional properties: +- clock-output-names: From common clock binding to override the + default output clock name +- rockchip,system-power-controller: Telling whether or not this pmic is controlling + the system power. +- gpio-controller: Specifies that the node is a gpio controller when you attempt to + use the TS pin of RK816 by GPIO general interface. +- #gpio-cells: Should be two. The first cell is the GPIO number and the second cell + is used to specify the GPIO polarity. +- wakeup-source: Flag to indicate this device can wake system (suspend/resume) +- vcc1-supply: The input supply for DCDC_REG1 +- vcc2-supply: The input supply for DCDC_REG2 +- vcc3-supply: The input supply for DCDC_REG3 +- vcc4-supply: The input supply for DCDC_REG4 +- vcc5-supply: The input supply for LDO_REG1, LDO_REG2, LDO_REG3 +- vcc6-supply: The input supply for LDO_REG4, LDO_REG5, LDO_REG6 + +Regulators: All the regulators of RK816 to be instantiated shall be +listed in a child node named 'regulators'. Each regulator is represented +by a child node of the 'regulators' node. + + regulator-name { + /* standard regulator bindings here */ + }; + +Following regulators of the RK816 PMIC block are supported. Note that +the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO +number as described in RK816 datasheet. + + - DCDC_REGn + - valid values for n are 1 to 4. + - LDO_REGn + - valid values for n are 1 to 6. + +Standard regulator bindings are used inside regulator subnodes. Check + Documentation/devicetree/bindings/regulator/regulator.txt +for more details + +Gpio, Rtc, Pwrkey: the node are represented like below. When you attempt to enable + the module, setting the "status" to be "okay", otherwise "disabled". + + rtc { + status = "okay"; + }; + + pwrkey { + status = "okay"; + }; + + gpio { + status = "okay"; + }; + +Example: + rk816: pmic@1a { + compatible = "rockchip,rk816"; + status = "disabled"; + reg = <0x1a>; + clock-output-names = "xin32k", "wifibt_32kin"; + interrupt-parent = <&gpio0>; + interrupts = <1 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + gpio-controller; + #gpio-cells = <2>; + + vcc1-supply = <&vcc_sys>; + vcc2-supply = <&vcc_sys>; + vcc3-supply = <&vcc_sys>; + vcc4-supply = <&vcc_sys>; + vcc5-supply = <&vcc_sys>; + vcc6-supply = <&vcc_sys>; + + rtc { + status = "okay"; + }; + + pwrkey { + status = "okay"; + }; + + gpio { + status = "okay"; + }; + + regulators { + vdd_cpu: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <6001>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + vdd_gpu: DCDC_REG2 { + regulator-name = "vdd_gpu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1250000>; + regulator-ramp-delay = <6001>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_ddr"; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc33_io: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc33_io"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vccio_pmu: LDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vccio_pmu"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_tp: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_tp"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_10: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-name = "vdd_10"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc18_lcd: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc18_lcd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vccio_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vdd10_lcd: LDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-name = "vdd10_lcd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + }; + }; diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index c3e3a02f7f1f..56698bd7cf77 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -52,10 +52,10 @@ config COMMON_CLK_MAX77802 This driver supports Maxim 77802 crystal oscillator clock. config COMMON_CLK_RK808 - tristate "Clock driver for RK808" + tristate "Clock driver for RK808/RK816" depends on MFD_RK808 ---help--- - This driver supports RK808 crystal oscillator clock. These + This driver supports RK808/RK816 crystal oscillator clock. These multi-function devices have two fixed-rate oscillators, clocked at 32KHz each. Clkout1 is always on, Clkout2 can off by control register. diff --git a/drivers/gpio/gpio-rk8xx.c b/drivers/gpio/gpio-rk8xx.c index 6adc8d408c4a..67577d21baab 100644 --- a/drivers/gpio/gpio-rk8xx.c +++ b/drivers/gpio/gpio-rk8xx.c @@ -29,6 +29,10 @@ #define RK805_OUT0_VALMASK BIT(0) #define RK805_OUT1_VALMASK BIT(1) +#define RK816_FUN_MASK BIT(2) +#define RK816_OUT_VALMASK BIT(3) +#define RK816_DIR_MASK BIT(4) + struct rk8xx_gpio_reg { u8 reg; u8 dir_msk; @@ -174,6 +178,15 @@ static struct rk8xx_gpio_reg rk805_gpio_reg[] = { }, }; +static struct rk8xx_gpio_reg rk816_gpio_reg[] = { + { + .reg = RK816_GPIO_IO_POL_REG, + .dir_msk = RK816_DIR_MASK, + .val_msk = RK816_OUT_VALMASK, + .fun_msk = RK816_FUN_MASK, + }, +}; + static int rk8xx_gpio_probe(struct platform_device *pdev) { struct rk808 *rk8xx = dev_get_drvdata(pdev->dev.parent); @@ -198,6 +211,10 @@ static int rk8xx_gpio_probe(struct platform_device *pdev) gi->gpio_reg = rk805_gpio_reg; gi->gpio_nr = ARRAY_SIZE(rk805_gpio_reg); break; + case RK816_ID: + gi->gpio_reg = rk816_gpio_reg; + gi->gpio_nr = ARRAY_SIZE(rk816_gpio_reg); + break; default: dev_err(&pdev->dev, "unsupported RK8XX ID %lu\n", rk8xx->variant); diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 4905291724f7..dadecc76e48e 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -69,6 +69,16 @@ static int rk808_shutdown(struct regmap *regmap) return ret; } +static int rk816_shutdown(struct regmap *regmap) +{ + int ret; + + ret = regmap_update_bits(regmap, + RK816_DEV_CTRL_REG, + DEV_OFF, DEV_OFF); + return ret; +} + static int rk818_shutdown(struct regmap *regmap) { int ret; @@ -146,6 +156,22 @@ static const struct regmap_config rk805_regmap_config = { .volatile_reg = rk808_is_volatile_reg, }; +static const struct regmap_config rk816_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK816_DATA18_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk818_is_volatile_reg, +}; + +static const struct regmap_config rk818_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK818_SAVE_DATA19, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk818_is_volatile_reg, +}; + static struct resource rtc_resources[] = { { .start = RK808_IRQ_RTC_ALARM, @@ -167,6 +193,19 @@ static struct resource pwrkey_resources[] = { }, }; +static struct resource rk816_pwrkey_resources[] = { + { + .start = RK816_IRQ_PWRON_RISE, + .end = RK816_IRQ_PWRON_RISE, + .flags = IORESOURCE_IRQ, + }, + { + .start = RK816_IRQ_PWRON_FALL, + .end = RK816_IRQ_PWRON_FALL, + .flags = IORESOURCE_IRQ, + }, +}; + static const struct mfd_cell rk808s[] = { { .name = "rk808-clkout", }, { .name = "rk808-regulator", }, @@ -243,12 +282,96 @@ static struct regmap_irq_chip rk808_irq_chip = { .init_ack_masked = true, }; -static const struct regmap_config rk818_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .max_register = RK818_SAVE_DATA19, - .cache_type = REGCACHE_RBTREE, - .volatile_reg = rk818_is_volatile_reg, +static const struct mfd_cell rk816s[] = { + { .name = "rk808-clkout", }, + { .name = "rk808-regulator", }, + { .name = "rk8xx-gpio", }, + { + .name = "rk8xx-pwrkey", + .num_resources = ARRAY_SIZE(rk816_pwrkey_resources), + .resources = &rk816_pwrkey_resources[0], + }, + { + .name = "rk808-rtc", + .num_resources = ARRAY_SIZE(rtc_resources), + .resources = &rtc_resources[0], + }, +}; + +static const struct rk808_reg_data rk816_pre_init_reg[] = { + /* buck4 Max ILMIT*/ + {RK816_BUCK4_CONFIG_REG, BUCK4_MAX_ILIMIT, REG_WRITE_MSK}, + /* hotdie temperature: 105c*/ + {RK816_THERMAL_REG, TEMP105C, REG_WRITE_MSK}, + /* set buck 12.5mv/us */ + {RK816_BUCK1_CONFIG_REG, BUCK_RATE_12_5MV_US, BUCK_RATE_MSK}, + {RK816_BUCK2_CONFIG_REG, BUCK_RATE_12_5MV_US, BUCK_RATE_MSK}, + /* enable RTC_PERIOD & RTC_ALARM int */ + {RK816_INT_STS_MSK_REG2, RTC_PERIOD_ALARM_INT_EN, REG_WRITE_MSK}, + /* set bat 3.0 low and act shutdown */ + {RK816_VB_MON_REG, RK816_VBAT_LOW_3V0 | EN_VABT_LOW_SHUT_DOWN, + VBAT_LOW_VOL_MASK | VBAT_LOW_ACT_MASK}, + /* enable PWRON rising/faling int */ + {RK816_INT_STS_MSK_REG1, RK816_PWRON_FALL_RISE_INT_EN, REG_WRITE_MSK}, + /* enable PLUG IN/OUT int */ + {RK816_INT_STS_MSK_REG3, PLUGIN_OUT_INT_EN, REG_WRITE_MSK}, + /* clear int flags */ + {RK816_INT_STS_REG1, ALL_INT_FLAGS_ST, REG_WRITE_MSK}, + {RK816_INT_STS_REG2, ALL_INT_FLAGS_ST, REG_WRITE_MSK}, + {RK816_INT_STS_REG3, ALL_INT_FLAGS_ST, REG_WRITE_MSK}, + {RK816_DCDC_EN_REG2, BOOST_DISABLE, BOOST_EN_MASK}, +}; + +static const struct regmap_irq rk816_irqs[] = { + /* INT_STS */ + [RK816_IRQ_PWRON_FALL] = { + .mask = RK816_IRQ_PWRON_FALL_MSK, + .reg_offset = 0, + }, + [RK816_IRQ_PWRON_RISE] = { + .mask = RK816_IRQ_PWRON_RISE_MSK, + .reg_offset = 0, + }, + [RK816_IRQ_VB_LOW] = { + .mask = RK816_IRQ_VB_LOW_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_PWRON] = { + .mask = RK816_IRQ_PWRON_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_PWRON_LP] = { + .mask = RK816_IRQ_PWRON_LP_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_HOTDIE] = { + .mask = RK816_IRQ_HOTDIE_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_RTC_ALARM] = { + .mask = RK816_IRQ_RTC_ALARM_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_RTC_PERIOD] = { + .mask = RK816_IRQ_RTC_PERIOD_MSK, + .reg_offset = 1, + }, + [RK816_IRQ_USB_OV] = { + .mask = RK816_IRQ_USB_OV_MSK, + .reg_offset = 1, + }, +}; + +static struct regmap_irq_chip rk816_irq_chip = { + .name = "rk816", + .irqs = rk816_irqs, + .num_irqs = ARRAY_SIZE(rk816_irqs), + .num_regs = 2, + .irq_reg_stride = 3, + .status_base = RK816_INT_STS_REG1, + .mask_base = RK816_INT_STS_MSK_REG1, + .ack_base = RK816_INT_STS_REG1, + .init_ack_masked = true, }; static const struct mfd_cell rk818s[] = { @@ -522,6 +645,7 @@ static struct device_attribute rk8xx_attrs = static const struct of_device_id rk808_of_match[] = { { .compatible = "rockchip,rk805" }, { .compatible = "rockchip,rk808" }, + { .compatible = "rockchip,rk816" }, { .compatible = "rockchip,rk818" }, { }, }; @@ -584,6 +708,17 @@ static int rk808_probe(struct i2c_client *client, on_source = RK818_ON_SOURCE_REG; off_source = RK818_OFF_SOURCE_REG; break; + case RK816_ID: + cell = rk816s; + cell_num = ARRAY_SIZE(rk816s); + pre_init_reg = rk816_pre_init_reg; + reg_num = ARRAY_SIZE(rk816_pre_init_reg); + regmap_config = &rk816_regmap_config; + irq_chip = &rk816_irq_chip; + pm_shutdown_fn = rk816_shutdown; + on_source = RK816_ON_SOURCE_REG; + off_source = RK816_OFF_SOURCE_REG; + break; case RK808_ID: cell = rk808s; cell_num = ARRAY_SIZE(rk808s); @@ -711,6 +846,7 @@ static int rk808_remove(struct i2c_client *client) static const struct i2c_device_id rk808_ids[] = { { "rk805" }, { "rk808" }, + { "rk816" }, { "rk818" }, { }, }; diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index f9dde4d26ea2..bc24890f7184 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -574,11 +574,11 @@ config REGULATOR_RC5T583 outputs which can be controlled by i2c communication. config REGULATOR_RK808 - tristate "Rockchip RK808/RK818 Power regulators" + tristate "Rockchip RK808/RK816/RK818 Power regulators" depends on MFD_RK808 help Select this option to enable the power regulator of ROCKCHIP - PMIC RK808 and RK818. + PMIC RK808/RK816/RK818. This driver supports the control of different power rails of device through regulator interface. The device supports multiple DCDC/LDO outputs which can be controlled by i2c communication. diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index a16d81420612..92c274217a1d 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -36,6 +36,11 @@ #define RK808_BUCK4_VSEL_MASK 0xf #define RK808_LDO_VSEL_MASK 0x1f +#define RK816_DCDC_SLP_EN_REG_OFFSET 2 +#define RK816_SWITCH_SLP_EN_REG_OFFSET 1 +#define RK816_LDO1_4_SLP_EN_REG_OFFSET 1 +#define RK816_LDO5_6_SLP_EN_REG_OFFSET 2 + #define RK818_BUCK_VSEL_MASK 0x3f #define RK818_BUCK4_VSEL_MASK 0x1f #define RK818_LDO_VSEL_MASK 0x1f @@ -86,6 +91,28 @@ .ops = &rk808_reg_ops, \ } +#define RK816_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \ + _vmask, _ereg, _emask, _disval, _etime) \ + [_id] = { \ + .name = (_match), \ + .supply_name = (_supply), \ + .of_match = of_match_ptr(_match), \ + .regulators_node = of_match_ptr("regulators"), \ + .type = REGULATOR_VOLTAGE, \ + .id = (_id), \ + .n_voltages = (((_max) - (_min)) / (_step) + 1), \ + .owner = THIS_MODULE, \ + .min_uV = (_min) * 1000, \ + .uV_step = (_step) * 1000, \ + .vsel_reg = (_vreg), \ + .vsel_mask = (_vmask), \ + .enable_reg = (_ereg), \ + .enable_mask = (_emask), \ + .disable_val = (_disval), \ + .enable_time = (_etime), \ + .ops = &rk808_reg_ops, \ + } + #define RK8XX_DESC_SWITCH(_id, _match, _supply, _ereg, _emask) \ [_id] = { \ .name = (_match), \ @@ -117,6 +144,17 @@ static const struct regulator_linear_range rk808_ldo3_voltage_ranges[] = { REGULATOR_LINEAR_RANGE(2500000, 15, 15, 0), }; +static const struct regulator_linear_range rk816_buck_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(712500, 0, 59, 12500), /* 0.7125v - 1.45v */ + REGULATOR_LINEAR_RANGE(1800000, 60, 62, 200000),/* 1.8v - 2.2v */ + REGULATOR_LINEAR_RANGE(2300000, 63, 63, 0), /* 2.3v - 2.3v */ +}; + +static const struct regulator_linear_range rk816_buck4_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(800000, 0, 26, 100000), /* 0.8v - 3.4 */ + REGULATOR_LINEAR_RANGE(3500000, 27, 31, 0), /* 3.5v */ +}; + static int rk808_buck1_2_get_voltage_sel_regmap(struct regulator_dev *rdev) { struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev); @@ -298,9 +336,72 @@ static int rk808_set_suspend_voltage_range(struct regulator_dev *rdev, int uv) sel); } +static int rk816_set_suspend_enable(struct regulator_dev *rdev) +{ + unsigned int reg, val; + + if (rdev->desc->id <= RK816_ID_DCDC4) + reg = rdev->desc->enable_reg + + RK816_DCDC_SLP_EN_REG_OFFSET; + + if ((rdev->desc->id > RK816_ID_DCDC4) && + (rdev->desc->id <= RK816_ID_OTG_SWITCH)) + reg = rdev->desc->enable_reg + + RK816_SWITCH_SLP_EN_REG_OFFSET; + + if ((rdev->desc->id > RK816_ID_OTG_SWITCH) && + (rdev->desc->id <= RK816_ID_LDO4)) + reg = rdev->desc->enable_reg - + RK816_LDO1_4_SLP_EN_REG_OFFSET; + + if ((rdev->desc->id > RK816_ID_LDO4) && + (rdev->desc->id <= RK816_ID_LDO6)) + reg = rdev->desc->enable_reg - + RK816_LDO5_6_SLP_EN_REG_OFFSET; + + val = 1 << (rdev->desc->id % 8); + return regmap_update_bits(rdev->regmap, reg, + val, + 0); +} + +static int rk816_set_suspend_disable(struct regulator_dev *rdev) +{ + unsigned int reg, val; + + if (rdev->desc->id <= RK816_ID_DCDC4) + reg = rdev->desc->enable_reg + + RK816_DCDC_SLP_EN_REG_OFFSET; + + if ((rdev->desc->id > RK816_ID_DCDC4) && + (rdev->desc->id <= RK816_ID_OTG_SWITCH)) + reg = rdev->desc->enable_reg + + RK816_SWITCH_SLP_EN_REG_OFFSET; + + if ((rdev->desc->id > RK816_ID_OTG_SWITCH) && + (rdev->desc->id <= RK816_ID_LDO4)) + reg = rdev->desc->enable_reg - + RK816_LDO1_4_SLP_EN_REG_OFFSET; + + if ((rdev->desc->id > RK816_ID_LDO4) && + (rdev->desc->id <= RK816_ID_LDO6)) + reg = rdev->desc->enable_reg - + RK816_LDO5_6_SLP_EN_REG_OFFSET; + + val = 1 << (rdev->desc->id % 8); + + return regmap_update_bits(rdev->regmap, reg, + val, + val); +} + static int rk808_set_suspend_enable(struct regulator_dev *rdev) { unsigned int reg; + struct rk808 *rk808 = dev_get_drvdata(rdev->dev.parent); + + if (rk808->variant == RK816_ID) + return rk816_set_suspend_enable(rdev); reg = rdev->desc->enable_reg + RK808_SLP_SET_OFF_REG_OFFSET; @@ -312,6 +413,10 @@ static int rk808_set_suspend_enable(struct regulator_dev *rdev) static int rk808_set_suspend_disable(struct regulator_dev *rdev) { unsigned int reg; + struct rk808 *rk808 = dev_get_drvdata(rdev->dev.parent); + + if (rk808->variant == RK816_ID) + return rk816_set_suspend_disable(rdev); reg = rdev->desc->enable_reg + RK808_SLP_SET_OFF_REG_OFFSET; @@ -463,6 +568,109 @@ static const struct regulator_desc rk808_reg[] = { RK808_DCDC_EN_REG, BIT(6)), }; +static const struct regulator_desc rk816_reg[] = { + { + .name = "DCDC_REG1", + .supply_name = "vcc1", + .of_match = of_match_ptr("DCDC_REG1"), + .regulators_node = of_match_ptr("regulators"), + .id = RK816_ID_DCDC1, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 64, + .linear_ranges = rk816_buck_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk816_buck_voltage_ranges), + .vsel_reg = RK816_BUCK1_ON_VSEL_REG, + .vsel_mask = RK818_BUCK_VSEL_MASK, + .enable_reg = RK816_DCDC_EN_REG1, + .enable_mask = BIT(4) | BIT(0), + .disable_val = BIT(4), + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG2", + .supply_name = "vcc2", + .of_match = of_match_ptr("DCDC_REG2"), + .regulators_node = of_match_ptr("regulators"), + .id = RK816_ID_DCDC2, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 64, + .linear_ranges = rk816_buck_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk816_buck_voltage_ranges), + .vsel_reg = RK816_BUCK2_ON_VSEL_REG, + .vsel_mask = RK818_BUCK_VSEL_MASK, + .enable_reg = RK816_DCDC_EN_REG1, + .enable_mask = BIT(5) | BIT(1), + .disable_val = BIT(5), + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG3", + .supply_name = "vcc3", + .of_match = of_match_ptr("DCDC_REG3"), + .regulators_node = of_match_ptr("regulators"), + .id = RK818_ID_DCDC3, + .ops = &rk808_switch_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 1, + .enable_reg = RK816_DCDC_EN_REG1, + .enable_mask = BIT(6) | BIT(2), + .disable_val = BIT(6), + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG4", + .supply_name = "vcc4", + .of_match = of_match_ptr("DCDC_REG4"), + .regulators_node = of_match_ptr("regulators"), + .id = RK816_ID_DCDC4, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 32, + .linear_ranges = rk816_buck4_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk816_buck4_voltage_ranges), + .vsel_reg = RK816_BUCK4_ON_VSEL_REG, + .vsel_mask = RK818_BUCK4_VSEL_MASK, + .enable_reg = RK816_DCDC_EN_REG1, + .enable_mask = BIT(7) | BIT(3), + .disable_val = BIT(7), + .owner = THIS_MODULE, + }, + RK816_DESC(RK816_ID_BOOST, "DCDC_BOOST", "boost", 4700, 5400, 100, + RK816_BOOST_ON_VESL_REG, RK818_BOOST_ON_VSEL_MASK, + RK816_DCDC_EN_REG2, BIT(4) | BIT(0), BIT(4), 0), + { + .name = "OTG_SWITCH", + .supply_name = "usb", + .of_match = of_match_ptr("OTG_SWITCH"), + .regulators_node = of_match_ptr("regulators"), + .id = RK816_ID_OTG_SWITCH, + .ops = &rk808_switch_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 1, + .enable_reg = RK816_DCDC_EN_REG2, + .enable_mask = BIT(6) | BIT(2), + .disable_val = BIT(6), + .owner = THIS_MODULE, + }, + RK816_DESC(RK816_ID_LDO1, "LDO_REG1", "vcc5", 800, 3400, 100, + RK816_LDO1_ON_VSEL_REG, RK818_LDO_VSEL_MASK, + RK816_LDO_EN_REG1, BIT(4) | BIT(0), BIT(4), 400), + RK816_DESC(RK816_ID_LDO2, "LDO_REG2", "vcc5", 800, 3400, 100, + RK816_LDO2_ON_VSEL_REG, RK818_LDO_VSEL_MASK, + RK816_LDO_EN_REG1, BIT(5) | BIT(1), BIT(5), 400), + RK816_DESC(RK816_ID_LDO3, "LDO_REG2", "vcc5", 800, 3400, 100, + RK816_LDO3_ON_VSEL_REG, RK818_LDO_VSEL_MASK, + RK816_LDO_EN_REG1, BIT(6) | BIT(2), BIT(6), 400), + RK816_DESC(RK816_ID_LDO4, "LDO_REG4", "vcc6", 800, 3400, 100, + RK816_LDO4_ON_VSEL_REG, RK818_LDO_VSEL_MASK, + RK816_LDO_EN_REG1, BIT(7) | BIT(3), BIT(7), 400), + RK816_DESC(RK816_ID_LDO5, "LDO_REG5", "vcc6", 800, 3400, 100, + RK816_LDO5_ON_VSEL_REG, RK818_LDO_VSEL_MASK, + RK816_LDO_EN_REG2, BIT(4) | BIT(0), BIT(4), 400), + RK816_DESC(RK816_ID_LDO6, "LDO_REG6", "vcc6", 800, 3400, 100, + RK816_LDO6_ON_VSEL_REG, RK818_LDO_VSEL_MASK, + RK816_LDO_EN_REG2, BIT(5) | BIT(1), BIT(5), 400), +}; + static const struct regulator_desc rk818_reg[] = { { .name = "DCDC_REG1", @@ -633,6 +841,10 @@ static int rk808_regulator_probe(struct platform_device *pdev) regulators = rk818_reg; nregulators = RK818_NUM_REGULATORS; break; + case RK816_ID: + regulators = rk816_reg; + nregulators = RK816_NUM_REGULATORS; + break; default: dev_err(&client->dev, "unsupported RK8XX ID %lu\n", rk808->variant); @@ -666,7 +878,7 @@ static struct platform_driver rk808_regulator_driver = { module_platform_driver(rk808_regulator_driver); -MODULE_DESCRIPTION("regulator driver for the RK808/RK818 series PMICs"); +MODULE_DESCRIPTION("regulator driver for the RK808/RK816/RK818 series PMICs"); MODULE_AUTHOR("Chris Zhong "); MODULE_AUTHOR("Zhang Qing "); MODULE_AUTHOR("Wadim Egorov "); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 2a524244afec..87e06adce2b9 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -326,11 +326,11 @@ config RTC_DRV_MAX77686 will be called rtc-max77686. config RTC_DRV_RK808 - tristate "Rockchip RK808 RTC" + tristate "Rockchip RK808/RK816 RTC" depends on MFD_RK808 help If you say yes here you will get support for the - RTC of RK808 PMIC. + RTC of RK808/RK816 PMIC. This driver can also be built as a module. If so, the module will be called rk808-rtc. diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h index d8f766135867..20d24c079961 100644 --- a/include/linux/mfd/rk808.h +++ b/include/linux/mfd/rk808.h @@ -47,6 +47,21 @@ enum rk808_reg { RK808_ID_SWITCH2, }; +enum rk816_reg { + RK816_ID_DCDC1, + RK816_ID_DCDC2, + RK816_ID_DCDC3, + RK816_ID_DCDC4, + RK816_ID_BOOST = 5, + RK816_ID_OTG_SWITCH, + RK816_ID_LDO1 = 8, + RK816_ID_LDO2, + RK816_ID_LDO3, + RK816_ID_LDO4, + RK816_ID_LDO5, + RK816_ID_LDO6, +}; + enum rk818_reg { RK818_ID_DCDC1, RK818_ID_DCDC2, @@ -530,6 +545,145 @@ enum rk805_reg { #define RK805_PWRON_FALL_RISE_INT_EN 0x0 #define RK805_PWRON_FALL_RISE_INT_MSK 0x81 +/*VERSION REGISTER*/ +#define RK816_CHIP_NAME_REG 0x17 +#define RK816_CHIP_VER_REG 0x18 +#define RK816_OTP_VER_REG 0x19 +#define RK816_NUM_REGULATORS 12 + +/*POWER ON/OFF REGISTER*/ +#define RK816_VB_MON_REG 0x21 +#define RK816_THERMAL_REG 0x22 +#define RK816_PWRON_LP_INT_TIME_REG 0x47 +#define RK816_PWRON_DB_REG 0x48 +#define RK816_DEV_CTRL_REG 0x4B +#define RK816_ON_SOURCE_REG 0xAE +#define RK816_OFF_SOURCE_REG 0xAF + +/*POWER CHANNELS ENABLE REGISTER*/ +#define RK816_DCDC_EN_REG1 0x23 +#define RK816_DCDC_EN_REG2 0x24 +#define RK816_SLP_DCDC_EN_REG 0x25 +#define RK816_SLP_LDO_EN_REG 0x26 +#define RK816_LDO_EN_REG1 0x27 +#define RK816_LDO_EN_REG2 0x28 + +/*BUCK AND LDO CONFIG REGISTER*/ +#define RK816_BUCK1_CONFIG_REG 0x2E +#define RK816_BUCK1_ON_VSEL_REG 0x2F +#define RK816_BUCK1_SLP_VSEL_REG 0x30 +#define RK816_BUCK2_CONFIG_REG 0x32 +#define RK816_BUCK2_ON_VSEL_REG 0x33 +#define RK816_BUCK2_SLP_VSEL_REG 0x34 +#define RK816_BUCK3_CONFIG_REG 0x36 +#define RK816_BUCK4_CONFIG_REG 0x37 +#define RK816_BUCK4_ON_VSEL_REG 0x38 +#define RK816_BUCK4_SLP_VSEL_REG 0x39 +#define RK816_LDO1_ON_VSEL_REG 0x3B +#define RK816_LDO1_SLP_VSEL_REG 0x3C +#define RK816_LDO2_ON_VSEL_REG 0x3D +#define RK816_LDO2_SLP_VSEL_REG 0x3E +#define RK816_LDO3_ON_VSEL_REG 0x3F +#define RK816_LDO3_SLP_VSEL_REG 0x40 +#define RK816_LDO4_ON_VSEL_REG 0x41 +#define RK816_LDO4_SLP_VSEL_REG 0x42 +#define RK816_LDO5_ON_VSEL_REG 0x43 +#define RK816_LDO5_SLP_VSEL_REG 0x44 +#define RK816_LDO6_ON_VSEL_REG 0x45 +#define RK816_LDO6_SLP_VSEL_REG 0x46 + +/*CHARGER BOOST AND OTG REGISTER*/ +#define RK816_OTG_BUCK_LDO_CONFIG_REG 0x2A +#define RK816_CHRG_CONFIG_REG 0x2B +#define RK816_BOOST_ON_VESL_REG 0x54 +#define RK816_BOOST_SLP_VSEL_REG 0x55 +#define RK816_CHRG_BOOST_CONFIG_REG 0x9A +#define RK816_SUP_STS_REG 0xA0 +#define RK816_USB_CTRL_REG 0xA1 +#define RK816_CHRG_CTRL_REG1 0xA3 +#define RK816_CHRG_CTRL_REG2 0xA4 +#define RK816_CHRG_CTRL_REG3 0xA5 +#define RK816_BAT_CTRL_REG 0xA6 +#define RK816_BAT_HTS_TS_REG 0xA8 +#define RK816_BAT_LTS_TS_REG 0xA9 + +/*INTERRUPT REGISTER*/ +#define RK816_INT_STS_REG1 0x49 +#define RK816_INT_STS_MSK_REG1 0x4A +#define RK816_INT_STS_REG2 0x4C +#define RK816_INT_STS_MSK_REG2 0x4D +#define RK816_INT_STS_REG3 0x4E +#define RK816_INT_STS_MSK_REG3 0x4F +#define RK816_GPIO_IO_POL_REG 0x50 + +#define RK816_DATA18_REG 0xF2 + +/* IRQ Definitions */ +#define RK816_IRQ_PWRON_FALL 0 +#define RK816_IRQ_PWRON_RISE 1 +#define RK816_IRQ_VB_LOW 2 +#define RK816_IRQ_PWRON 3 +#define RK816_IRQ_PWRON_LP 4 +#define RK816_IRQ_HOTDIE 5 +#define RK816_IRQ_RTC_ALARM 6 +#define RK816_IRQ_RTC_PERIOD 7 +#define RK816_IRQ_USB_OV 8 +#define RK816_IRQ_PLUG_IN 9 +#define RK816_IRQ_PLUG_OUT 10 +#define RK816_IRQ_CHG_OK 11 +#define RK816_IRQ_CHG_TE 12 +#define RK816_IRQ_CHG_TS 13 +#define RK816_IRQ_CHG_CVTLIM 14 +#define RK816_IRQ_DISCHG_ILIM 15 + +#define RK816_IRQ_PWRON_FALL_MSK BIT(5) +#define RK816_IRQ_PWRON_RISE_MSK BIT(6) +#define RK816_IRQ_VB_LOW_MSK BIT(1) +#define RK816_IRQ_PWRON_MSK BIT(2) +#define RK816_IRQ_PWRON_LP_MSK BIT(3) +#define RK816_IRQ_HOTDIE_MSK BIT(4) +#define RK816_IRQ_RTC_ALARM_MSK BIT(5) +#define RK816_IRQ_RTC_PERIOD_MSK BIT(6) +#define RK816_IRQ_USB_OV_MSK BIT(7) +#define RK816_IRQ_PLUG_IN_MSK BIT(0) +#define RK816_IRQ_PLUG_OUT_MSK BIT(1) +#define RK816_IRQ_CHG_OK_MSK BIT(2) +#define RK816_IRQ_CHG_TE_MSK BIT(3) +#define RK816_IRQ_CHG_TS_MSK BIT(4) +#define RK816_IRQ_CHG_CVTLIM_MSK BIT(6) +#define RK816_IRQ_DISCHG_ILIM_MSK BIT(7) + +#define RK816_VBAT_LOW_2V8 0x00 +#define RK816_VBAT_LOW_2V9 0x01 +#define RK816_VBAT_LOW_3V0 0x02 +#define RK816_VBAT_LOW_3V1 0x03 +#define RK816_VBAT_LOW_3V2 0x04 +#define RK816_VBAT_LOW_3V3 0x05 +#define RK816_VBAT_LOW_3V4 0x06 +#define RK816_VBAT_LOW_3V5 0x07 +#define RK816_PWR_FALL_INT_STATUS (0x1 << 5) +#define RK816_PWR_RISE_INT_STATUS (0x1 << 6) +#define RK816_ALARM_INT_STATUS (0x1 << 5) +#define EN_VBAT_LOW_IRQ (0x1 << 4) +#define VBAT_LOW_ACT_MASK (0x1 << 4) +#define RTC_TIMER_ALARM_INT_MSK (0x3 << 2) +#define RTC_TIMER_ALARM_INT_DIS (0x0 << 2) +#define RTC_PERIOD_ALARM_INT_MSK (0x3 << 5) +#define RTC_PERIOD_ALARM_INT_ST (0x3 << 5) +#define RTC_PERIOD_ALARM_INT_DIS (0x3 << 5) +#define RTC_PERIOD_ALARM_INT_EN (0x9f) +#define REG_WRITE_MSK 0xff +#define BUCK4_MAX_ILIMIT 0x2c +#define BUCK_RATE_MSK (0x3 << 3) +#define BUCK_RATE_12_5MV_US (0x2 << 3) +#define ALL_INT_FLAGS_ST 0xff +#define PLUGIN_OUT_INT_EN 0xfc +#define RK816_PWRON_FALL_RISE_INT_EN 0x9f +#define BUCK1_2_IMAX_MAX (0x3 << 6) +#define BUCK3_4_IMAX_MAX (0x3 << 3) +#define BOOST_DISABLE ((0x1 << 5) | (0x0 << 1)) + +#define TEMP105C 0x08 #define TEMP115C 0x0c #define TEMP_HOTDIE_MSK 0x0c #define SLP_SD_MSK (0x3 << 2) @@ -570,6 +724,7 @@ struct rk808 { enum { RK805_ID = 0x8050, RK808_ID = 0x0000, + RK816_ID = 0x8160, RK818_ID = 0x8180, }; -- 2.34.1