Skip to content

Commit 884fdaa

Browse files
jwn0222krzk
authored andcommitted
pinctrl: samsung: support ExynosAuto GPIO structure
New ExynosAuto series GPIO have a different register structure. In the existing Exynos series, EINT control register is enumerated after a specific offset (e.g EXYNOS_GPIO_ECON_OFFSET, EXYNOS_GPIO_EMASK_OFFSET). However, from ExynosAutov920 SoC, the register that controls EINT belongs to each GPIO bank, and each GPIO bank has 0x1000 align. This is a structure to protect the GPIO bank using S2MPU in VM environment, and will only be applied in ExynosAuto series SoCs. -------------------------------------------------------------- | Original Exynos | ExynosAuto | |------------------------------------------------------------| | 0x0 GPIO_CON | 0x0 GPIO_CON | | 0x4 GPIO_DAT | 0x4 GPIO_DAT | | 0x8 GPIO_PUD | 0x8 GPIO_PUD | | 0xc GPIO_DRV | 0xc GPIO_DRV | | 0x10 GPIO_CONPDN | 0x10 GPIO_CONPDN | | 0x14 GPIO_PUDPDN | 0x14 GPIO_PUDPDN | |----------------------------| 0x18 EINT_CON (per_bank) | | ... | 0x1c EINT_FLTCON0 (per_bank) | | ... | 0x20 EINT_FLTCON1 (per_bank) | | ... | 0x24 EINT_MASK (per_bank) | | ... | 0x28 EINT_PEND (per_bank) | |----------------------------|-------------------------------| | 0x700 EINT_CON (global) | ... | | 0x800 EINT_FLTCON (global) | ... | | 0x900 EINT_MASK (global) | ... | | 0xa00 EINT_FEND (global) | ... | -------------------------------------------------------------- Signed-off-by: Jaewon Kim <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Krzysztof Kozlowski <[email protected]>
1 parent 4a8be01 commit 884fdaa

File tree

3 files changed

+79
-8
lines changed

3 files changed

+79
-8
lines changed

drivers/pinctrl/samsung/pinctrl-exynos.c

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,15 @@ static void exynos_irq_mask(struct irq_data *irqd)
5252
struct irq_chip *chip = irq_data_get_irq_chip(irqd);
5353
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
5454
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
55-
unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
55+
unsigned long reg_mask;
5656
unsigned int mask;
5757
unsigned long flags;
5858

59+
if (bank->eint_mask_offset)
60+
reg_mask = bank->pctl_offset + bank->eint_mask_offset;
61+
else
62+
reg_mask = our_chip->eint_mask + bank->eint_offset;
63+
5964
raw_spin_lock_irqsave(&bank->slock, flags);
6065

6166
mask = readl(bank->eint_base + reg_mask);
@@ -70,7 +75,12 @@ static void exynos_irq_ack(struct irq_data *irqd)
7075
struct irq_chip *chip = irq_data_get_irq_chip(irqd);
7176
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
7277
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
73-
unsigned long reg_pend = our_chip->eint_pend + bank->eint_offset;
78+
unsigned long reg_pend;
79+
80+
if (bank->eint_pend_offset)
81+
reg_pend = bank->pctl_offset + bank->eint_pend_offset;
82+
else
83+
reg_pend = our_chip->eint_pend + bank->eint_offset;
7484

7585
writel(1 << irqd->hwirq, bank->eint_base + reg_pend);
7686
}
@@ -80,7 +90,7 @@ static void exynos_irq_unmask(struct irq_data *irqd)
8090
struct irq_chip *chip = irq_data_get_irq_chip(irqd);
8191
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
8292
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
83-
unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
93+
unsigned long reg_mask;
8494
unsigned int mask;
8595
unsigned long flags;
8696

@@ -95,6 +105,11 @@ static void exynos_irq_unmask(struct irq_data *irqd)
95105
if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
96106
exynos_irq_ack(irqd);
97107

108+
if (bank->eint_mask_offset)
109+
reg_mask = bank->pctl_offset + bank->eint_mask_offset;
110+
else
111+
reg_mask = our_chip->eint_mask + bank->eint_offset;
112+
98113
raw_spin_lock_irqsave(&bank->slock, flags);
99114

100115
mask = readl(bank->eint_base + reg_mask);
@@ -111,7 +126,7 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
111126
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
112127
unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq;
113128
unsigned int con, trig_type;
114-
unsigned long reg_con = our_chip->eint_con + bank->eint_offset;
129+
unsigned long reg_con;
115130

116131
switch (type) {
117132
case IRQ_TYPE_EDGE_RISING:
@@ -139,6 +154,11 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
139154
else
140155
irq_set_handler_locked(irqd, handle_level_irq);
141156

157+
if (bank->eint_con_offset)
158+
reg_con = bank->pctl_offset + bank->eint_con_offset;
159+
else
160+
reg_con = our_chip->eint_con + bank->eint_offset;
161+
142162
con = readl(bank->eint_base + reg_con);
143163
con &= ~(EXYNOS_EINT_CON_MASK << shift);
144164
con |= trig_type << shift;
@@ -669,15 +689,32 @@ static void exynos_pinctrl_suspend_bank(
669689
pr_debug("%s: save mask %#010x\n", bank->name, save->eint_mask);
670690
}
671691

692+
static void exynosauto_pinctrl_suspend_bank(struct samsung_pinctrl_drv_data *drvdata,
693+
struct samsung_pin_bank *bank)
694+
{
695+
struct exynos_eint_gpio_save *save = bank->soc_priv;
696+
void __iomem *regs = bank->eint_base;
697+
698+
save->eint_con = readl(regs + bank->pctl_offset + bank->eint_con_offset);
699+
save->eint_mask = readl(regs + bank->pctl_offset + bank->eint_mask_offset);
700+
701+
pr_debug("%s: save con %#010x\n", bank->name, save->eint_con);
702+
pr_debug("%s: save mask %#010x\n", bank->name, save->eint_mask);
703+
}
704+
672705
void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
673706
{
674707
struct samsung_pin_bank *bank = drvdata->pin_banks;
675708
struct exynos_irq_chip *irq_chip = NULL;
676709
int i;
677710

678711
for (i = 0; i < drvdata->nr_banks; ++i, ++bank) {
679-
if (bank->eint_type == EINT_TYPE_GPIO)
680-
exynos_pinctrl_suspend_bank(drvdata, bank);
712+
if (bank->eint_type == EINT_TYPE_GPIO) {
713+
if (bank->eint_con_offset)
714+
exynosauto_pinctrl_suspend_bank(drvdata, bank);
715+
else
716+
exynos_pinctrl_suspend_bank(drvdata, bank);
717+
}
681718
else if (bank->eint_type == EINT_TYPE_WKUP) {
682719
if (!irq_chip) {
683720
irq_chip = bank->irq_chip;
@@ -718,14 +755,33 @@ static void exynos_pinctrl_resume_bank(
718755
+ bank->eint_offset);
719756
}
720757

758+
static void exynosauto_pinctrl_resume_bank(struct samsung_pinctrl_drv_data *drvdata,
759+
struct samsung_pin_bank *bank)
760+
{
761+
struct exynos_eint_gpio_save *save = bank->soc_priv;
762+
void __iomem *regs = bank->eint_base;
763+
764+
pr_debug("%s: con %#010x => %#010x\n", bank->name,
765+
readl(regs + bank->pctl_offset + bank->eint_con_offset), save->eint_con);
766+
pr_debug("%s: mask %#010x => %#010x\n", bank->name,
767+
readl(regs + bank->pctl_offset + bank->eint_mask_offset), save->eint_mask);
768+
769+
writel(save->eint_con, regs + bank->pctl_offset + bank->eint_con_offset);
770+
writel(save->eint_mask, regs + bank->pctl_offset + bank->eint_mask_offset);
771+
}
772+
721773
void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
722774
{
723775
struct samsung_pin_bank *bank = drvdata->pin_banks;
724776
int i;
725777

726778
for (i = 0; i < drvdata->nr_banks; ++i, ++bank)
727-
if (bank->eint_type == EINT_TYPE_GPIO)
728-
exynos_pinctrl_resume_bank(drvdata, bank);
779+
if (bank->eint_type == EINT_TYPE_GPIO) {
780+
if (bank->eint_con_offset)
781+
exynosauto_pinctrl_resume_bank(drvdata, bank);
782+
else
783+
exynos_pinctrl_resume_bank(drvdata, bank);
784+
}
729785
}
730786

731787
static void exynos_retention_enable(struct samsung_pinctrl_drv_data *drvdata)

drivers/pinctrl/samsung/pinctrl-samsung.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,9 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
11061106
bank->eint_type = bdata->eint_type;
11071107
bank->eint_mask = bdata->eint_mask;
11081108
bank->eint_offset = bdata->eint_offset;
1109+
bank->eint_con_offset = bdata->eint_con_offset;
1110+
bank->eint_mask_offset = bdata->eint_mask_offset;
1111+
bank->eint_pend_offset = bdata->eint_pend_offset;
11091112
bank->name = bdata->name;
11101113

11111114
raw_spin_lock_init(&bank->slock);

drivers/pinctrl/samsung/pinctrl-samsung.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ struct samsung_pin_bank_type {
122122
* @eint_type: type of the external interrupt supported by the bank.
123123
* @eint_mask: bit mask of pins which support EINT function.
124124
* @eint_offset: SoC-specific EINT register or interrupt offset of bank.
125+
* @eint_con_offset: ExynosAuto SoC-specific EINT control register offset of bank.
126+
* @eint_mask_offset: ExynosAuto SoC-specific EINT mask register offset of bank.
127+
* @eint_pend_offset: ExynosAuto SoC-specific EINT pend register offset of bank.
125128
* @name: name to be prefixed for each pin in this pin bank.
126129
*/
127130
struct samsung_pin_bank_data {
@@ -133,6 +136,9 @@ struct samsung_pin_bank_data {
133136
enum eint_type eint_type;
134137
u32 eint_mask;
135138
u32 eint_offset;
139+
u32 eint_con_offset;
140+
u32 eint_mask_offset;
141+
u32 eint_pend_offset;
136142
const char *name;
137143
};
138144

@@ -147,6 +153,9 @@ struct samsung_pin_bank_data {
147153
* @eint_type: type of the external interrupt supported by the bank.
148154
* @eint_mask: bit mask of pins which support EINT function.
149155
* @eint_offset: SoC-specific EINT register or interrupt offset of bank.
156+
* @eint_con_offset: ExynosAuto SoC-specific EINT register or interrupt offset of bank.
157+
* @eint_mask_offset: ExynosAuto SoC-specific EINT mask register offset of bank.
158+
* @eint_pend_offset: ExynosAuto SoC-specific EINT pend register offset of bank.
150159
* @name: name to be prefixed for each pin in this pin bank.
151160
* @id: id of the bank, propagated to the pin range.
152161
* @pin_base: starting pin number of the bank.
@@ -170,6 +179,9 @@ struct samsung_pin_bank {
170179
enum eint_type eint_type;
171180
u32 eint_mask;
172181
u32 eint_offset;
182+
u32 eint_con_offset;
183+
u32 eint_mask_offset;
184+
u32 eint_pend_offset;
173185
const char *name;
174186
u32 id;
175187

0 commit comments

Comments
 (0)