mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
pinctrl: support pinctrl driver for the RK817&RK809 PMIC
Change-Id: I9a24ee0d9266a000d582f8ffff8b0c872e3a0769 Signed-off-by: Tony Xie <tony.xie@rock-chips.com> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
This commit is contained in:
@@ -19,6 +19,8 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pinctrl/devinfo.h>
|
||||
|
||||
struct rk808_reg_data {
|
||||
int addr;
|
||||
@@ -478,10 +480,55 @@ static void rk808_pm_power_off(void)
|
||||
dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n");
|
||||
}
|
||||
|
||||
static void rk817_shutdown_prepare(void)
|
||||
{
|
||||
int ret;
|
||||
struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
|
||||
|
||||
/* close rtc int when power off */
|
||||
regmap_update_bits(rk808->regmap,
|
||||
RK817_INT_STS_MSK_REG0,
|
||||
(0x3 << 5), (0x3 << 5));
|
||||
regmap_update_bits(rk808->regmap,
|
||||
RK817_RTC_INT_REG,
|
||||
(0x3 << 2), (0x0 << 2));
|
||||
|
||||
if (rk808->pins && 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");
|
||||
|
||||
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");
|
||||
|
||||
ret = pinctrl_select_state(rk808->pins->p,
|
||||
rk808->pins->power_off);
|
||||
if (ret)
|
||||
pr_info("%s:failed to activate pwroff state\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
/* pmic sleep shutdown function */
|
||||
ret = regmap_update_bits(rk808->regmap,
|
||||
RK817_SYS_CFG(3),
|
||||
RK817_SLPPIN_FUNC_MSK, SLPPIN_DN_FUN);
|
||||
if (ret)
|
||||
dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n");
|
||||
/* pmic need the SCL clock to synchronize register */
|
||||
mdelay(2);
|
||||
}
|
||||
|
||||
static void rk8xx_shutdown(struct i2c_client *client)
|
||||
{
|
||||
struct rk808 *rk808 = i2c_get_clientdata(client);
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
switch (rk808->variant) {
|
||||
case RK805_ID:
|
||||
@@ -492,10 +539,7 @@ static void rk8xx_shutdown(struct i2c_client *client)
|
||||
break;
|
||||
case RK809_ID:
|
||||
case RK817_ID:
|
||||
ret = regmap_update_bits(rk808->regmap,
|
||||
RK817_SYS_CFG(3),
|
||||
RK817_SLPPIN_FUNC_MSK,
|
||||
SLPPIN_DN_FUN);
|
||||
rk817_shutdown_prepare();
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
@@ -505,6 +549,131 @@ static void rk8xx_shutdown(struct i2c_client *client)
|
||||
"Cannot switch to power down function\n");
|
||||
}
|
||||
|
||||
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 rk808 *rk808, 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(rk808->regmap, RK817_POWER_CONFIG,
|
||||
RK817_BUCK3_FB_RES_MSK,
|
||||
RK817_BUCK3_FB_RES_INTER);
|
||||
else
|
||||
regmap_update_bits(rk808->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(rk808->regmap, RK817_SYS_CFG(3), msk, val);
|
||||
|
||||
dev_info(dev, "support pmic reset mode:%d,%d\n", ret, func);
|
||||
}
|
||||
|
||||
static const struct of_device_id rk808_of_match[] = {
|
||||
{ .compatible = "rockchip,rk805" },
|
||||
{ .compatible = "rockchip,rk808" },
|
||||
@@ -528,6 +697,9 @@ static int rk808_probe(struct i2c_client *client,
|
||||
unsigned char pmic_id_msb, pmic_id_lsb;
|
||||
int ret;
|
||||
int i;
|
||||
void (*of_property_prepare_fn)(struct rk808 *rk808,
|
||||
struct device *dev) = NULL;
|
||||
int (*pinctrl_init)(struct device *dev, struct rk808 *rk808) = NULL;
|
||||
|
||||
rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL);
|
||||
if (!rk808)
|
||||
@@ -593,6 +765,8 @@ static int rk808_probe(struct i2c_client *client,
|
||||
nr_pre_init_regs = ARRAY_SIZE(rk817_pre_init_reg);
|
||||
cells = rk817s;
|
||||
nr_cells = ARRAY_SIZE(rk817s);
|
||||
of_property_prepare_fn = rk817_of_property_prepare;
|
||||
pinctrl_init = rk817_pinctrl_init;
|
||||
break;
|
||||
default:
|
||||
dev_err(&client->dev, "Unsupported RK8XX ID %lu\n",
|
||||
@@ -614,6 +788,19 @@ static int rk808_probe(struct i2c_client *client,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (of_property_prepare_fn)
|
||||
of_property_prepare_fn(rk808, &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, -1,
|
||||
rk808->regmap_irq_chip, &rk808->irq_data);
|
||||
@@ -675,6 +862,7 @@ static int __maybe_unused rk8xx_suspend(struct device *dev)
|
||||
{
|
||||
struct rk808 *rk808 = i2c_get_clientdata(to_i2c_client(dev));
|
||||
int ret = 0;
|
||||
int value;
|
||||
|
||||
switch (rk808->variant) {
|
||||
case RK805_ID:
|
||||
@@ -685,30 +873,84 @@ static int __maybe_unused rk8xx_suspend(struct device *dev)
|
||||
break;
|
||||
case RK809_ID:
|
||||
case RK817_ID:
|
||||
ret = regmap_update_bits(rk808->regmap,
|
||||
RK817_SYS_CFG(3),
|
||||
RK817_SLPPIN_FUNC_MSK,
|
||||
SLPPIN_SLP_FUN);
|
||||
if (rk808->pins && 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 ret;
|
||||
}
|
||||
|
||||
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 ret;
|
||||
}
|
||||
|
||||
/* pmic need the SCL clock to synchronize register */
|
||||
regmap_read(rk808->regmap, RK817_SYS_STS, &value);
|
||||
mdelay(2);
|
||||
ret = pinctrl_select_state(rk808->pins->p, rk808->pins->sleep);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to act slp pinctrl state\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (rk808->pins && rk808->pins->p && rk808->pins->sleep) {
|
||||
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 ret;
|
||||
}
|
||||
|
||||
static int __maybe_unused rk8xx_resume(struct device *dev)
|
||||
{
|
||||
struct rk808 *rk808 = i2c_get_clientdata(to_i2c_client(dev));
|
||||
int value;
|
||||
int ret = 0;
|
||||
|
||||
switch (rk808->variant) {
|
||||
case RK809_ID:
|
||||
case RK817_ID:
|
||||
ret = regmap_update_bits(rk808->regmap,
|
||||
RK817_SYS_CFG(3),
|
||||
RK817_SLPPIN_FUNC_MSK,
|
||||
SLPPIN_NULL_FUN);
|
||||
if (rk808->pins && 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 ret;
|
||||
}
|
||||
|
||||
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 ret;
|
||||
}
|
||||
|
||||
/* pmic need the SCL clock to synchronize register */
|
||||
regmap_read(rk808->regmap, RK817_SYS_STS, &value);
|
||||
mdelay(2);
|
||||
ret = pinctrl_select_state(rk808->pins->p, rk808->pins->reset);
|
||||
if (ret)
|
||||
dev_dbg(dev, "failed to act reset pinctrl state\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -132,12 +132,118 @@ static const 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);
|
||||
@@ -154,6 +260,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,
|
||||
@@ -214,6 +323,20 @@ static const 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)
|
||||
{
|
||||
@@ -289,7 +412,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,
|
||||
@@ -306,6 +429,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)
|
||||
@@ -314,7 +458,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,
|
||||
@@ -324,13 +478,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;
|
||||
@@ -390,8 +537,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");
|
||||
@@ -415,9 +567,18 @@ static const 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);
|
||||
@@ -425,18 +586,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;
|
||||
@@ -448,13 +610,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");
|
||||
@@ -485,7 +676,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>");
|
||||
|
||||
@@ -613,6 +613,13 @@ enum {
|
||||
RK818_ID = 0x8180,
|
||||
};
|
||||
|
||||
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;
|
||||
@@ -620,5 +627,6 @@ struct rk808 {
|
||||
long variant;
|
||||
const struct regmap_config *regmap_cfg;
|
||||
const struct regmap_irq_chip *regmap_irq_chip;
|
||||
struct rk808_pin_info *pins;
|
||||
};
|
||||
#endif /* __LINUX_REGULATOR_RK808_H */
|
||||
|
||||
Reference in New Issue
Block a user