Rockchip-pinctrl fixes from Doug Anderson and suspend-specific
functions from Chris Zhong -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABCAAGBQJUVpbfAAoJEPOmecmc0R2Bl14H/Rwmpp+KUPcudzSMpnfcqSKt s8B/EVa7I/eURz+5ZFg6kbkTYsT0N/81vGG3MbLT6609iHsxkfClYHkX2JQNBqIn mDYKCpbKPWxS0OrAhYPqG5ywiKEYWZb95DRRoXX7TKh7SFC+5nb/MC9gYtd0kKx4 4fibILzOteN7Besvu+Ma8JkPJZR6/sebFkGj51Rpucff91qkiicy4nSEdCwSq2F5 8neEX95FQlmf1rSPcdt2GY4hEvPAJBe9R2EPIaPy77p0uy3POmgMJNyK7d2b2dxU mV/AP2Pc71OPIfmKYP9LlWPP3AWS1thA8kFEEUjDJvaSVX5qbJggmptVFWQ884o= =/WZL -----END PGP SIGNATURE----- Merge tag 'v3.19-rockchip-pinctrl1' of git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip into devel Rockchip-pinctrl fixes from Doug Anderson and suspend-specific functions from Chris Zhong
This commit is contained in:
commit
13d6a11af6
drivers/pinctrl
|
@ -856,27 +856,22 @@ static int rockchip_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
|
||||||
* leads to this function call (via the pinctrl_gpio_direction_{input|output}()
|
* leads to this function call (via the pinctrl_gpio_direction_{input|output}()
|
||||||
* function called from the gpiolib interface).
|
* function called from the gpiolib interface).
|
||||||
*/
|
*/
|
||||||
static int rockchip_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
|
static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip,
|
||||||
struct pinctrl_gpio_range *range,
|
int pin, bool input)
|
||||||
unsigned offset, bool input)
|
|
||||||
{
|
{
|
||||||
struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
|
|
||||||
struct rockchip_pin_bank *bank;
|
struct rockchip_pin_bank *bank;
|
||||||
struct gpio_chip *chip;
|
int ret;
|
||||||
int pin, ret;
|
unsigned long flags;
|
||||||
u32 data;
|
u32 data;
|
||||||
|
|
||||||
chip = range->gc;
|
|
||||||
bank = gc_to_pin_bank(chip);
|
bank = gc_to_pin_bank(chip);
|
||||||
pin = offset - chip->base;
|
|
||||||
|
|
||||||
dev_dbg(info->dev, "gpio_direction for pin %u as %s-%d to %s\n",
|
|
||||||
offset, range->name, pin, input ? "input" : "output");
|
|
||||||
|
|
||||||
ret = rockchip_set_mux(bank, pin, RK_FUNC_GPIO);
|
ret = rockchip_set_mux(bank, pin, RK_FUNC_GPIO);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&bank->slock, flags);
|
||||||
|
|
||||||
data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
|
data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
|
||||||
/* set bit to 1 for output, 0 for input */
|
/* set bit to 1 for output, 0 for input */
|
||||||
if (!input)
|
if (!input)
|
||||||
|
@ -885,9 +880,28 @@ static int rockchip_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||||
data &= ~BIT(pin);
|
data &= ~BIT(pin);
|
||||||
writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
|
writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&bank->slock, flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rockchip_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||||
|
struct pinctrl_gpio_range *range,
|
||||||
|
unsigned offset, bool input)
|
||||||
|
{
|
||||||
|
struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
|
||||||
|
struct gpio_chip *chip;
|
||||||
|
int pin;
|
||||||
|
|
||||||
|
chip = range->gc;
|
||||||
|
pin = offset - chip->base;
|
||||||
|
dev_dbg(info->dev, "gpio_direction for pin %u as %s-%d to %s\n",
|
||||||
|
offset, range->name, pin, input ? "input" : "output");
|
||||||
|
|
||||||
|
return _rockchip_pmx_gpio_set_direction(chip, offset - chip->base,
|
||||||
|
input);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct pinmux_ops rockchip_pmx_ops = {
|
static const struct pinmux_ops rockchip_pmx_ops = {
|
||||||
.get_functions_count = rockchip_pmx_get_funcs_count,
|
.get_functions_count = rockchip_pmx_get_funcs_count,
|
||||||
.get_function_name = rockchip_pmx_get_func_name,
|
.get_function_name = rockchip_pmx_get_func_name,
|
||||||
|
@ -917,8 +931,7 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rockchip_gpio_direction_output(struct gpio_chip *gc,
|
static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value);
|
||||||
unsigned offset, int value);
|
|
||||||
static int rockchip_gpio_get(struct gpio_chip *gc, unsigned offset);
|
static int rockchip_gpio_get(struct gpio_chip *gc, unsigned offset);
|
||||||
|
|
||||||
/* set the pin config settings for a specified pin */
|
/* set the pin config settings for a specified pin */
|
||||||
|
@ -959,9 +972,10 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||||
return rc;
|
return rc;
|
||||||
break;
|
break;
|
||||||
case PIN_CONFIG_OUTPUT:
|
case PIN_CONFIG_OUTPUT:
|
||||||
rc = rockchip_gpio_direction_output(&bank->gpio_chip,
|
rockchip_gpio_set(&bank->gpio_chip,
|
||||||
pin - bank->pin_base,
|
pin - bank->pin_base, arg);
|
||||||
arg);
|
rc = _rockchip_pmx_gpio_set_direction(&bank->gpio_chip,
|
||||||
|
pin - bank->pin_base, false);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
break;
|
break;
|
||||||
|
@ -1253,6 +1267,10 @@ static int rockchip_pinctrl_register(struct platform_device *pdev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = rockchip_pinctrl_parse_dt(pdev, info);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
info->pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, info);
|
info->pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, info);
|
||||||
if (!info->pctl_dev) {
|
if (!info->pctl_dev) {
|
||||||
dev_err(&pdev->dev, "could not register pinctrl driver\n");
|
dev_err(&pdev->dev, "could not register pinctrl driver\n");
|
||||||
|
@ -1270,12 +1288,6 @@ static int rockchip_pinctrl_register(struct platform_device *pdev,
|
||||||
pinctrl_add_gpio_range(info->pctl_dev, &pin_bank->grange);
|
pinctrl_add_gpio_range(info->pctl_dev, &pin_bank->grange);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = rockchip_pinctrl_parse_dt(pdev, info);
|
|
||||||
if (ret) {
|
|
||||||
pinctrl_unregister(info->pctl_dev);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1387,6 +1399,7 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
|
||||||
u32 polarity = 0, data = 0;
|
u32 polarity = 0, data = 0;
|
||||||
u32 pend;
|
u32 pend;
|
||||||
bool edge_changed = false;
|
bool edge_changed = false;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name);
|
dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name);
|
||||||
|
|
||||||
|
@ -1432,10 +1445,14 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
|
||||||
|
|
||||||
if (bank->toggle_edge_mode && edge_changed) {
|
if (bank->toggle_edge_mode && edge_changed) {
|
||||||
/* Interrupt params should only be set with ints disabled */
|
/* Interrupt params should only be set with ints disabled */
|
||||||
|
spin_lock_irqsave(&bank->slock, flags);
|
||||||
|
|
||||||
data = readl_relaxed(bank->reg_base + GPIO_INTEN);
|
data = readl_relaxed(bank->reg_base + GPIO_INTEN);
|
||||||
writel_relaxed(0, bank->reg_base + GPIO_INTEN);
|
writel_relaxed(0, bank->reg_base + GPIO_INTEN);
|
||||||
writel(polarity, bank->reg_base + GPIO_INT_POLARITY);
|
writel(polarity, bank->reg_base + GPIO_INT_POLARITY);
|
||||||
writel(data, bank->reg_base + GPIO_INTEN);
|
writel(data, bank->reg_base + GPIO_INTEN);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&bank->slock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
chained_irq_exit(chip, desc);
|
chained_irq_exit(chip, desc);
|
||||||
|
@ -1449,6 +1466,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
|
||||||
u32 polarity;
|
u32 polarity;
|
||||||
u32 level;
|
u32 level;
|
||||||
u32 data;
|
u32 data;
|
||||||
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* make sure the pin is configured as gpio input */
|
/* make sure the pin is configured as gpio input */
|
||||||
|
@ -1456,15 +1474,20 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&bank->slock, flags);
|
||||||
|
|
||||||
data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
|
data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
|
||||||
data &= ~mask;
|
data &= ~mask;
|
||||||
writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
|
writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&bank->slock, flags);
|
||||||
|
|
||||||
if (type & IRQ_TYPE_EDGE_BOTH)
|
if (type & IRQ_TYPE_EDGE_BOTH)
|
||||||
__irq_set_handler_locked(d->irq, handle_edge_irq);
|
__irq_set_handler_locked(d->irq, handle_edge_irq);
|
||||||
else
|
else
|
||||||
__irq_set_handler_locked(d->irq, handle_level_irq);
|
__irq_set_handler_locked(d->irq, handle_level_irq);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&bank->slock, flags);
|
||||||
irq_gc_lock(gc);
|
irq_gc_lock(gc);
|
||||||
|
|
||||||
level = readl_relaxed(gc->reg_base + GPIO_INTTYPE_LEVEL);
|
level = readl_relaxed(gc->reg_base + GPIO_INTTYPE_LEVEL);
|
||||||
|
@ -1507,6 +1530,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
irq_gc_unlock(gc);
|
irq_gc_unlock(gc);
|
||||||
|
spin_unlock_irqrestore(&bank->slock, flags);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1514,6 +1538,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
|
||||||
writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY);
|
writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY);
|
||||||
|
|
||||||
irq_gc_unlock(gc);
|
irq_gc_unlock(gc);
|
||||||
|
spin_unlock_irqrestore(&bank->slock, flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1563,6 +1588,7 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
|
||||||
gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
|
gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
|
||||||
gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake;
|
gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake;
|
||||||
gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type;
|
gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type;
|
||||||
|
gc->wake_enabled = IRQ_MSK(bank->nr_pins);
|
||||||
|
|
||||||
irq_set_handler_data(bank->irq, bank);
|
irq_set_handler_data(bank->irq, bank);
|
||||||
irq_set_chained_handler(bank->irq, rockchip_irq_demux);
|
irq_set_chained_handler(bank->irq, rockchip_irq_demux);
|
||||||
|
@ -1770,6 +1796,51 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
|
||||||
return ctrl;
|
return ctrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define RK3288_GRF_GPIO6C_IOMUX 0x64
|
||||||
|
#define GPIO6C6_SEL_WRITE_ENABLE BIT(28)
|
||||||
|
|
||||||
|
static u32 rk3288_grf_gpio6c_iomux;
|
||||||
|
|
||||||
|
static int __maybe_unused rockchip_pinctrl_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct rockchip_pinctrl *info = dev_get_drvdata(dev);
|
||||||
|
int ret = pinctrl_force_sleep(info->pctl_dev);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RK3288 GPIO6_C6 mux would be modified by Maskrom when resume, so save
|
||||||
|
* the setting here, and restore it at resume.
|
||||||
|
*/
|
||||||
|
if (info->ctrl->type == RK3288) {
|
||||||
|
ret = regmap_read(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX,
|
||||||
|
&rk3288_grf_gpio6c_iomux);
|
||||||
|
if (ret) {
|
||||||
|
pinctrl_force_default(info->pctl_dev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __maybe_unused rockchip_pinctrl_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct rockchip_pinctrl *info = dev_get_drvdata(dev);
|
||||||
|
int ret = regmap_write(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX,
|
||||||
|
rk3288_grf_gpio6c_iomux |
|
||||||
|
GPIO6C6_SEL_WRITE_ENABLE);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return pinctrl_force_default(info->pctl_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SIMPLE_DEV_PM_OPS(rockchip_pinctrl_dev_pm_ops, rockchip_pinctrl_suspend,
|
||||||
|
rockchip_pinctrl_resume);
|
||||||
|
|
||||||
static int rockchip_pinctrl_probe(struct platform_device *pdev)
|
static int rockchip_pinctrl_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct rockchip_pinctrl *info;
|
struct rockchip_pinctrl *info;
|
||||||
|
@ -1983,6 +2054,7 @@ static struct platform_driver rockchip_pinctrl_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "rockchip-pinctrl",
|
.name = "rockchip-pinctrl",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
.pm = &rockchip_pinctrl_dev_pm_ops,
|
||||||
.of_match_table = rockchip_pinctrl_dt_match,
|
.of_match_table = rockchip_pinctrl_dt_match,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue