Commit 915fdc94 authored by Linus Walleij's avatar Linus Walleij

Merge tag 'samsung-pinctrl-6.8' of...

Merge tag 'samsung-pinctrl-6.8' of https://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/samsung into devel

Samsung pinctrl drivers changes for v6.8

1. New hardware: Add pin controllers for Samsung ExynosAutov920 and
   Google Tensor GS101.

2. Few DT bindings cleanups: add specific compatibles for each device
   using generic compatible as fallback.  This affects only DTS, no
   driver changes are needed.

3. Allow setting affinity on non wake-up external GPIO interrupts.
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parents 84e769e6 6cf96df7
......@@ -28,15 +28,27 @@ description: |
properties:
compatible:
enum:
- samsung,s3c2410-wakeup-eint
- samsung,s3c2412-wakeup-eint
- samsung,s3c64xx-wakeup-eint
- samsung,s5pv210-wakeup-eint
- samsung,exynos4210-wakeup-eint
- samsung,exynos7-wakeup-eint
- samsung,exynos850-wakeup-eint
- samsung,exynosautov9-wakeup-eint
oneOf:
- enum:
- samsung,s3c2410-wakeup-eint
- samsung,s3c2412-wakeup-eint
- samsung,s3c64xx-wakeup-eint
- samsung,s5pv210-wakeup-eint
- samsung,exynos4210-wakeup-eint
- samsung,exynos7-wakeup-eint
- samsung,exynosautov920-wakeup-eint
- items:
- enum:
- samsung,exynos5433-wakeup-eint
- samsung,exynos7885-wakeup-eint
- samsung,exynos850-wakeup-eint
- const: samsung,exynos7-wakeup-eint
- items:
- enum:
- google,gs101-wakeup-eint
- samsung,exynosautov9-wakeup-eint
- const: samsung,exynos850-wakeup-eint
- const: samsung,exynos7-wakeup-eint
interrupts:
description:
......@@ -79,11 +91,14 @@ allOf:
- if:
properties:
compatible:
contains:
enum:
- samsung,s5pv210-wakeup-eint
- samsung,exynos4210-wakeup-eint
- samsung,exynos7-wakeup-eint
# Match without "contains", to skip newer variants which are still
# compatible with samsung,exynos7-wakeup-eint
enum:
- samsung,s5pv210-wakeup-eint
- samsung,exynos4210-wakeup-eint
- samsung,exynos5433-wakeup-eint
- samsung,exynos7-wakeup-eint
- samsung,exynos7885-wakeup-eint
then:
properties:
interrupts:
......@@ -98,7 +113,7 @@ allOf:
contains:
enum:
- samsung,exynos850-wakeup-eint
- samsung,exynosautov9-wakeup-eint
- samsung,exynosautov920-wakeup-eint
then:
properties:
interrupts: false
......
......@@ -35,6 +35,7 @@ properties:
compatible:
enum:
- google,gs101-pinctrl
- samsung,s3c2412-pinctrl
- samsung,s3c2416-pinctrl
- samsung,s3c2440-pinctrl
......@@ -53,6 +54,7 @@ properties:
- samsung,exynos7885-pinctrl
- samsung,exynos850-pinctrl
- samsung,exynosautov9-pinctrl
- samsung,exynosautov920-pinctrl
- tesla,fsd-pinctrl
interrupts:
......@@ -313,7 +315,8 @@ examples:
pinctrl-0 = <&initial_alive>;
wakeup-interrupt-controller {
compatible = "samsung,exynos7-wakeup-eint";
compatible = "samsung,exynos5433-wakeup-eint",
"samsung,exynos7-wakeup-eint";
interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
};
......
......@@ -19227,7 +19227,6 @@ R: Alim Akhtar <alim.akhtar@samsung.com>
L: linux-samsung-soc@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/snawrocki/clk.git
F: Documentation/devicetree/bindings/clock/samsung,*.yaml
F: Documentation/devicetree/bindings/clock/samsung,s3c*
F: drivers/clk/samsung/
......
......@@ -52,10 +52,15 @@ static void exynos_irq_mask(struct irq_data *irqd)
struct irq_chip *chip = irq_data_get_irq_chip(irqd);
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
unsigned long reg_mask;
unsigned int mask;
unsigned long flags;
if (bank->eint_mask_offset)
reg_mask = bank->pctl_offset + bank->eint_mask_offset;
else
reg_mask = our_chip->eint_mask + bank->eint_offset;
raw_spin_lock_irqsave(&bank->slock, flags);
mask = readl(bank->eint_base + reg_mask);
......@@ -70,7 +75,12 @@ static void exynos_irq_ack(struct irq_data *irqd)
struct irq_chip *chip = irq_data_get_irq_chip(irqd);
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
unsigned long reg_pend = our_chip->eint_pend + bank->eint_offset;
unsigned long reg_pend;
if (bank->eint_pend_offset)
reg_pend = bank->pctl_offset + bank->eint_pend_offset;
else
reg_pend = our_chip->eint_pend + bank->eint_offset;
writel(1 << irqd->hwirq, bank->eint_base + reg_pend);
}
......@@ -80,7 +90,7 @@ static void exynos_irq_unmask(struct irq_data *irqd)
struct irq_chip *chip = irq_data_get_irq_chip(irqd);
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
unsigned long reg_mask;
unsigned int mask;
unsigned long flags;
......@@ -95,6 +105,11 @@ static void exynos_irq_unmask(struct irq_data *irqd)
if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
exynos_irq_ack(irqd);
if (bank->eint_mask_offset)
reg_mask = bank->pctl_offset + bank->eint_mask_offset;
else
reg_mask = our_chip->eint_mask + bank->eint_offset;
raw_spin_lock_irqsave(&bank->slock, flags);
mask = readl(bank->eint_base + reg_mask);
......@@ -111,7 +126,7 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq;
unsigned int con, trig_type;
unsigned long reg_con = our_chip->eint_con + bank->eint_offset;
unsigned long reg_con;
switch (type) {
case IRQ_TYPE_EDGE_RISING:
......@@ -139,6 +154,11 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
else
irq_set_handler_locked(irqd, handle_level_irq);
if (bank->eint_con_offset)
reg_con = bank->pctl_offset + bank->eint_con_offset;
else
reg_con = our_chip->eint_con + bank->eint_offset;
con = readl(bank->eint_base + reg_con);
con &= ~(EXYNOS_EINT_CON_MASK << shift);
con |= trig_type << shift;
......@@ -147,6 +167,19 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
return 0;
}
static int exynos_irq_set_affinity(struct irq_data *irqd,
const struct cpumask *dest, bool force)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
struct irq_data *parent = irq_get_irq_data(d->irq);
if (parent)
return parent->chip->irq_set_affinity(parent, dest, force);
return -EINVAL;
}
static int exynos_irq_request_resources(struct irq_data *irqd)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
......@@ -212,6 +245,7 @@ static const struct exynos_irq_chip exynos_gpio_irq_chip __initconst = {
.irq_mask = exynos_irq_mask,
.irq_ack = exynos_irq_ack,
.irq_set_type = exynos_irq_set_type,
.irq_set_affinity = exynos_irq_set_affinity,
.irq_request_resources = exynos_irq_request_resources,
.irq_release_resources = exynos_irq_release_resources,
},
......@@ -247,7 +281,10 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
unsigned int svc, group, pin;
int ret;
svc = readl(bank->eint_base + EXYNOS_SVC_OFFSET);
if (bank->eint_con_offset)
svc = readl(bank->eint_base + EXYNOSAUTO_SVC_OFFSET);
else
svc = readl(bank->eint_base + EXYNOS_SVC_OFFSET);
group = EXYNOS_SVC_GROUP(svc);
pin = svc & EXYNOS_SVC_NUM_MASK;
......@@ -456,6 +493,22 @@ static const struct exynos_irq_chip exynos7_wkup_irq_chip __initconst = {
.set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask,
};
static const struct exynos_irq_chip exynosautov920_wkup_irq_chip __initconst = {
.chip = {
.name = "exynosautov920_wkup_irq_chip",
.irq_unmask = exynos_irq_unmask,
.irq_mask = exynos_irq_mask,
.irq_ack = exynos_irq_ack,
.irq_set_type = exynos_irq_set_type,
.irq_set_wake = exynos_wkup_irq_set_wake,
.irq_request_resources = exynos_irq_request_resources,
.irq_release_resources = exynos_irq_release_resources,
},
.eint_wake_mask_value = &eint_wake_mask_value,
.eint_wake_mask_reg = EXYNOS5433_EINT_WAKEUP_MASK,
.set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask,
};
/* list of external wakeup controllers supported */
static const struct of_device_id exynos_wkup_irq_ids[] = {
{ .compatible = "samsung,s5pv210-wakeup-eint",
......@@ -468,6 +521,8 @@ static const struct of_device_id exynos_wkup_irq_ids[] = {
.data = &exynos7_wkup_irq_chip },
{ .compatible = "samsung,exynosautov9-wakeup-eint",
.data = &exynos7_wkup_irq_chip },
{ .compatible = "samsung,exynosautov920-wakeup-eint",
.data = &exynosautov920_wkup_irq_chip },
{ }
};
......@@ -655,6 +710,19 @@ static void exynos_pinctrl_suspend_bank(
pr_debug("%s: save mask %#010x\n", bank->name, save->eint_mask);
}
static void exynosauto_pinctrl_suspend_bank(struct samsung_pinctrl_drv_data *drvdata,
struct samsung_pin_bank *bank)
{
struct exynos_eint_gpio_save *save = bank->soc_priv;
void __iomem *regs = bank->eint_base;
save->eint_con = readl(regs + bank->pctl_offset + bank->eint_con_offset);
save->eint_mask = readl(regs + bank->pctl_offset + bank->eint_mask_offset);
pr_debug("%s: save con %#010x\n", bank->name, save->eint_con);
pr_debug("%s: save mask %#010x\n", bank->name, save->eint_mask);
}
void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
{
struct samsung_pin_bank *bank = drvdata->pin_banks;
......@@ -662,8 +730,12 @@ void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
int i;
for (i = 0; i < drvdata->nr_banks; ++i, ++bank) {
if (bank->eint_type == EINT_TYPE_GPIO)
exynos_pinctrl_suspend_bank(drvdata, bank);
if (bank->eint_type == EINT_TYPE_GPIO) {
if (bank->eint_con_offset)
exynosauto_pinctrl_suspend_bank(drvdata, bank);
else
exynos_pinctrl_suspend_bank(drvdata, bank);
}
else if (bank->eint_type == EINT_TYPE_WKUP) {
if (!irq_chip) {
irq_chip = bank->irq_chip;
......@@ -704,14 +776,33 @@ static void exynos_pinctrl_resume_bank(
+ bank->eint_offset);
}
static void exynosauto_pinctrl_resume_bank(struct samsung_pinctrl_drv_data *drvdata,
struct samsung_pin_bank *bank)
{
struct exynos_eint_gpio_save *save = bank->soc_priv;
void __iomem *regs = bank->eint_base;
pr_debug("%s: con %#010x => %#010x\n", bank->name,
readl(regs + bank->pctl_offset + bank->eint_con_offset), save->eint_con);
pr_debug("%s: mask %#010x => %#010x\n", bank->name,
readl(regs + bank->pctl_offset + bank->eint_mask_offset), save->eint_mask);
writel(save->eint_con, regs + bank->pctl_offset + bank->eint_con_offset);
writel(save->eint_mask, regs + bank->pctl_offset + bank->eint_mask_offset);
}
void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
{
struct samsung_pin_bank *bank = drvdata->pin_banks;
int i;
for (i = 0; i < drvdata->nr_banks; ++i, ++bank)
if (bank->eint_type == EINT_TYPE_GPIO)
exynos_pinctrl_resume_bank(drvdata, bank);
if (bank->eint_type == EINT_TYPE_GPIO) {
if (bank->eint_con_offset)
exynosauto_pinctrl_resume_bank(drvdata, bank);
else
exynos_pinctrl_resume_bank(drvdata, bank);
}
}
static void exynos_retention_enable(struct samsung_pinctrl_drv_data *drvdata)
......
......@@ -31,6 +31,7 @@
#define EXYNOS7_WKUP_EMASK_OFFSET 0x900
#define EXYNOS7_WKUP_EPEND_OFFSET 0xA00
#define EXYNOS_SVC_OFFSET 0xB08
#define EXYNOSAUTO_SVC_OFFSET 0xF008
/* helpers to access interrupt service register */
#define EXYNOS_SVC_GROUP_SHIFT 3
......@@ -140,6 +141,30 @@
.name = id \
}
#define EXYNOSV920_PIN_BANK_EINTG(pins, reg, id, con_offs, mask_offs, pend_offs) \
{ \
.type = &exynos850_bank_type_off, \
.pctl_offset = reg, \
.nr_pins = pins, \
.eint_type = EINT_TYPE_GPIO, \
.eint_con_offset = con_offs, \
.eint_mask_offset = mask_offs, \
.eint_pend_offset = pend_offs, \
.name = id \
}
#define EXYNOSV920_PIN_BANK_EINTW(pins, reg, id, con_offs, mask_offs, pend_offs) \
{ \
.type = &exynos850_bank_type_alive, \
.pctl_offset = reg, \
.nr_pins = pins, \
.eint_type = EINT_TYPE_WKUP, \
.eint_con_offset = con_offs, \
.eint_mask_offset = mask_offs, \
.eint_pend_offset = pend_offs, \
.name = id \
}
/**
* struct exynos_weint_data: irq specific data for all the wakeup interrupts
* generated by the external wakeup interrupt controller.
......
......@@ -1106,6 +1106,9 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
bank->eint_type = bdata->eint_type;
bank->eint_mask = bdata->eint_mask;
bank->eint_offset = bdata->eint_offset;
bank->eint_con_offset = bdata->eint_con_offset;
bank->eint_mask_offset = bdata->eint_mask_offset;
bank->eint_pend_offset = bdata->eint_pend_offset;
bank->name = bdata->name;
raw_spin_lock_init(&bank->slock);
......@@ -1309,6 +1312,8 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = {
.data = &s5pv210_of_data },
#endif
#ifdef CONFIG_PINCTRL_EXYNOS_ARM64
{ .compatible = "google,gs101-pinctrl",
.data = &gs101_of_data },
{ .compatible = "samsung,exynos5433-pinctrl",
.data = &exynos5433_of_data },
{ .compatible = "samsung,exynos7-pinctrl",
......@@ -1319,6 +1324,8 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = {
.data = &exynos850_of_data },
{ .compatible = "samsung,exynosautov9-pinctrl",
.data = &exynosautov9_of_data },
{ .compatible = "samsung,exynosautov920-pinctrl",
.data = &exynosautov920_of_data },
{ .compatible = "tesla,fsd-pinctrl",
.data = &fsd_of_data },
#endif
......
......@@ -122,6 +122,9 @@ struct samsung_pin_bank_type {
* @eint_type: type of the external interrupt supported by the bank.
* @eint_mask: bit mask of pins which support EINT function.
* @eint_offset: SoC-specific EINT register or interrupt offset of bank.
* @eint_con_offset: ExynosAuto SoC-specific EINT control register offset of bank.
* @eint_mask_offset: ExynosAuto SoC-specific EINT mask register offset of bank.
* @eint_pend_offset: ExynosAuto SoC-specific EINT pend register offset of bank.
* @name: name to be prefixed for each pin in this pin bank.
*/
struct samsung_pin_bank_data {
......@@ -133,6 +136,9 @@ struct samsung_pin_bank_data {
enum eint_type eint_type;
u32 eint_mask;
u32 eint_offset;
u32 eint_con_offset;
u32 eint_mask_offset;
u32 eint_pend_offset;
const char *name;
};
......@@ -147,6 +153,9 @@ struct samsung_pin_bank_data {
* @eint_type: type of the external interrupt supported by the bank.
* @eint_mask: bit mask of pins which support EINT function.
* @eint_offset: SoC-specific EINT register or interrupt offset of bank.
* @eint_con_offset: ExynosAuto SoC-specific EINT register or interrupt offset of bank.
* @eint_mask_offset: ExynosAuto SoC-specific EINT mask register offset of bank.
* @eint_pend_offset: ExynosAuto SoC-specific EINT pend register offset of bank.
* @name: name to be prefixed for each pin in this pin bank.
* @id: id of the bank, propagated to the pin range.
* @pin_base: starting pin number of the bank.
......@@ -170,6 +179,9 @@ struct samsung_pin_bank {
enum eint_type eint_type;
u32 eint_mask;
u32 eint_offset;
u32 eint_con_offset;
u32 eint_mask_offset;
u32 eint_pend_offset;
const char *name;
u32 id;
......@@ -350,7 +362,9 @@ extern const struct samsung_pinctrl_of_match_data exynos7_of_data;
extern const struct samsung_pinctrl_of_match_data exynos7885_of_data;
extern const struct samsung_pinctrl_of_match_data exynos850_of_data;
extern const struct samsung_pinctrl_of_match_data exynosautov9_of_data;
extern const struct samsung_pinctrl_of_match_data exynosautov920_of_data;
extern const struct samsung_pinctrl_of_match_data fsd_of_data;
extern const struct samsung_pinctrl_of_match_data gs101_of_data;
extern const struct samsung_pinctrl_of_match_data s3c64xx_of_data;
extern const struct samsung_pinctrl_of_match_data s3c2412_of_data;
extern const struct samsung_pinctrl_of_match_data s3c2416_of_data;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment