summaryrefslogtreecommitdiff
path: root/drivers/pinctrl/pinctrl-rockchip.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-09-04 20:22:09 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-04 20:22:09 +0300
commit88a99886c26fec8bf662e7b6bc080431a8660326 (patch)
tree615b9a9a959ab093f6d8d0dd94d3bbc5299fc4c6 /drivers/pinctrl/pinctrl-rockchip.c
parent8d2faea672606827c2018143ec7d88c760f2d6de (diff)
parent1ab36387ea4face01aac3560b396b1e2ce07c4ff (diff)
downloadlinux-88a99886c26fec8bf662e7b6bc080431a8660326.tar.xz
Merge tag 'pinctrl-v4.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl
Pull pin control updates from Linus Walleij: "This is the bulk of pin control changes for the v4.3 development cycle. Like with GPIO it's a lot of stuff. If my subsystems are any sign of the overall tempo of the kernel v4.3 will be a gigantic diff. [ It looks like 4.3 is calmer than 4.2 in most other subsystems, but we'll see - Linus ] Core changes: - It is possible configure groups in debugfs. - Consolidation of chained IRQ handler install/remove replacing all call sites where irq_set_handler_data() and irq_set_chained_handler() were done in succession with a combined call to irq_set_chained_handler_and_data(). This series was created by Thomas Gleixner after the problem was observed by Russell King. - Tglx also made another series of patches switching __irq_set_handler_locked() for irq_set_handler_locked() which is way cleaner. - Tglx also wrote a good bunch of patches to make use of irq_desc_get_xxx() accessors and avoid looking up irq_descs from IRQ numbers. The goal is to get rid of the irq number from the handlers in the IRQ flow which is nice. Driver feature enhancements: - Power management support for the SiRF SoC Atlas 7. - Power down support for the Qualcomm driver. - Intel Cherryview and Baytrail: switch drivers to use raw spinlocks in IRQ handlers to play nice with the realtime patch set. - Rework and new modes handling for Qualcomm SPMI-MPP. - Pinconf power source config for SH PFC. New drivers and subdrivers: - A new driver for Conexant Digicolor CX92755. - A new driver for UniPhier PH1-LD4, PH1-Pro4, PH1-sLD8, PH1-Pro5, ProXtream2 and PH1-LD6b SoC pin control support. - Reverse-egineered the S/PDIF settings for the Allwinner sun4i driver. - Support for Qualcomm Technologies QDF2xxx ARM64 SoCs - A new Freescale i.mx6ul subdriver. Cleanup: - Remove platform data support in a number of SH PFC subdrivers" * tag 'pinctrl-v4.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (95 commits) pinctrl: at91: fix null pointer dereference pinctrl: mediatek: Implement wake handler and suspend resume pinctrl: mediatek: Fix multiple registration issue. pinctrl: sh-pfc: r8a7794: add USB pin groups pinctrl: at91: Use generic irq_{request,release}_resources() pinctrl: cherryview: Use raw_spinlock for locking pinctrl: baytrail: Use raw_spinlock for locking pinctrl: imx6ul: Remove .owner field pinctrl: zynq: Fix typos in smc0_nand_grp and smc0_nor_grp pinctrl: sh-pfc: Implement pinconf power-source param for voltage switching clk: rockchip: add pclk_pd_pmu to the list of rk3288 critical clocks pinctrl: sun4i: add spdif to pin description. pinctrl: atlas7: clear ugly branch statements for pull and drivestrength pinctrl: baytrail: Serialize all register access pinctrl: baytrail: Drop FSF mailing address pinctrl: rockchip: only enable gpio clock when it setting pinctrl/mediatek: fix spelling mistake in dev_err error message pinctrl: cherryview: Serialize all register access pinctrl: UniPhier: PH1-Pro5: add I2C ch6 pin-mux setting pinctrl: nomadik: reflect current input value ...
Diffstat (limited to 'drivers/pinctrl/pinctrl-rockchip.c')
-rw-r--r--drivers/pinctrl/pinctrl-rockchip.c71
1 files changed, 59 insertions, 12 deletions
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 9affcd725776..c5246c05f70c 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -945,6 +945,7 @@ static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip,
if (ret < 0)
return ret;
+ clk_enable(bank->clk);
spin_lock_irqsave(&bank->slock, flags);
data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
@@ -956,6 +957,7 @@ static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip,
writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
spin_unlock_irqrestore(&bank->slock, flags);
+ clk_disable(bank->clk);
return 0;
}
@@ -1389,6 +1391,7 @@ static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
unsigned long flags;
u32 data;
+ clk_enable(bank->clk);
spin_lock_irqsave(&bank->slock, flags);
data = readl(reg);
@@ -1398,6 +1401,7 @@ static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
writel(data, reg);
spin_unlock_irqrestore(&bank->slock, flags);
+ clk_disable(bank->clk);
}
/*
@@ -1409,7 +1413,9 @@ static int rockchip_gpio_get(struct gpio_chip *gc, unsigned offset)
struct rockchip_pin_bank *bank = gc_to_pin_bank(gc);
u32 data;
+ clk_enable(bank->clk);
data = readl(bank->reg_base + GPIO_EXT_PORT);
+ clk_disable(bank->clk);
data >>= offset;
data &= 1;
return data;
@@ -1469,10 +1475,10 @@ static const struct gpio_chip rockchip_gpiolib_chip = {
* Interrupt handling
*/
-static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
+static void rockchip_irq_demux(unsigned int __irq, struct irq_desc *desc)
{
- struct irq_chip *chip = irq_get_chip(irq);
- struct rockchip_pin_bank *bank = irq_get_handler_data(irq);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct rockchip_pin_bank *bank = irq_desc_get_handler_data(desc);
u32 pend;
dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name);
@@ -1482,7 +1488,7 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS);
while (pend) {
- unsigned int virq;
+ unsigned int irq, virq;
irq = __ffs(pend);
pend &= ~BIT(irq);
@@ -1546,6 +1552,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
if (ret < 0)
return ret;
+ clk_enable(bank->clk);
spin_lock_irqsave(&bank->slock, flags);
data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
@@ -1555,9 +1562,9 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
spin_unlock_irqrestore(&bank->slock, flags);
if (type & IRQ_TYPE_EDGE_BOTH)
- __irq_set_handler_locked(d->irq, handle_edge_irq);
+ irq_set_handler_locked(d, handle_edge_irq);
else
- __irq_set_handler_locked(d->irq, handle_level_irq);
+ irq_set_handler_locked(d, handle_level_irq);
spin_lock_irqsave(&bank->slock, flags);
irq_gc_lock(gc);
@@ -1603,6 +1610,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
default:
irq_gc_unlock(gc);
spin_unlock_irqrestore(&bank->slock, flags);
+ clk_disable(bank->clk);
return -EINVAL;
}
@@ -1611,6 +1619,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
irq_gc_unlock(gc);
spin_unlock_irqrestore(&bank->slock, flags);
+ clk_disable(bank->clk);
return 0;
}
@@ -1620,8 +1629,10 @@ static void rockchip_irq_suspend(struct irq_data *d)
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct rockchip_pin_bank *bank = gc->private;
+ clk_enable(bank->clk);
bank->saved_masks = irq_reg_readl(gc, GPIO_INTMASK);
irq_reg_writel(gc, ~gc->wake_active, GPIO_INTMASK);
+ clk_disable(bank->clk);
}
static void rockchip_irq_resume(struct irq_data *d)
@@ -1629,7 +1640,27 @@ static void rockchip_irq_resume(struct irq_data *d)
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct rockchip_pin_bank *bank = gc->private;
+ clk_enable(bank->clk);
irq_reg_writel(gc, bank->saved_masks, GPIO_INTMASK);
+ clk_disable(bank->clk);
+}
+
+static void rockchip_irq_gc_mask_clr_bit(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct rockchip_pin_bank *bank = gc->private;
+
+ clk_enable(bank->clk);
+ irq_gc_mask_clr_bit(d);
+}
+
+void rockchip_irq_gc_mask_set_bit(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct rockchip_pin_bank *bank = gc->private;
+
+ irq_gc_mask_set_bit(d);
+ clk_disable(bank->clk);
}
static int rockchip_interrupts_register(struct platform_device *pdev,
@@ -1640,7 +1671,7 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
struct irq_chip_generic *gc;
int ret;
- int i;
+ int i, j;
for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
if (!bank->valid) {
@@ -1649,11 +1680,19 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
continue;
}
+ ret = clk_enable(bank->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to enable clock for bank %s\n",
+ bank->name);
+ continue;
+ }
+
bank->domain = irq_domain_add_linear(bank->of_node, 32,
&irq_generic_chip_ops, NULL);
if (!bank->domain) {
dev_warn(&pdev->dev, "could not initialize irq domain for bank %s\n",
bank->name);
+ clk_disable(bank->clk);
continue;
}
@@ -1664,6 +1703,7 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
dev_err(&pdev->dev, "could not alloc generic chips for bank %s\n",
bank->name);
irq_domain_remove(bank->domain);
+ clk_disable(bank->clk);
continue;
}
@@ -1681,16 +1721,23 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
gc->chip_types[0].regs.mask = GPIO_INTMASK;
gc->chip_types[0].regs.ack = GPIO_PORTS_EOI;
gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
- gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit;
- gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit;
+ gc->chip_types[0].chip.irq_mask = rockchip_irq_gc_mask_set_bit;
+ gc->chip_types[0].chip.irq_unmask =
+ rockchip_irq_gc_mask_clr_bit;
gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake;
gc->chip_types[0].chip.irq_suspend = rockchip_irq_suspend;
gc->chip_types[0].chip.irq_resume = rockchip_irq_resume;
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_chained_handler(bank->irq, rockchip_irq_demux);
+ irq_set_chained_handler_and_data(bank->irq,
+ rockchip_irq_demux, bank);
+
+ /* map the gpio irqs here, when the clock is still running */
+ for (j = 0 ; j < 32 ; j++)
+ irq_create_mapping(bank->domain, j);
+
+ clk_disable(bank->clk);
}
return 0;
@@ -1808,7 +1855,7 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank,
if (IS_ERR(bank->clk))
return PTR_ERR(bank->clk);
- return clk_prepare_enable(bank->clk);
+ return clk_prepare(bank->clk);
}
static const struct of_device_id rockchip_pinctrl_dt_match[];