pinctrl: support pinctrl driver for the RK817&RK809 PMIC

Change-Id: I9a24ee0d9266a000d582f8ffff8b0c872e3a0769
Signed-off-by: Tony Xie <tony.xie@rock-chips.com>
This commit is contained in:
Tony Xie
2018-02-07 15:05:03 +08:00
committed by Tao Huang
parent 1a69527184
commit ed38d26a33
5 changed files with 652 additions and 122 deletions

View File

@@ -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";
};
}

View File

@@ -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";
};
}

View File

@@ -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;
}

View File

@@ -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 <chenjh@rock-chips.com>");

View File

@@ -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 {