diff --git a/Documentation/devicetree/bindings/mfd/rk809.txt b/Documentation/devicetree/bindings/mfd/rk809.txt index 17c23275e892..577562a79ed0 100644 --- a/Documentation/devicetree/bindings/mfd/rk809.txt +++ b/Documentation/devicetree/bindings/mfd/rk809.txt @@ -41,6 +41,12 @@ number as described in RK808 datasheet. - valid values for n are 1 to 9. - SWITCH_REGn - valid values for n are 1 to 2. + + The gpio_slp pin is for controlling the pmic states, as below: + reset + power down + sleep + Standard regulator bindings are used inside regulator subnodes. Check Documentation/devicetree/bindings/regulator/regulator.txt for more details @@ -51,12 +57,16 @@ Example: reg = <0x20>; interrupt-parent = <&gpio0>; interrupts = <7 IRQ_TYPE_LEVEL_LOW>; - pinctrl-names = "default"; + pinctrl-names = "default", "pmic-sleep", + "pmic-power-off", "pmic-reset"; pinctrl-0 = <&pmic_int>; + pinctrl-1 = <&soc_slppin_slp>, <&rk817_slppin_slp>; + pinctrl-2 = <&soc_slppin_gpio>, <&rk817_slppin_pwrdn>; + pinctrl-3 = <&soc_slppin_rst>, <&rk817_slppin_rst>; rockchip,system-power-controller; wakeup-source; #clock-cells = <1>; - clock-output-names = "xin32k", "rk808-clkout2"; + clock-output-names = "rk808-clkout1", "rk808-clkout2"; vcc1-supply = <&vcc5v0_sys>; vcc2-supply = <&vcc5v0_sys>; @@ -68,59 +78,61 @@ Example: vcc8-supply = <&vcc3v3_sys>; vcc9-supply = <&vcc5v0_sys>; - vcc5v0_sys: vccsys{ - compatible = "regulator-fixed"; - regulator-name = "vcc5v0_sys"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; + pwrkey { + status = "okay"; }; - rk817_pin0_ts: rk817_pin0_ts { - pins = "gpio0"; - function = "pin_fun0"; - }; + pinctrl_rk8xx: pinctrl_rk8xx { + gpio-controller; + #gpio-cells = <2>; - rk817_pin0_gpio: rk817_pin0_gpio { - pins = "gpio0"; - function = "gpio"; - }; + rk817_slppin_null: rk817_slppin_null { + pins = "gpio_slp"; + function = "pin_fun0"; + }; - rk817_pin1_gt: rk817_pin1_gt { - pins = "gpio1"; - function = "pin_fun0"; - }; + rk817_slppin_slp: rk817_slppin_slp { + pins = "gpio_slp"; + function = "pin_fun1"; + }; - rk817_pin1_gpio: rk817_pin1_gpio { - pins = "gpio1"; - function = "gpio"; + rk817_slppin_pwrdn: rk817_slppin_pwrdn { + pins = "gpio_slp"; + function = "pin_fun2"; + }; + + rk817_slppin_rst: rk817_slppin_rst { + pins = "gpio_slp"; + function = "pin_fun3"; + }; }; regulators { - vdd_arm: DCDC_REG1 { + vdd_logic: DCDC_REG1 { regulator-always-on; regulator-boot-on; regulator-min-microvolt = <950000>; regulator-max-microvolt = <1350000>; regulator-ramp-delay = <6001>; - regulator-name = "vdd_arm"; + regulator-initial-mode = <0x1>; + regulator-name = "vdd_logic"; regulator-state-mem { regulator-on-in-suspend; - regulator-suspend-microvolt = <700000>; + regulator-suspend-microvolt = <950000>; }; }; - vdd_logic: DCDC_REG2 { + vdd_arm: DCDC_REG2 { regulator-always-on; regulator-boot-on; regulator-min-microvolt = <950000>; regulator-max-microvolt = <1350000>; regulator-ramp-delay = <6001>; - regulator-name = "vdd_logic"; + regulator-initial-mode = <0x1>; + regulator-name = "vdd_arm"; regulator-state-mem { regulator-off-in-suspend; - regulator-suspend-microvolt = <800000>; + regulator-suspend-microvolt = <950000>; }; }; @@ -128,6 +140,7 @@ Example: regulator-always-on; regulator-boot-on; regulator-name = "vcc_ddr"; + regulator-initial-mode = <0x1>; regulator-state-mem { regulator-on-in-suspend; }; @@ -138,6 +151,7 @@ Example: regulator-boot-on; regulator-min-microvolt = <3000000>; regulator-max-microvolt = <3000000>; + regulator-initial-mode = <0x1>; regulator-name = "vcc_3v0"; regulator-state-mem { regulator-off-in-suspend; @@ -178,7 +192,7 @@ Example: regulator-name = "vcc1v0_soc"; regulator-state-mem { - regulator-off-in-suspend; + regulator-on-in-suspend; regulator-suspend-microvolt = <1000000>; }; }; @@ -191,7 +205,7 @@ Example: regulator-name = "vcc3v0_pmu"; regulator-state-mem { - regulator-off-in-suspend; + regulator-on-in-suspend; regulator-suspend-microvolt = <3000000>; }; @@ -276,7 +290,6 @@ Example: }; vcc3v3_lcd: SWITCH_REG1 { - regulator-always-on; regulator-boot-on; regulator-name = "vcc3v3_lcd"; }; @@ -287,7 +300,16 @@ Example: regulator-name = "vcc5v0_host"; }; }; - }; - - + rk809_codec: codec { + #sound-dai-cells = <0>; + compatible = "rockchip,rk809-codec", "rockchip,rk817-codec"; + clocks = <&cru SCLK_I2S1_OUT>; + clock-names = "mclk"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s1_2ch_mclk>; + hp-volume = <20>; + spk-volume = <3>; + status = "okay"; + }; + } \ No newline at end of file diff --git a/Documentation/devicetree/bindings/mfd/rk817.txt b/Documentation/devicetree/bindings/mfd/rk817.txt index 062b9f7d957a..de4378306c5c 100644 --- a/Documentation/devicetree/bindings/mfd/rk817.txt +++ b/Documentation/devicetree/bindings/mfd/rk817.txt @@ -40,6 +40,18 @@ number as described in RK808 datasheet. - LDO_REGn - valid values for n are 1 to 9. +There are three pins needed config, named "gpio_ts" "gpio_gt" "gpio_slp". + The gpio_gt and gpio_ts pins support the gpio function. + For using a gpio function, dtsi need the following info: + pinctrl-names = "default"; + pinctrl-0 = <&rk817_ts_gpio1>, <&rk817_gt_gpio2>; + gpios = <&pinctrl_rk8xx 1 GPIO_ACTIVE_HIGH>, + <&pinctrl_rk8xx 2 GPIO_ACTIVE_HIGH>; + The gpio_slp pin is for controlling the pmic states, as below: + reset + power down + sleep + Standard regulator bindings are used inside regulator subnodes. Check Documentation/devicetree/bindings/regulator/regulator.txt for more details @@ -50,12 +62,16 @@ Example: reg = <0x20>; interrupt-parent = <&gpio0>; interrupts = <7 IRQ_TYPE_LEVEL_LOW>; - pinctrl-names = "default"; + pinctrl-names = "default", "pmic-sleep", + "pmic-power-off", "pmic-reset"; pinctrl-0 = <&pmic_int>; + pinctrl-1 = <&soc_slppin_slp>, <&rk817_slppin_slp>; + pinctrl-2 = <&soc_slppin_gpio>, <&rk817_slppin_pwrdn>; + pinctrl-3 = <&soc_slppin_rst>, <&rk817_slppin_rst>; rockchip,system-power-controller; wakeup-source; #clock-cells = <1>; - clock-output-names = "xin32k", "rk808-clkout2"; + clock-output-names = "rk808-clkout1", "rk808-clkout2"; vcc1-supply = <&vccsys>; vcc2-supply = <&vccsys>; @@ -63,75 +79,94 @@ Example: vcc4-supply = <&vccsys>; vcc5-supply = <&vccsys>; vcc6-supply = <&vccsys>; - vcc7-supply = <&vccsys>; + vcc7-supply = <&vcc_3v0>; vcc8-supply = <&vccsys>; - vcc9-supply = <&vccsys>; - vcc10-supply = <&vccsys>; - vcc11-supply = <&vcc_3v0>; - vcc12-supply = <&vcc_3v0>; - vcc13-supply = <&vcc_3v0>; - vcc14-supply = <&vccsys>; - vcc15-supply = <&rk817_boost>; + vcc9-supply = <&dcdc_boost>; - vccsys: vccsys{ - compatible = "regulator-fixed"; - regulator-name = "vcc3v8_sys"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3800000>; - regulator-max-microvolt = <3800000>; + pwrkey { + status = "okay"; }; - rk817_pin0_ts: rk817_pin0_ts { - pins = "gpio0"; - function = "pin_fun0"; - }; + pinctrl_rk8xx: pinctrl_rk8xx { + gpio-controller; + #gpio-cells = <2>; - rk817_pin0_gpio: rk817_pin0_gpio { - pins = "gpio0"; - function = "gpio"; - }; + rk817_ts_gpio1: rk817_ts_gpio1 { + pins = "gpio_ts"; + function = "pin_fun1"; + /* output-low; */ + /* input-enable; */ + }; - rk817_pin1_gt: rk817_pin1_gt { - pins = "gpio1"; - function = "pin_fun0"; - }; + rk817_gt_gpio2: rk817_gt_gpio2 { + pins = "gpio_gt"; + function = "pin_fun1"; + }; - rk817_pin1_gpio: rk817_pin1_gpio { - pins = "gpio1"; - function = "gpio"; + rk817_pin_ts: rk817_pin_ts { + pins = "gpio_ts"; + function = "pin_fun0"; + }; + + rk817_pin_gt: rk817_pin_gt { + pins = "gpio_gt"; + function = "pin_fun0"; + }; + + rk817_slppin_null: rk817_slppin_null { + pins = "gpio_slp"; + function = "pin_fun0"; + }; + + rk817_slppin_slp: rk817_slppin_slp { + pins = "gpio_slp"; + function = "pin_fun1"; + }; + + rk817_slppin_pwrdn: rk817_slppin_pwrdn { + pins = "gpio_slp"; + function = "pin_fun2"; + }; + + rk817_slppin_rst: rk817_slppin_rst { + pins = "gpio_slp"; + function = "pin_fun3"; + }; }; regulators { - vdd_arm: DCDC_REG1 { + vdd_logic: DCDC_REG1 { regulator-always-on; regulator-boot-on; regulator-min-microvolt = <950000>; regulator-max-microvolt = <1350000>; regulator-ramp-delay = <6001>; - regulator-name = "vdd_arm"; + regulator-initial-mode = <0x1>; + regulator-name = "vdd_logic"; regulator-state-mem { regulator-on-in-suspend; - regulator-suspend-microvolt = <700000>; + regulator-suspend-microvolt = <950000>; }; }; - vdd_logic: DCDC_REG2 { + vdd_arm: DCDC_REG2 { regulator-always-on; regulator-boot-on; regulator-min-microvolt = <950000>; regulator-max-microvolt = <1350000>; regulator-ramp-delay = <6001>; - regulator-name = "vdd_logic"; + regulator-initial-mode = <0x1>; + regulator-name = "vdd_arm"; regulator-state-mem { regulator-off-in-suspend; - regulator-suspend-microvolt = <800000>; + regulator-suspend-microvolt = <950000>; }; }; vcc_ddr: DCDC_REG3 { regulator-always-on; regulator-boot-on; + regulator-initial-mode = <0x1>; regulator-name = "vcc_ddr"; regulator-state-mem { regulator-on-in-suspend; @@ -143,6 +178,7 @@ Example: regulator-boot-on; regulator-min-microvolt = <3000000>; regulator-max-microvolt = <3000000>; + regulator-initial-mode = <0x1>; regulator-name = "vcc_3v0"; regulator-state-mem { regulator-off-in-suspend; @@ -175,7 +211,7 @@ Example: }; }; - vcc1v0_soc: LDO_REG3 { + vdd1v0_soc: LDO_REG3 { regulator-always-on; regulator-boot-on; regulator-min-microvolt = <1000000>; @@ -183,7 +219,7 @@ Example: regulator-name = "vcc1v0_soc"; regulator-state-mem { - regulator-off-in-suspend; + regulator-on-in-suspend; regulator-suspend-microvolt = <1000000>; }; }; @@ -196,7 +232,7 @@ Example: regulator-name = "vcc3v0_pmu"; regulator-state-mem { - regulator-off-in-suspend; + regulator-on-in-suspend; regulator-suspend-microvolt = <3000000>; }; @@ -218,7 +254,7 @@ Example: vcc_sd: LDO_REG6 { regulator-always-on; regulator-boot-on; - regulator-min-microvolt = <3300000>; //?? + regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-name = "vcc_sd"; @@ -229,46 +265,46 @@ Example: }; }; - vcc2v8_cif: LDO_REG7 { + vcc2v8_dvp: LDO_REG7 { regulator-always-on; regulator-boot-on; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; - regulator-name = "vcc2v8_cif"; + regulator-name = "vcc2v8_dvp"; regulator-state-mem { regulator-off-in-suspend; regulator-suspend-microvolt = <2800000>; }; }; - vcc1v8_cif: LDO_REG8 { + vcc1v8_dvp: LDO_REG8 { regulator-always-on; regulator-boot-on; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; - regulator-name = "vcc1v8_cif"; + regulator-name = "vcc1v8_dvp"; regulator-state-mem { regulator-on-in-suspend; regulator-suspend-microvolt = <1800000>; }; }; - vcc1v5_dvp: LDO_REG9 { + vdd1v5_dvp: LDO_REG9 { regulator-always-on; regulator-boot-on; regulator-min-microvolt = <1500000>; regulator-max-microvolt = <1500000>; - regulator-name = "vcc1v5_dvp"; + regulator-name = "vdd1v5_dvp"; regulator-state-mem { regulator-off-in-suspend; regulator-suspend-microvolt = <1500000>; }; }; - boost: BOOST { + dcdc_boost: BOOST { regulator-always-on; regulator-boot-on; regulator-min-microvolt = <4700000>; @@ -277,12 +313,52 @@ Example: }; otg_switch: OTG_SWITCH { - regulator-always-on; regulator-boot-on; regulator-name = "otg_switch"; }; }; - }; + battery { + compatible = "rk817,battery"; + ocv_table = <3500 3625 3685 3697 3718 3735 3748 + 3760 3774 3788 3802 3816 3834 3853 + 3877 3908 3946 3975 4018 4071 4106>; + design_capacity = <2500>; + design_qmax = <2750>; + bat_res = <100>; + sleep_enter_current = <300>; + sleep_exit_current = <300>; + sleep_filter_current = <100>; + power_off_thresd = <3500>; + zero_algorithm_vol = <3850>; + max_soc_offset = <60>; + monitor_sec = <5>; + sample_res = <10>; + virtual_power = <1>; + }; + charger { + compatible = "rk817,charger"; + min_input_voltage = <4500>; + max_input_current = <1500>; + max_chrg_current = <1300>; + max_chrg_voltage = <4200>; + chrg_term_mode = <1>; + chrg_finish_cur = <300>; + virtual_power = <0>; + dc_det_adc = <0>; + extcon = <&u2phy>; + }; + rk817_codec: codec { + #sound-dai-cells = <0>; + compatible = "rockchip,rk817-codec"; + clocks = <&cru SCLK_I2S1_OUT>; + clock-names = "mclk"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s1_2ch_mclk>; + hp-volume = <20>; + spk-volume = <3>; + status = "okay"; + }; + } diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 02ad3ae9aed3..730a645253c5 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -114,39 +114,66 @@ static int rk818_shutdown(struct regmap *regmap) return ret; } -static int rk805_shutdown_prepare(struct regmap *regmap) +static int rk805_shutdown_prepare(struct rk808 *rk808) { int ret; /* close rtc int when power off */ - regmap_update_bits(regmap, + regmap_update_bits(rk808->regmap, RK808_INT_STS_MSK_REG1, (0x3 << 5), (0x3 << 5)); - regmap_update_bits(regmap, + regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG, (0x3 << 2), (0x0 << 2)); /* pmic sleep shutdown function */ - ret = regmap_update_bits(regmap, + ret = regmap_update_bits(rk808->regmap, RK805_GPIO_IO_POL_REG, SLP_SD_MSK, SHUTDOWN_FUN); return ret; } -static int rk817_shutdown_prepare(struct regmap *regmap) +static int rk817_shutdown_prepare(struct rk808 *rk808) { int ret; /* close rtc int when power off */ - regmap_update_bits(regmap, + regmap_update_bits(rk808->regmap, RK817_INT_STS_MSK_REG1, (0x3 << 5), (0x3 << 5)); - regmap_update_bits(regmap, + regmap_update_bits(rk808->regmap, RK817_RTC_INT_REG, (0x3 << 2), (0x0 << 2)); + if (rk808->pins->p && rk808->pins->power_off) { + ret = regmap_update_bits(rk808->regmap, + RK817_SYS_CFG(3), + RK817_SLPPIN_FUNC_MSK, + SLPPIN_NULL_FUN); + if (ret) { + pr_err("shutdown: config SLPPIN_NULL_FUN error!\n"); + return 0; + } + + ret = regmap_update_bits(rk808->regmap, + RK817_SYS_CFG(3), + RK817_SLPPOL_MSK, + RK817_SLPPOL_H); + if (ret) { + pr_err("shutdown: config RK817_SLPPOL_H error!\n"); + return 0; + } + ret = pinctrl_select_state(rk808->pins->p, + rk808->pins->power_off); + if (ret) + pr_info("%s:failed to activate pwroff state\n", + __func__); + else + return ret; + } + /* pmic sleep shutdown function */ - ret = regmap_update_bits(regmap, + ret = regmap_update_bits(rk808->regmap, RK817_SYS_CFG(3), RK817_SLPPIN_FUNC_MSK, SLPPIN_DN_FUN); return ret; @@ -754,7 +781,6 @@ static struct regmap_irq_chip rk817_irq_chip = { static const struct mfd_cell rk817s[] = { { .name = "rk808-clkout",}, { .name = "rk808-regulator",}, - { .name = "rk805-pinctrl", }, { .name = "rk817-battery", .of_compatible = "rk817,battery", }, { .name = "rk817-charger", .of_compatible = "rk817,charger", }, { @@ -774,7 +800,6 @@ static const struct mfd_cell rk817s[] = { }; static const struct rk808_reg_data rk817_pre_init_reg[] = { - {RK817_SYS_CFG(3), RK817_SLPPIN_FUNC_MSK, SLPPIN_SLP_FUN}, {RK817_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, {RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_L}, {RK817_SYS_CFG(1), RK817_HOTDIE_TEMP_MSK | RK817_TSD_TEMP_MSK, @@ -782,7 +807,7 @@ static const struct rk808_reg_data rk817_pre_init_reg[] = { }; static int (*pm_shutdown)(struct regmap *regmap); -static int (*pm_shutdown_prepare)(struct regmap *regmap); +static int (*pm_shutdown_prepare)(struct rk808 *rk808); static struct i2c_client *rk808_i2c_client; static struct rk808_reg_data *suspend_reg, *resume_reg; static int suspend_reg_num, resume_reg_num; @@ -799,7 +824,7 @@ static void rk808_device_shutdown_prepare(void) } if (pm_shutdown_prepare) { - ret = pm_shutdown_prepare(rk808->regmap); + ret = pm_shutdown_prepare(rk808); if (ret) dev_err(&rk808_i2c_client->dev, "power off prepare error!\n"); @@ -913,6 +938,131 @@ out: return count; } +static int rk817_pinctrl_init(struct device *dev, struct rk808 *rk808) +{ + int ret; + struct platform_device *pinctrl_dev; + struct pinctrl_state *default_st; + + pinctrl_dev = platform_device_alloc("rk805-pinctrl", -1); + if (!pinctrl_dev) { + dev_err(dev, "Alloc pinctrl dev failed!\n"); + return -ENOMEM; + } + + pinctrl_dev->dev.parent = dev; + + ret = platform_device_add(pinctrl_dev); + + if (ret) { + platform_device_put(pinctrl_dev); + dev_err(dev, "Add rk805-pinctrl dev failed!\n"); + return ret; + } + if (dev->pins && !IS_ERR(dev->pins->p)) { + dev_info(dev, "had get a pinctrl!\n"); + return 0; + } + + rk808->pins = devm_kzalloc(dev, sizeof(struct rk808_pin_info), + GFP_KERNEL); + if (!rk808->pins) + return -ENOMEM; + + rk808->pins->p = devm_pinctrl_get(dev); + if (IS_ERR(rk808->pins->p)) { + rk808->pins->p = NULL; + dev_err(dev, "no pinctrl handle\n"); + return 0; + } + + default_st = pinctrl_lookup_state(rk808->pins->p, + PINCTRL_STATE_DEFAULT); + + if (IS_ERR(default_st)) { + dev_dbg(dev, "no default pinctrl state\n"); + return -EINVAL; + } + + ret = pinctrl_select_state(rk808->pins->p, default_st); + if (ret) { + dev_dbg(dev, "failed to activate default pinctrl state\n"); + return -EINVAL; + } + + rk808->pins->power_off = pinctrl_lookup_state(rk808->pins->p, + "pmic-power-off"); + if (IS_ERR(rk808->pins->power_off)) { + rk808->pins->power_off = NULL; + dev_dbg(dev, "no power-off pinctrl state\n"); + } + + rk808->pins->sleep = pinctrl_lookup_state(rk808->pins->p, + "pmic-sleep"); + if (IS_ERR(rk808->pins->sleep)) { + rk808->pins->sleep = NULL; + dev_dbg(dev, "no sleep-setting state\n"); + } + + rk808->pins->reset = pinctrl_lookup_state(rk808->pins->p, + "pmic-reset"); + if (IS_ERR(rk808->pins->reset)) { + rk808->pins->reset = NULL; + dev_dbg(dev, "no reset-setting pinctrl state\n"); + return 0; + } + + ret = regmap_update_bits(rk808->regmap, + RK817_SYS_CFG(3), + RK817_SLPPOL_MSK, + RK817_SLPPOL_L); + if (ret) { + dev_err(dev, "init: config RK817_SLPPOL_L error!\n"); + return -1; + } + + ret = pinctrl_select_state(rk808->pins->p, rk808->pins->reset); + + if (ret) + dev_dbg(dev, "failed to activate reset-setting pinctrl state\n"); + + return 0; +} + +static void rk817_of_property_prepare(struct regmap *regmap, struct device *dev) +{ + u32 inner; + int ret, func, msk, val; + struct device_node *np = dev->of_node; + + ret = of_property_read_u32_index(np, "fb-inner-reg-idxs", 0, &inner); + if (!ret && inner == RK817_ID_DCDC3) + regmap_update_bits(regmap, RK817_POWER_CONFIG, + RK817_BUCK3_FB_RES_MSK, + RK817_BUCK3_FB_RES_INTER); + else + regmap_update_bits(regmap, RK817_POWER_CONFIG, + RK817_BUCK3_FB_RES_MSK, + RK817_BUCK3_FB_RES_EXT); + dev_info(dev, "support dcdc3 fb mode:%d, %d\n", ret, inner); + + ret = of_property_read_u32(np, "pmic-reset-func", &func); + + msk = RK817_SLPPIN_FUNC_MSK | RK817_RST_FUNC_MSK; + val = SLPPIN_NULL_FUN; + + if (!ret && func < RK817_RST_FUNC_CNT) { + val |= RK817_RST_FUNC_MSK & + (func << RK817_RST_FUNC_SFT); + } else { + val |= RK817_RST_FUNC_REG; + } + + regmap_update_bits(regmap, RK817_SYS_CFG(3), msk, val); + + dev_info(dev, "support pmic reset mode:%d,%d\n", ret, func); +} + static struct kobject *rk8xx_kobj; static struct device_attribute rk8xx_attrs = __ATTR(rk8xx_dbg, 0200, NULL, rk8xx_dbg_store); @@ -935,7 +1085,7 @@ static int rk808_probe(struct i2c_client *client, struct device_node *np = client->dev.of_node; struct rk808 *rk808; int (*pm_shutdown_fn)(struct regmap *regmap) = NULL; - int (*pm_shutdown_prepare_fn)(struct regmap *regmap) = NULL; + int (*pm_shutdown_prepare_fn)(struct rk808 *rk808) = NULL; const struct rk808_reg_data *pre_init_reg; const struct regmap_config *regmap_config; const struct regmap_irq_chip *irq_chip, *battery_irq_chip = NULL; @@ -945,6 +1095,9 @@ static int rk808_probe(struct i2c_client *client, int ret, i, pm_off = 0; unsigned int on, off; u8 pmic_id_msb = RK808_ID_MSB, pmic_id_lsb = RK808_ID_LSB; + void (*of_property_prepare_fn)(struct regmap *regmap, + struct device *dev) = NULL; + int (*pinctrl_init)(struct device *dev, struct rk808 *rk808) = NULL; if (!client->irq) { dev_err(&client->dev, "No interrupt support, no core IRQ\n"); @@ -1046,6 +1199,8 @@ static int rk808_probe(struct i2c_client *client, pm_shutdown_prepare_fn = rk817_shutdown_prepare; on_source = RK817_ON_SOURCE_REG; off_source = RK817_OFF_SOURCE_REG; + of_property_prepare_fn = rk817_of_property_prepare; + pinctrl_init = rk817_pinctrl_init; break; default: dev_err(&client->dev, "unsupported RK8XX ID 0x%lx\n", @@ -1090,6 +1245,19 @@ static int rk808_probe(struct i2c_client *client, } } + if (of_property_prepare_fn) + of_property_prepare_fn(rk808->regmap, &client->dev); + + i2c_set_clientdata(client, rk808); + rk808->i2c = client; + rk808_i2c_client = client; + + if (pinctrl_init) { + ret = pinctrl_init(&client->dev, rk808); + if (ret) + return ret; + } + ret = regmap_add_irq_chip(rk808->regmap, client->irq, IRQF_ONESHOT | IRQF_SHARED, -1, irq_chip, &rk808->irq_data); @@ -1111,10 +1279,6 @@ static int rk808_probe(struct i2c_client *client, } } - rk808->i2c = client; - rk808_i2c_client = client; - i2c_set_clientdata(client, rk808); - ret = mfd_add_devices(&client->dev, -1, cell, cell_num, NULL, 0, regmap_irq_get_domain(rk808->irq_data)); @@ -1176,6 +1340,32 @@ static int rk808_suspend(struct device *dev) } } + if (rk808->pins->p && rk808->pins->sleep) { + ret = regmap_update_bits(rk808->regmap, + RK817_SYS_CFG(3), + RK817_SLPPIN_FUNC_MSK, + SLPPIN_NULL_FUN); + if (ret) { + dev_err(dev, "suspend: config SLPPIN_NULL_FUN error!\n"); + return -1; + } + + ret = regmap_update_bits(rk808->regmap, + RK817_SYS_CFG(3), + RK817_SLPPOL_MSK, + RK817_SLPPOL_H); + if (ret) { + dev_err(dev, "suspend: config RK817_SLPPOL_H error!\n"); + return -1; + } + + ret = pinctrl_select_state(rk808->pins->p, rk808->pins->sleep); + if (ret) { + dev_err(dev, "failed to act slp pinctrl state\n"); + return -1; + } + } + return 0; } @@ -1196,6 +1386,30 @@ static int rk808_resume(struct device *dev) } } + if (rk808->pins->p && rk808->pins->reset) { + ret = regmap_update_bits(rk808->regmap, + RK817_SYS_CFG(3), + RK817_SLPPIN_FUNC_MSK, + SLPPIN_NULL_FUN); + if (ret) { + dev_err(dev, "resume: config SLPPIN_NULL_FUN error!\n"); + return -1; + } + + ret = regmap_update_bits(rk808->regmap, + RK817_SYS_CFG(3), + RK817_SLPPOL_MSK, + RK817_SLPPOL_L); + if (ret) { + dev_err(dev, "resume: config RK817_SLPPOL_L error!\n"); + return -1; + } + + ret = pinctrl_select_state(rk808->pins->p, rk808->pins->reset); + if (ret) + dev_dbg(dev, "failed to act reset pinctrl state\n"); + } + return 0; } diff --git a/drivers/pinctrl/pinctrl-rk805.c b/drivers/pinctrl/pinctrl-rk805.c index b0bfd3082a1b..8810aabb7555 100644 --- a/drivers/pinctrl/pinctrl-rk805.c +++ b/drivers/pinctrl/pinctrl-rk805.c @@ -136,12 +136,118 @@ static struct rk805_pin_config rk805_gpio_cfgs[] = { }, }; +enum rk817_pinmux_option { + RK817_PINMUX_FUN0 = 0, + RK817_PINMUX_FUN1, + RK817_PINMUX_FUN2, + RK817_PINMUX_FUN3 +}; + +enum { + RK817_GPIO_SLP, + RK817_GPIO_TS, + RK817_GPIO_GT +}; + +/* for rk809 only a sleep pin */ +static const char *const rk817_gpio_groups[] = { + "gpio_slp", + "gpio_ts", + "gpio_gt", +}; + +static const struct pinctrl_pin_desc rk817_pins_desc[] = { + PINCTRL_PIN(RK817_GPIO_SLP, "gpio_slp"), /* sleep pin */ + PINCTRL_PIN(RK817_GPIO_TS, "gpio_ts"), /* ts pin */ + PINCTRL_PIN(RK817_GPIO_GT, "gpio_gt")/* gate pin */ +}; + +static const struct rk805_pin_function rk817_pin_functions[] = { + { + .name = "pin_fun0", + .groups = rk817_gpio_groups, + .ngroups = ARRAY_SIZE(rk817_gpio_groups), + .mux_option = RK817_PINMUX_FUN0, + }, + { + .name = "pin_fun1", + .groups = rk817_gpio_groups, + .ngroups = ARRAY_SIZE(rk817_gpio_groups), + .mux_option = RK817_PINMUX_FUN1, + }, + { + .name = "pin_fun2", + .groups = rk817_gpio_groups, + .ngroups = ARRAY_SIZE(rk817_gpio_groups), + .mux_option = RK817_PINMUX_FUN2, + }, + { + .name = "pin_fun3", + .groups = rk817_gpio_groups, + .ngroups = ARRAY_SIZE(rk817_gpio_groups), + .mux_option = RK817_PINMUX_FUN3, + }, +}; + +/* for rk809 only a sleep pin */ +static const struct rk805_pin_group rk817_pin_groups[] = { + { + .name = "gpio_slp", + .pins = { RK817_GPIO_SLP }, + .npins = 1, + }, + { + .name = "gpio_ts", + .pins = { RK817_GPIO_TS }, + .npins = 1, + }, + { + .name = "gpio_gt", + .pins = { RK817_GPIO_GT }, + .npins = 1, + } +}; + +#define RK817_GPIOTS_VAL_MSK BIT(3) +#define RK817_GPIOGT_VAL_MSK BIT(6) +#define RK817_GPIOTS_FUNC_MSK BIT(2) +#define RK817_GPIOGT_FUNC_MSK BIT(5) +#define RK817_GPIOTS_DIR_MSK BIT(4) +#define RK817_GPIOGT_DIR_MSK BIT(7) + +static struct rk805_pin_config rk817_gpio_cfgs[] = { + { + .reg = RK817_SYS_CFG(3), + .val_msk = 0, + .fun_msk = RK817_SLPPIN_FUNC_MSK, + .dir_msk = 0 + }, + { + .reg = RK817_GPIO_INT_CFG, + .val_msk = RK817_GPIOTS_VAL_MSK, + .fun_msk = RK817_GPIOTS_FUNC_MSK, + .dir_msk = RK817_GPIOTS_DIR_MSK + }, + { + .reg = RK817_GPIO_INT_CFG, + .val_msk = RK817_GPIOGT_VAL_MSK, + .fun_msk = RK817_GPIOGT_FUNC_MSK, + .dir_msk = RK817_GPIOGT_DIR_MSK + } +}; + /* generic gpio chip */ static int rk805_gpio_get(struct gpio_chip *chip, unsigned int offset) { struct rk805_pctrl_info *pci = gpiochip_get_data(chip); int ret, val; + if (!pci->pin_cfg[offset].val_msk) { + dev_dbg(pci->dev, "getting gpio%d value is not support\n", + offset); + return -1; + } + ret = regmap_read(pci->rk808->regmap, pci->pin_cfg[offset].reg, &val); if (ret) { dev_err(pci->dev, "get gpio%d value failed\n", offset); @@ -158,6 +264,9 @@ static void rk805_gpio_set(struct gpio_chip *chip, struct rk805_pctrl_info *pci = gpiochip_get_data(chip); int ret; + if (!pci->pin_cfg[offset].val_msk) + return; + ret = regmap_update_bits(pci->rk808->regmap, pci->pin_cfg[offset].reg, pci->pin_cfg[offset].val_msk, @@ -215,6 +324,20 @@ static struct gpio_chip rk805_gpio_chip = { .owner = THIS_MODULE, }; +static struct gpio_chip rk817_gpio_chip = { + .label = "rk817-gpio", + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, + .get_direction = rk805_gpio_get_direction, + .get = rk805_gpio_get, + .set = rk805_gpio_set, + .direction_input = rk805_gpio_direction_input, + .direction_output = rk805_gpio_direction_output, + .can_sleep = true, + .base = -1, + .owner = THIS_MODULE, +}; + /* generic pinctrl */ static int rk805_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) { @@ -290,7 +413,7 @@ static int _rk805_pinctrl_set_mux(struct pinctrl_dev *pctldev, if (!pci->pin_cfg[offset].fun_msk) return 0; - if (mux == RK805_PINMUX_GPIO) { + if (mux == RK805_PINMUX_GPIO) { ret = regmap_update_bits(pci->rk808->regmap, pci->pin_cfg[offset].reg, pci->pin_cfg[offset].fun_msk, @@ -307,6 +430,27 @@ static int _rk805_pinctrl_set_mux(struct pinctrl_dev *pctldev, return 0; } +static int _rk817_pinctrl_set_mux(struct pinctrl_dev *pctldev, + unsigned int offset, + int mux) +{ + struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); + int ret; + + if (!pci->pin_cfg[offset].fun_msk) + return 0; + + mux <<= ffs(pci->pin_cfg[offset].fun_msk) - 1; + ret = regmap_update_bits(pci->rk808->regmap, + pci->pin_cfg[offset].reg, + pci->pin_cfg[offset].fun_msk, mux); + + if (ret) + dev_err(pci->dev, "set gpio%d func%d failed\n", offset, mux); + + return ret; +} + static int rk805_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned int function, unsigned int group) @@ -315,7 +459,17 @@ static int rk805_pinctrl_set_mux(struct pinctrl_dev *pctldev, int mux = pci->functions[function].mux_option; int offset = group; - return _rk805_pinctrl_set_mux(pctldev, offset, mux); + switch (pci->rk808->variant) { + case RK805_ID: + return _rk805_pinctrl_set_mux(pctldev, offset, mux); + + case RK809_ID: + case RK817_ID: + return _rk817_pinctrl_set_mux(pctldev, offset, mux); + default: + dev_err(pci->dev, "Couldn't find the variant id\n"); + return -EINVAL; + } } static int rk805_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, @@ -325,13 +479,6 @@ static int rk805_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); int ret; - /* switch to gpio function */ - ret = _rk805_pinctrl_set_mux(pctldev, offset, RK805_PINMUX_GPIO); - if (ret) { - dev_err(pci->dev, "set gpio%d mux failed\n", offset); - return ret; - } - /* set direction */ if (!pci->pin_cfg[offset].dir_msk) return 0; @@ -391,8 +538,13 @@ static int rk805_pinconf_set(struct pinctrl_dev *pctldev, switch (param) { case PIN_CONFIG_OUTPUT: - rk805_gpio_set(&pci->gpio_chip, pin, arg); rk805_pmx_gpio_set_direction(pctldev, NULL, pin, false); + rk805_gpio_set(&pci->gpio_chip, pin, arg); + break; + case PIN_CONFIG_INPUT_ENABLE: + if (arg) + rk805_pmx_gpio_set_direction(pctldev, NULL, + pin, true); break; default: dev_err(pci->dev, "Properties not supported\n"); @@ -416,9 +568,18 @@ static struct pinctrl_desc rk805_pinctrl_desc = { .owner = THIS_MODULE, }; +static struct pinctrl_desc rk817_pinctrl_desc = { + .name = "rk817-pinctrl", + .pctlops = &rk805_pinctrl_ops, + .pmxops = &rk805_pinmux_ops, + .confops = &rk805_pinconf_ops, + .owner = THIS_MODULE, +}; + static int rk805_pinctrl_probe(struct platform_device *pdev) { struct rk805_pctrl_info *pci; + struct device_node *np; int ret; pci = devm_kzalloc(&pdev->dev, sizeof(*pci), GFP_KERNEL); @@ -426,18 +587,19 @@ static int rk805_pinctrl_probe(struct platform_device *pdev) return -ENOMEM; pci->dev = &pdev->dev; - pci->dev->of_node = pdev->dev.parent->of_node; + np = of_get_child_by_name(pdev->dev.parent->of_node, "pinctrl_rk8xx"); + if (np) + pci->dev->of_node = np; + else + pci->dev->of_node = pdev->dev.parent->of_node; pci->rk808 = dev_get_drvdata(pdev->dev.parent); - pci->pinctrl_desc = rk805_pinctrl_desc; - pci->gpio_chip = rk805_gpio_chip; - pci->gpio_chip.parent = &pdev->dev; - pci->gpio_chip.of_node = pdev->dev.parent->of_node; - platform_set_drvdata(pdev, pci); switch (pci->rk808->variant) { case RK805_ID: + pci->pinctrl_desc = rk805_pinctrl_desc; + pci->gpio_chip = rk805_gpio_chip; pci->pins = rk805_pins_desc; pci->num_pins = ARRAY_SIZE(rk805_pins_desc); pci->functions = rk805_pin_functions; @@ -449,13 +611,42 @@ static int rk805_pinctrl_probe(struct platform_device *pdev) pci->pin_cfg = rk805_gpio_cfgs; pci->gpio_chip.ngpio = ARRAY_SIZE(rk805_gpio_cfgs); break; + case RK809_ID: + case RK817_ID: + pci->pinctrl_desc = rk817_pinctrl_desc; + pci->gpio_chip = rk817_gpio_chip; + pci->pins = rk817_pins_desc; + pci->num_pins = ARRAY_SIZE(rk817_pins_desc); + pci->functions = rk817_pin_functions; + pci->num_functions = ARRAY_SIZE(rk817_pin_functions); + pci->groups = rk817_pin_groups; + pci->num_pin_groups = ARRAY_SIZE(rk817_pin_groups); + pci->pinctrl_desc.pins = rk817_pins_desc; + pci->pinctrl_desc.npins = ARRAY_SIZE(rk817_pins_desc); + pci->pin_cfg = rk817_gpio_cfgs; + pci->gpio_chip.ngpio = ARRAY_SIZE(rk817_gpio_cfgs); + /* for rk809 only a sleep pin */ + if (pci->rk808->variant == RK809_ID) { + pci->pinctrl_desc.npins = 1; + pci->num_pin_groups = 1; + pci->num_pins = 1; + pci->gpio_chip.ngpio = 1; + } + break; default: dev_err(&pdev->dev, "unsupported RK805 ID %lu\n", pci->rk808->variant); return -EINVAL; } - /* Add gpio chip */ + pci->gpio_chip.parent = &pdev->dev; + + if (np) + pci->gpio_chip.of_node = np; + else + pci->gpio_chip.of_node = pdev->dev.parent->of_node; + + /* Add gpiochip */ ret = devm_gpiochip_add_data(&pdev->dev, &pci->gpio_chip, pci); if (ret < 0) { dev_err(&pdev->dev, "Couldn't add gpiochip\n"); @@ -486,7 +677,12 @@ static struct platform_driver rk805_pinctrl_driver = { .name = "rk805-pinctrl", }, }; -module_platform_driver(rk805_pinctrl_driver); + +static int __init rk805_pinctrl_driver_register(void) +{ + return platform_driver_register(&rk805_pinctrl_driver); +} +fs_initcall_sync(rk805_pinctrl_driver_register); MODULE_DESCRIPTION("RK805 pin control and GPIO driver"); MODULE_AUTHOR("Joseph Chen "); diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h index fd37ab08beb2..ad9e1558fba0 100644 --- a/include/linux/mfd/rk808.h +++ b/include/linux/mfd/rk808.h @@ -814,6 +814,8 @@ enum rk809_reg_id { #define RK817_POWER_EN_REG(i) (0xb1 + (i)) #define RK817_POWER_SLP_EN_REG(i) (0xb5 + (i)) +#define RK817_POWER_CONFIG (0xb9) + #define RK817_BUCK_CONFIG_REG(i) (0xba + (i) * 3) #define RK817_BUCK1_ON_VSEL_REG 0xBB @@ -885,6 +887,11 @@ enum rk809_reg_id { */ #define RK817_RTC_CTRL_RSV4 BIT(4) +/* power config 0xb9 */ +#define RK817_BUCK3_FB_RES_MSK BIT(6) +#define RK817_BUCK3_FB_RES_INTER BIT(6) +#define RK817_BUCK3_FB_RES_EXT 0 + /* buck config 0xba */ #define RK817_RAMP_RATE_OFFSET 6 #define RK817_RAMP_RATE_MASK (0x3 << RK817_RAMP_RATE_OFFSET) @@ -913,8 +920,15 @@ enum rk809_reg_id { #define SLPPIN_DN_FUN (0x2 << 3) #define SLPPIN_RST_FUN (0x3 << 3) +#define RK817_RST_FUNC_MSK (0x3 << 6) +#define RK817_RST_FUNC_SFT (6) +#define RK817_RST_FUNC_CNT (3) +#define RK817_RST_FUNC_DEV (0) /* reset the dev */ +#define RK817_RST_FUNC_REG (0x1 << 6) /* reset the reg only */ + #define RK817_SLPPOL_MSK BIT(5) #define RK817_SLPPOL_H BIT(5) +#define RK817_SLPPOL_L (0) /* gpio&int 0xfe */ #define RK817_INT_POL_MSK BIT(1) @@ -944,12 +958,20 @@ enum { BOOST_ILMIN_250MA, }; +struct rk808_pin_info { + struct pinctrl *p; + struct pinctrl_state *reset; + struct pinctrl_state *power_off; + struct pinctrl_state *sleep; +}; + struct rk808 { struct i2c_client *i2c; struct regmap_irq_chip_data *irq_data; struct regmap_irq_chip_data *battery_irq_data; struct regmap *regmap; long variant; + struct rk808_pin_info *pins; }; enum {