Skip to content

Commit f9c7447

Browse files
andredkrzk
authored andcommitted
pinctrl: samsung: support a bus clock
On some Samsung-based SoCs there are separate bus clocks / gates each for each pinctrl instance. To be able to access each pinctrl instance's registers, this bus clock needs to be running, otherwise register access will hang. Google Tensor gs101 is one example for such an implementation. Update the driver to handle this optional bus clock: * handle an optional bus clock from DT * prepare it during driver probe * enclose all relevant register accesses with a clock enable & disable Signed-off-by: André Draszik <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Krzysztof Kozlowski <[email protected]>
1 parent dff9f3f commit f9c7447

File tree

3 files changed

+207
-4
lines changed

3 files changed

+207
-4
lines changed

drivers/pinctrl/samsung/pinctrl-exynos.c

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// the Samsung pinctrl/gpiolib driver. It also includes the implementation of
1414
// external gpio and wakeup interrupt support.
1515

16+
#include <linux/clk.h>
1617
#include <linux/device.h>
1718
#include <linux/interrupt.h>
1819
#include <linux/irqdomain.h>
@@ -61,13 +62,21 @@ static void exynos_irq_mask(struct irq_data *irqd)
6162
else
6263
reg_mask = our_chip->eint_mask + bank->eint_offset;
6364

65+
if (clk_enable(bank->drvdata->pclk)) {
66+
dev_err(bank->gpio_chip.parent,
67+
"unable to enable clock for masking IRQ\n");
68+
return;
69+
}
70+
6471
raw_spin_lock_irqsave(&bank->slock, flags);
6572

6673
mask = readl(bank->eint_base + reg_mask);
6774
mask |= 1 << irqd->hwirq;
6875
writel(mask, bank->eint_base + reg_mask);
6976

7077
raw_spin_unlock_irqrestore(&bank->slock, flags);
78+
79+
clk_disable(bank->drvdata->pclk);
7180
}
7281

7382
static void exynos_irq_ack(struct irq_data *irqd)
@@ -82,7 +91,15 @@ static void exynos_irq_ack(struct irq_data *irqd)
8291
else
8392
reg_pend = our_chip->eint_pend + bank->eint_offset;
8493

94+
if (clk_enable(bank->drvdata->pclk)) {
95+
dev_err(bank->gpio_chip.parent,
96+
"unable to enable clock to ack IRQ\n");
97+
return;
98+
}
99+
85100
writel(1 << irqd->hwirq, bank->eint_base + reg_pend);
101+
102+
clk_disable(bank->drvdata->pclk);
86103
}
87104

88105
static void exynos_irq_unmask(struct irq_data *irqd)
@@ -110,13 +127,21 @@ static void exynos_irq_unmask(struct irq_data *irqd)
110127
else
111128
reg_mask = our_chip->eint_mask + bank->eint_offset;
112129

130+
if (clk_enable(bank->drvdata->pclk)) {
131+
dev_err(bank->gpio_chip.parent,
132+
"unable to enable clock for unmasking IRQ\n");
133+
return;
134+
}
135+
113136
raw_spin_lock_irqsave(&bank->slock, flags);
114137

115138
mask = readl(bank->eint_base + reg_mask);
116139
mask &= ~(1 << irqd->hwirq);
117140
writel(mask, bank->eint_base + reg_mask);
118141

119142
raw_spin_unlock_irqrestore(&bank->slock, flags);
143+
144+
clk_disable(bank->drvdata->pclk);
120145
}
121146

122147
static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
@@ -127,6 +152,7 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
127152
unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq;
128153
unsigned int con, trig_type;
129154
unsigned long reg_con;
155+
int ret;
130156

131157
switch (type) {
132158
case IRQ_TYPE_EDGE_RISING:
@@ -159,11 +185,20 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
159185
else
160186
reg_con = our_chip->eint_con + bank->eint_offset;
161187

188+
ret = clk_enable(bank->drvdata->pclk);
189+
if (ret) {
190+
dev_err(bank->gpio_chip.parent,
191+
"unable to enable clock for configuring IRQ type\n");
192+
return ret;
193+
}
194+
162195
con = readl(bank->eint_base + reg_con);
163196
con &= ~(EXYNOS_EINT_CON_MASK << shift);
164197
con |= trig_type << shift;
165198
writel(con, bank->eint_base + reg_con);
166199

200+
clk_disable(bank->drvdata->pclk);
201+
167202
return 0;
168203
}
169204

@@ -200,6 +235,14 @@ static int exynos_irq_request_resources(struct irq_data *irqd)
200235
shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC];
201236
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
202237

238+
ret = clk_enable(bank->drvdata->pclk);
239+
if (ret) {
240+
dev_err(bank->gpio_chip.parent,
241+
"unable to enable clock for configuring pin %s-%lu\n",
242+
bank->name, irqd->hwirq);
243+
return ret;
244+
}
245+
203246
raw_spin_lock_irqsave(&bank->slock, flags);
204247

205248
con = readl(bank->pctl_base + reg_con);
@@ -209,6 +252,8 @@ static int exynos_irq_request_resources(struct irq_data *irqd)
209252

210253
raw_spin_unlock_irqrestore(&bank->slock, flags);
211254

255+
clk_disable(bank->drvdata->pclk);
256+
212257
return 0;
213258
}
214259

@@ -223,6 +268,13 @@ static void exynos_irq_release_resources(struct irq_data *irqd)
223268
shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC];
224269
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
225270

271+
if (clk_enable(bank->drvdata->pclk)) {
272+
dev_err(bank->gpio_chip.parent,
273+
"unable to enable clock for deconfiguring pin %s-%lu\n",
274+
bank->name, irqd->hwirq);
275+
return;
276+
}
277+
226278
raw_spin_lock_irqsave(&bank->slock, flags);
227279

228280
con = readl(bank->pctl_base + reg_con);
@@ -232,6 +284,8 @@ static void exynos_irq_release_resources(struct irq_data *irqd)
232284

233285
raw_spin_unlock_irqrestore(&bank->slock, flags);
234286

287+
clk_disable(bank->drvdata->pclk);
288+
235289
gpiochip_unlock_as_irq(&bank->gpio_chip, irqd->hwirq);
236290
}
237291

@@ -281,10 +335,19 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
281335
unsigned int svc, group, pin;
282336
int ret;
283337

338+
if (clk_enable(bank->drvdata->pclk)) {
339+
dev_err(bank->gpio_chip.parent,
340+
"unable to enable clock for handling IRQ\n");
341+
return IRQ_NONE;
342+
}
343+
284344
if (bank->eint_con_offset)
285345
svc = readl(bank->eint_base + EXYNOSAUTO_SVC_OFFSET);
286346
else
287347
svc = readl(bank->eint_base + EXYNOS_SVC_OFFSET);
348+
349+
clk_disable(bank->drvdata->pclk);
350+
288351
group = EXYNOS_SVC_GROUP(svc);
289352
pin = svc & EXYNOS_SVC_NUM_MASK;
290353

@@ -563,6 +626,20 @@ static void exynos_irq_demux_eint16_31(struct irq_desc *desc)
563626

564627
chained_irq_enter(chip, desc);
565628

629+
/*
630+
* just enable the clock once here, to avoid an enable/disable dance for
631+
* each bank.
632+
*/
633+
if (eintd->nr_banks) {
634+
struct samsung_pin_bank *b = eintd->banks[0];
635+
636+
if (clk_enable(b->drvdata->pclk)) {
637+
dev_err(b->gpio_chip.parent,
638+
"unable to enable clock for pending IRQs\n");
639+
return;
640+
}
641+
}
642+
566643
for (i = 0; i < eintd->nr_banks; ++i) {
567644
struct samsung_pin_bank *b = eintd->banks[i];
568645
pend = readl(b->eint_base + b->irq_chip->eint_pend
@@ -572,6 +649,9 @@ static void exynos_irq_demux_eint16_31(struct irq_desc *desc)
572649
exynos_irq_demux_eint(pend & ~mask, b->irq_domain);
573650
}
574651

652+
if (eintd->nr_banks)
653+
clk_disable(eintd->banks[0]->drvdata->pclk);
654+
575655
chained_irq_exit(chip, desc);
576656
}
577657

@@ -695,6 +775,12 @@ static void exynos_pinctrl_suspend_bank(
695775
struct exynos_eint_gpio_save *save = bank->soc_priv;
696776
const void __iomem *regs = bank->eint_base;
697777

778+
if (clk_enable(bank->drvdata->pclk)) {
779+
dev_err(bank->gpio_chip.parent,
780+
"unable to enable clock for saving state\n");
781+
return;
782+
}
783+
698784
save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
699785
+ bank->eint_offset);
700786
save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
@@ -704,6 +790,8 @@ static void exynos_pinctrl_suspend_bank(
704790
save->eint_mask = readl(regs + bank->irq_chip->eint_mask
705791
+ bank->eint_offset);
706792

793+
clk_disable(bank->drvdata->pclk);
794+
707795
pr_debug("%s: save con %#010x\n", bank->name, save->eint_con);
708796
pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0);
709797
pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1);
@@ -716,9 +804,17 @@ static void exynosauto_pinctrl_suspend_bank(struct samsung_pinctrl_drv_data *drv
716804
struct exynos_eint_gpio_save *save = bank->soc_priv;
717805
const void __iomem *regs = bank->eint_base;
718806

807+
if (clk_enable(bank->drvdata->pclk)) {
808+
dev_err(bank->gpio_chip.parent,
809+
"unable to enable clock for saving state\n");
810+
return;
811+
}
812+
719813
save->eint_con = readl(regs + bank->pctl_offset + bank->eint_con_offset);
720814
save->eint_mask = readl(regs + bank->pctl_offset + bank->eint_mask_offset);
721815

816+
clk_disable(bank->drvdata->pclk);
817+
722818
pr_debug("%s: save con %#010x\n", bank->name, save->eint_con);
723819
pr_debug("%s: save mask %#010x\n", bank->name, save->eint_mask);
724820
}
@@ -753,6 +849,12 @@ static void exynos_pinctrl_resume_bank(
753849
struct exynos_eint_gpio_save *save = bank->soc_priv;
754850
void __iomem *regs = bank->eint_base;
755851

852+
if (clk_enable(bank->drvdata->pclk)) {
853+
dev_err(bank->gpio_chip.parent,
854+
"unable to enable clock for restoring state\n");
855+
return;
856+
}
857+
756858
pr_debug("%s: con %#010x => %#010x\n", bank->name,
757859
readl(regs + EXYNOS_GPIO_ECON_OFFSET
758860
+ bank->eint_offset), save->eint_con);
@@ -774,6 +876,8 @@ static void exynos_pinctrl_resume_bank(
774876
+ 2 * bank->eint_offset + 4);
775877
writel(save->eint_mask, regs + bank->irq_chip->eint_mask
776878
+ bank->eint_offset);
879+
880+
clk_disable(bank->drvdata->pclk);
777881
}
778882

779883
static void exynosauto_pinctrl_resume_bank(struct samsung_pinctrl_drv_data *drvdata,
@@ -782,13 +886,21 @@ static void exynosauto_pinctrl_resume_bank(struct samsung_pinctrl_drv_data *drvd
782886
struct exynos_eint_gpio_save *save = bank->soc_priv;
783887
void __iomem *regs = bank->eint_base;
784888

889+
if (clk_enable(bank->drvdata->pclk)) {
890+
dev_err(bank->gpio_chip.parent,
891+
"unable to enable clock for restoring state\n");
892+
return;
893+
}
894+
785895
pr_debug("%s: con %#010x => %#010x\n", bank->name,
786896
readl(regs + bank->pctl_offset + bank->eint_con_offset), save->eint_con);
787897
pr_debug("%s: mask %#010x => %#010x\n", bank->name,
788898
readl(regs + bank->pctl_offset + bank->eint_mask_offset), save->eint_mask);
789899

790900
writel(save->eint_con, regs + bank->pctl_offset + bank->eint_con_offset);
791901
writel(save->eint_mask, regs + bank->pctl_offset + bank->eint_mask_offset);
902+
903+
clk_disable(bank->drvdata->pclk);
792904
}
793905

794906
void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)

0 commit comments

Comments
 (0)