* [PATCH AUTOSEL 5.1 33/39] pinctrl: mediatek: Ignore interrupts that are wake only during resume
From: Sasha Levin @ 2019-07-03 2:15 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Nicolas Boichat, Sean Wang, Linus Walleij, Sasha Levin,
linux-gpio
In-Reply-To: <20190703021514.17727-1-sashal@kernel.org>
From: Nicolas Boichat <drinkcat@chromium.org>
[ Upstream commit 35594bc7cecf3a78504b590e350570e8f4d7779e ]
Before suspending, mtk-eint would set the interrupt mask to the
one in wake_mask. However, some of these interrupts may not have a
corresponding interrupt handler, or the interrupt may be disabled.
On resume, the eint irq handler would trigger nevertheless,
and irq/pm.c:irq_pm_check_wakeup would be called, which would
try to call irq_disable. However, if the interrupt is not enabled
(irqd_irq_disabled(&desc->irq_data) is true), the call does nothing,
and the interrupt is left enabled in the eint driver.
Especially for level-sensitive interrupts, this will lead to an
interrupt storm on resume.
If we detect that an interrupt is only in wake_mask, but not in
cur_mask, we can just mask it out immediately (as mtk_eint_resume
would do anyway at a later stage in the resume sequence, when
restoring cur_mask).
Fixes: bf22ff45bed6 ("genirq: Avoid unnecessary low level irq function calls")
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
Acked-by: Sean Wang <sean.wang@kernel.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/pinctrl/mediatek/mtk-eint.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/pinctrl/mediatek/mtk-eint.c b/drivers/pinctrl/mediatek/mtk-eint.c
index f464f8cd274b..737385e86beb 100644
--- a/drivers/pinctrl/mediatek/mtk-eint.c
+++ b/drivers/pinctrl/mediatek/mtk-eint.c
@@ -318,7 +318,7 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
struct irq_chip *chip = irq_desc_get_chip(desc);
struct mtk_eint *eint = irq_desc_get_handler_data(desc);
unsigned int status, eint_num;
- int offset, index, virq;
+ int offset, mask_offset, index, virq;
void __iomem *reg = mtk_eint_get_offset(eint, 0, eint->regs->stat);
int dual_edge, start_level, curr_level;
@@ -328,10 +328,24 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
status = readl(reg);
while (status) {
offset = __ffs(status);
+ mask_offset = eint_num >> 5;
index = eint_num + offset;
virq = irq_find_mapping(eint->domain, index);
status &= ~BIT(offset);
+ /*
+ * If we get an interrupt on pin that was only required
+ * for wake (but no real interrupt requested), mask the
+ * interrupt (as would mtk_eint_resume do anyway later
+ * in the resume sequence).
+ */
+ if (eint->wake_mask[mask_offset] & BIT(offset) &&
+ !(eint->cur_mask[mask_offset] & BIT(offset))) {
+ writel_relaxed(BIT(offset), reg -
+ eint->regs->stat +
+ eint->regs->mask_set);
+ }
+
dual_edge = eint->dual_edge[index];
if (dual_edge) {
/*
--
2.20.1
^ permalink raw reply related
* [PATCH AUTOSEL 4.19 16/26] pinctrl: mcp23s08: Fix add_data and irqchip_add_nested call order
From: Sasha Levin @ 2019-07-03 2:16 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Phil Reid, Marco Felsch, Linus Walleij, Sasha Levin, linux-gpio
In-Reply-To: <20190703021625.18116-1-sashal@kernel.org>
From: Phil Reid <preid@electromag.com.au>
[ Upstream commit 6dbc6e6f58556369bf999cd7d9793586f1b0e4b4 ]
Currently probing of the mcp23s08 results in an error message
"detected irqchip that is shared with multiple gpiochips:
please fix the driver"
This is due to the following:
Call to mcp23s08_irqchip_setup() with call hierarchy:
mcp23s08_irqchip_setup()
gpiochip_irqchip_add_nested()
gpiochip_irqchip_add_key()
gpiochip_set_irq_hooks()
Call to devm_gpiochip_add_data() with call hierarchy:
devm_gpiochip_add_data()
gpiochip_add_data_with_key()
gpiochip_add_irqchip()
gpiochip_set_irq_hooks()
The gpiochip_add_irqchip() returns immediately if there isn't a irqchip
but we added a irqchip due to the previous mcp23s08_irqchip_setup()
call. So it calls gpiochip_set_irq_hooks() a second time.
Fix this by moving the call to devm_gpiochip_add_data before
the call to mcp23s08_irqchip_setup
Fixes: 02e389e63e35 ("pinctrl: mcp23s08: fix irq setup order")
Suggested-by: Marco Felsch <m.felsch@pengutronix.de>
Signed-off-by: Phil Reid <preid@electromag.com.au>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/pinctrl/pinctrl-mcp23s08.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c
index cecbce21d01f..33c3eca0ece9 100644
--- a/drivers/pinctrl/pinctrl-mcp23s08.c
+++ b/drivers/pinctrl/pinctrl-mcp23s08.c
@@ -889,6 +889,10 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
if (ret < 0)
goto fail;
+ ret = devm_gpiochip_add_data(dev, &mcp->chip, mcp);
+ if (ret < 0)
+ goto fail;
+
mcp->irq_controller =
device_property_read_bool(dev, "interrupt-controller");
if (mcp->irq && mcp->irq_controller) {
@@ -930,10 +934,6 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
goto fail;
}
- ret = devm_gpiochip_add_data(dev, &mcp->chip, mcp);
- if (ret < 0)
- goto fail;
-
if (one_regmap_config) {
mcp->pinctrl_desc.name = devm_kasprintf(dev, GFP_KERNEL,
"mcp23xxx-pinctrl.%d", raw_chip_address);
--
2.20.1
^ permalink raw reply related
* [PATCH AUTOSEL 4.19 23/26] pinctrl: mediatek: Ignore interrupts that are wake only during resume
From: Sasha Levin @ 2019-07-03 2:16 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Nicolas Boichat, Sean Wang, Linus Walleij, Sasha Levin,
linux-gpio
In-Reply-To: <20190703021625.18116-1-sashal@kernel.org>
From: Nicolas Boichat <drinkcat@chromium.org>
[ Upstream commit 35594bc7cecf3a78504b590e350570e8f4d7779e ]
Before suspending, mtk-eint would set the interrupt mask to the
one in wake_mask. However, some of these interrupts may not have a
corresponding interrupt handler, or the interrupt may be disabled.
On resume, the eint irq handler would trigger nevertheless,
and irq/pm.c:irq_pm_check_wakeup would be called, which would
try to call irq_disable. However, if the interrupt is not enabled
(irqd_irq_disabled(&desc->irq_data) is true), the call does nothing,
and the interrupt is left enabled in the eint driver.
Especially for level-sensitive interrupts, this will lead to an
interrupt storm on resume.
If we detect that an interrupt is only in wake_mask, but not in
cur_mask, we can just mask it out immediately (as mtk_eint_resume
would do anyway at a later stage in the resume sequence, when
restoring cur_mask).
Fixes: bf22ff45bed6 ("genirq: Avoid unnecessary low level irq function calls")
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
Acked-by: Sean Wang <sean.wang@kernel.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/pinctrl/mediatek/mtk-eint.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/pinctrl/mediatek/mtk-eint.c b/drivers/pinctrl/mediatek/mtk-eint.c
index a613e546717a..b9f3c02ba59d 100644
--- a/drivers/pinctrl/mediatek/mtk-eint.c
+++ b/drivers/pinctrl/mediatek/mtk-eint.c
@@ -318,7 +318,7 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
struct irq_chip *chip = irq_desc_get_chip(desc);
struct mtk_eint *eint = irq_desc_get_handler_data(desc);
unsigned int status, eint_num;
- int offset, index, virq;
+ int offset, mask_offset, index, virq;
void __iomem *reg = mtk_eint_get_offset(eint, 0, eint->regs->stat);
int dual_edge, start_level, curr_level;
@@ -328,10 +328,24 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
status = readl(reg);
while (status) {
offset = __ffs(status);
+ mask_offset = eint_num >> 5;
index = eint_num + offset;
virq = irq_find_mapping(eint->domain, index);
status &= ~BIT(offset);
+ /*
+ * If we get an interrupt on pin that was only required
+ * for wake (but no real interrupt requested), mask the
+ * interrupt (as would mtk_eint_resume do anyway later
+ * in the resume sequence).
+ */
+ if (eint->wake_mask[mask_offset] & BIT(offset) &&
+ !(eint->cur_mask[mask_offset] & BIT(offset))) {
+ writel_relaxed(BIT(offset), reg -
+ eint->regs->stat +
+ eint->regs->mask_set);
+ }
+
dual_edge = eint->dual_edge[index];
if (dual_edge) {
/*
--
2.20.1
^ permalink raw reply related
* [PATCH AUTOSEL 4.19 25/26] pinctrl: mediatek: Update cur_mask in mask/mask ops
From: Sasha Levin @ 2019-07-03 2:16 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Nicolas Boichat, Sean Wang, Linus Walleij, Sasha Levin,
linux-gpio
In-Reply-To: <20190703021625.18116-1-sashal@kernel.org>
From: Nicolas Boichat <drinkcat@chromium.org>
[ Upstream commit 9d957a959bc8c3dfe37572ac8e99affb5a885965 ]
During suspend/resume, mtk_eint_mask may be called while
wake_mask is active. For example, this happens if a wake-source
with an active interrupt handler wakes the system:
irq/pm.c:irq_pm_check_wakeup would disable the interrupt, so
that it can be handled later on in the resume flow.
However, this may happen before mtk_eint_do_resume is called:
in this case, wake_mask is loaded, and cur_mask is restored
from an older copy, re-enabling the interrupt, and causing
an interrupt storm (especially for level interrupts).
Step by step, for a line that has both wake and interrupt enabled:
1. cur_mask[irq] = 1; wake_mask[irq] = 1; EINT_EN[irq] = 1 (interrupt
enabled at hardware level)
2. System suspends, resumes due to that line (at this stage EINT_EN
== wake_mask)
3. irq_pm_check_wakeup is called, and disables the interrupt =>
EINT_EN[irq] = 0, but we still have cur_mask[irq] = 1
4. mtk_eint_do_resume is called, and restores EINT_EN = cur_mask, so
it reenables EINT_EN[irq] = 1 => interrupt storm as the driver
is not yet ready to handle the interrupt.
This patch fixes the issue in step 3, by recording all mask/unmask
changes in cur_mask. This also avoids the need to read the current
mask in eint_do_suspend, and we can remove mtk_eint_chip_read_mask
function.
The interrupt will be re-enabled properly later on, sometimes after
mtk_eint_do_resume, when the driver is ready to handle it.
Fixes: 58a5e1b64bb0 ("pinctrl: mediatek: Implement wake handler and suspend resume")
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
Acked-by: Sean Wang <sean.wang@kernel.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/pinctrl/mediatek/mtk-eint.c | 18 ++++--------------
1 file changed, 4 insertions(+), 14 deletions(-)
diff --git a/drivers/pinctrl/mediatek/mtk-eint.c b/drivers/pinctrl/mediatek/mtk-eint.c
index b9f3c02ba59d..564cfaee129d 100644
--- a/drivers/pinctrl/mediatek/mtk-eint.c
+++ b/drivers/pinctrl/mediatek/mtk-eint.c
@@ -113,6 +113,8 @@ static void mtk_eint_mask(struct irq_data *d)
void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
eint->regs->mask_set);
+ eint->cur_mask[d->hwirq >> 5] &= ~mask;
+
writel(mask, reg);
}
@@ -123,6 +125,8 @@ static void mtk_eint_unmask(struct irq_data *d)
void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
eint->regs->mask_clr);
+ eint->cur_mask[d->hwirq >> 5] |= mask;
+
writel(mask, reg);
if (eint->dual_edge[d->hwirq])
@@ -217,19 +221,6 @@ static void mtk_eint_chip_write_mask(const struct mtk_eint *eint,
}
}
-static void mtk_eint_chip_read_mask(const struct mtk_eint *eint,
- void __iomem *base, u32 *buf)
-{
- int port;
- void __iomem *reg;
-
- for (port = 0; port < eint->hw->ports; port++) {
- reg = base + eint->regs->mask + (port << 2);
- buf[port] = ~readl_relaxed(reg);
- /* Mask is 0 when irq is enabled, and 1 when disabled. */
- }
-}
-
static int mtk_eint_irq_request_resources(struct irq_data *d)
{
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
@@ -384,7 +375,6 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
int mtk_eint_do_suspend(struct mtk_eint *eint)
{
- mtk_eint_chip_read_mask(eint, eint->base, eint->cur_mask);
mtk_eint_chip_write_mask(eint, eint->base, eint->wake_mask);
return 0;
--
2.20.1
^ permalink raw reply related
* [PATCH AUTOSEL 5.1 36/39] pinctrl: mediatek: Update cur_mask in mask/mask ops
From: Sasha Levin @ 2019-07-03 2:15 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Nicolas Boichat, Sean Wang, Linus Walleij, Sasha Levin,
linux-gpio
In-Reply-To: <20190703021514.17727-1-sashal@kernel.org>
From: Nicolas Boichat <drinkcat@chromium.org>
[ Upstream commit 9d957a959bc8c3dfe37572ac8e99affb5a885965 ]
During suspend/resume, mtk_eint_mask may be called while
wake_mask is active. For example, this happens if a wake-source
with an active interrupt handler wakes the system:
irq/pm.c:irq_pm_check_wakeup would disable the interrupt, so
that it can be handled later on in the resume flow.
However, this may happen before mtk_eint_do_resume is called:
in this case, wake_mask is loaded, and cur_mask is restored
from an older copy, re-enabling the interrupt, and causing
an interrupt storm (especially for level interrupts).
Step by step, for a line that has both wake and interrupt enabled:
1. cur_mask[irq] = 1; wake_mask[irq] = 1; EINT_EN[irq] = 1 (interrupt
enabled at hardware level)
2. System suspends, resumes due to that line (at this stage EINT_EN
== wake_mask)
3. irq_pm_check_wakeup is called, and disables the interrupt =>
EINT_EN[irq] = 0, but we still have cur_mask[irq] = 1
4. mtk_eint_do_resume is called, and restores EINT_EN = cur_mask, so
it reenables EINT_EN[irq] = 1 => interrupt storm as the driver
is not yet ready to handle the interrupt.
This patch fixes the issue in step 3, by recording all mask/unmask
changes in cur_mask. This also avoids the need to read the current
mask in eint_do_suspend, and we can remove mtk_eint_chip_read_mask
function.
The interrupt will be re-enabled properly later on, sometimes after
mtk_eint_do_resume, when the driver is ready to handle it.
Fixes: 58a5e1b64bb0 ("pinctrl: mediatek: Implement wake handler and suspend resume")
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
Acked-by: Sean Wang <sean.wang@kernel.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/pinctrl/mediatek/mtk-eint.c | 18 ++++--------------
1 file changed, 4 insertions(+), 14 deletions(-)
diff --git a/drivers/pinctrl/mediatek/mtk-eint.c b/drivers/pinctrl/mediatek/mtk-eint.c
index 737385e86beb..7e526bcf5e0b 100644
--- a/drivers/pinctrl/mediatek/mtk-eint.c
+++ b/drivers/pinctrl/mediatek/mtk-eint.c
@@ -113,6 +113,8 @@ static void mtk_eint_mask(struct irq_data *d)
void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
eint->regs->mask_set);
+ eint->cur_mask[d->hwirq >> 5] &= ~mask;
+
writel(mask, reg);
}
@@ -123,6 +125,8 @@ static void mtk_eint_unmask(struct irq_data *d)
void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
eint->regs->mask_clr);
+ eint->cur_mask[d->hwirq >> 5] |= mask;
+
writel(mask, reg);
if (eint->dual_edge[d->hwirq])
@@ -217,19 +221,6 @@ static void mtk_eint_chip_write_mask(const struct mtk_eint *eint,
}
}
-static void mtk_eint_chip_read_mask(const struct mtk_eint *eint,
- void __iomem *base, u32 *buf)
-{
- int port;
- void __iomem *reg;
-
- for (port = 0; port < eint->hw->ports; port++) {
- reg = base + eint->regs->mask + (port << 2);
- buf[port] = ~readl_relaxed(reg);
- /* Mask is 0 when irq is enabled, and 1 when disabled. */
- }
-}
-
static int mtk_eint_irq_request_resources(struct irq_data *d)
{
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
@@ -384,7 +375,6 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
int mtk_eint_do_suspend(struct mtk_eint *eint)
{
- mtk_eint_chip_read_mask(eint, eint->base, eint->cur_mask);
mtk_eint_chip_write_mask(eint, eint->base, eint->wake_mask);
return 0;
--
2.20.1
^ permalink raw reply related
* [PATCH 4/4] gpio: stp-xway: allow compile-testing
From: Martin Blumenstingl @ 2019-07-02 22:32 UTC (permalink / raw)
To: blogic, linus.walleij, bgolaszewski, linux-gpio
Cc: dev, linux-kernel, Martin Blumenstingl
In-Reply-To: <20190702223248.31934-1-martin.blumenstingl@googlemail.com>
Enable compile-testing of the stp-xway GPIO driver now that it does not
depend on any architecture specific includes anymore.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
drivers/gpio/Kconfig | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index f1f02dac324e..43d7d6a9d9ab 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -489,7 +489,8 @@ config GPIO_STA2X11
config GPIO_STP_XWAY
bool "XWAY STP GPIOs"
- depends on SOC_XWAY
+ depends on SOC_XWAY || COMPILE_TEST
+ depends on OF_GPIO
help
This enables support for the Serial To Parallel (STP) unit found on
XWAY SoC. The STP allows the SoC to drive a shift registers cascade,
--
2.22.0
^ permalink raw reply related
* [PATCH 2/4] gpio: stp-xway: improve module clock error handling
From: Martin Blumenstingl @ 2019-07-02 22:32 UTC (permalink / raw)
To: blogic, linus.walleij, bgolaszewski, linux-gpio
Cc: dev, linux-kernel, Martin Blumenstingl
In-Reply-To: <20190702223248.31934-1-martin.blumenstingl@googlemail.com>
Three module clock error handling improvements:
- use devm_clk_get() so the clock instance can be freed if
devm_gpiochip_add_data() fails later on
- switch to clk_prepare_enable() so the driver is ready whenever the
lantiq target switches to the common clock framework
- disable the clock again (using clk_disable_unprepare()) if
devm_gpiochip_add_data()
All of these are virtually no-ops with the current lantiq target.
However, these will be relevant if we switch to the common clock
framework.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
drivers/gpio/gpio-stp-xway.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c
index a3326255ce3c..b31e08f84681 100644
--- a/drivers/gpio/gpio-stp-xway.c
+++ b/drivers/gpio/gpio-stp-xway.c
@@ -256,18 +256,23 @@ static int xway_stp_probe(struct platform_device *pdev)
if (!of_find_property(pdev->dev.of_node, "lantiq,rising", NULL))
chip->edge = XWAY_STP_FALLING;
- clk = clk_get(&pdev->dev, NULL);
+ clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "Failed to get clock\n");
return PTR_ERR(clk);
}
- clk_enable(clk);
+
+ ret = clk_prepare_enable(clk);
+ if (ret)
+ return ret;
xway_stp_hw_init(chip);
ret = devm_gpiochip_add_data(&pdev->dev, &chip->gc, chip);
- if (ret)
+ if (ret) {
+ clk_disable_unprepare(clk);
return ret;
+ }
dev_info(&pdev->dev, "Init done\n");
--
2.22.0
^ permalink raw reply related
* [PATCH 0/4] gpio: stp-xway: small cleanups and improvements
From: Martin Blumenstingl @ 2019-07-02 22:32 UTC (permalink / raw)
To: blogic, linus.walleij, bgolaszewski, linux-gpio
Cc: dev, linux-kernel, Martin Blumenstingl
This series brings a few small cleanups and improvements to the stp-xway
driver:
- enable compile-testing
- preparation for whenever the lantiq target switches to the common clock
framework
- easier to read (for me)
None of these fixes any known bugs so there's no Fixes tag anywhere.
It's probably too late for inclusion into Linux 5.3. No need to rush,
I'm happy with 5.4 as well.
Martin Blumenstingl (4):
gpio: stp-xway: simplify error handling in xway_stp_probe()
gpio: stp-xway: improve module clock error handling
gpio: stp-xway: get rid of the #include <lantiq_soc.h> dependency
gpio: stp-xway: allow compile-testing
drivers/gpio/Kconfig | 3 ++-
drivers/gpio/gpio-stp-xway.c | 33 +++++++++++++++++----------------
2 files changed, 19 insertions(+), 17 deletions(-)
--
2.22.0
^ permalink raw reply
* [PATCH 1/4] gpio: stp-xway: simplify error handling in xway_stp_probe()
From: Martin Blumenstingl @ 2019-07-02 22:32 UTC (permalink / raw)
To: blogic, linus.walleij, bgolaszewski, linux-gpio
Cc: dev, linux-kernel, Martin Blumenstingl
In-Reply-To: <20190702223248.31934-1-martin.blumenstingl@googlemail.com>
Return early if devm_gpiochip_add_data() returns an error instead of
having two consecutive "if (!ret) ..." statements.
Also make xway_stp_hw_init() return void because it unconditionally
returns 0. While here also update the kerneldoc comment for
xway_stp_hw_init().
These changes makes the error handling within the driver consistent.
No functional changes intended.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
drivers/gpio/gpio-stp-xway.c | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c
index 24c478392394..a3326255ce3c 100644
--- a/drivers/gpio/gpio-stp-xway.c
+++ b/drivers/gpio/gpio-stp-xway.c
@@ -156,9 +156,9 @@ static int xway_stp_request(struct gpio_chip *gc, unsigned gpio)
/**
* xway_stp_hw_init() - Configure the STP unit and enable the clock gate
- * @virt: pointer to the remapped register range
+ * @chip: Pointer to the xway_stp chip structure
*/
-static int xway_stp_hw_init(struct xway_stp *chip)
+static void xway_stp_hw_init(struct xway_stp *chip)
{
/* sane defaults */
xway_stp_w32(chip->virt, 0, XWAY_STP_AR);
@@ -201,8 +201,6 @@ static int xway_stp_hw_init(struct xway_stp *chip)
if (chip->reserved)
xway_stp_w32_mask(chip->virt, XWAY_STP_UPD_MASK,
XWAY_STP_UPD_FPI, XWAY_STP_CON1);
-
- return 0;
}
static int xway_stp_probe(struct platform_device *pdev)
@@ -265,14 +263,15 @@ static int xway_stp_probe(struct platform_device *pdev)
}
clk_enable(clk);
- ret = xway_stp_hw_init(chip);
- if (!ret)
- ret = devm_gpiochip_add_data(&pdev->dev, &chip->gc, chip);
+ xway_stp_hw_init(chip);
- if (!ret)
- dev_info(&pdev->dev, "Init done\n");
+ ret = devm_gpiochip_add_data(&pdev->dev, &chip->gc, chip);
+ if (ret)
+ return ret;
- return ret;
+ dev_info(&pdev->dev, "Init done\n");
+
+ return 0;
}
static const struct of_device_id xway_stp_match[] = {
--
2.22.0
^ permalink raw reply related
* Re: [RFC/RFT v3 10/14] arm64: dts: meson-g12-common: add pwm_a on GPIOE_2 pinmux
From: Martin Blumenstingl @ 2019-07-02 23:11 UTC (permalink / raw)
To: Neil Armstrong
Cc: jbrunet, khilman, linux-arm-kernel, linux-amlogic, linux-kernel,
linux-clk, linux-gpio
In-Reply-To: <20190701091258.3870-11-narmstrong@baylibre.com>
On Mon, Jul 1, 2019 at 11:13 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> Add the ao_pinctrl subnode for the pwm_a function on GPIOE_2.
>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
^ permalink raw reply
* Re: [RFC/RFT v3 01/14] pinctrl: meson-g12a: add pwm_a on GPIOE_2 pinmux
From: Martin Blumenstingl @ 2019-07-02 22:56 UTC (permalink / raw)
To: Neil Armstrong
Cc: jbrunet, khilman, linux-arm-kernel, linux-amlogic, linux-kernel,
linux-clk, linux-gpio
In-Reply-To: <20190701091258.3870-2-narmstrong@baylibre.com>
On Mon, Jul 1, 2019 at 11:13 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> Add the missing pinmux for the pwm_a function on the GPIOE_2 pin.
>
> Reviewed-by: Kevin Hilman <khilman@baylibre.com>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
it's not documented anywhere but Amlogic's buildroot kernel (from
buildroot-openlinux-A113-201901) uses the same bit so it seems
correct.
Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
^ permalink raw reply
* Re: [RFC/RFT v3 04/14] clk: meson: eeclk: add setup callback
From: Martin Blumenstingl @ 2019-07-02 23:16 UTC (permalink / raw)
To: Neil Armstrong
Cc: jbrunet, khilman, linux-arm-kernel, linux-amlogic, linux-kernel,
linux-clk, linux-gpio, amergnat
In-Reply-To: <20190701091258.3870-5-narmstrong@baylibre.com>
+Cc Alexandre Mergnat
On Mon, Jul 1, 2019 at 11:13 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> Add a setup() callback in the eeclk structure, to call an optional
> call() function at end of eeclk probe to setup clocks.
>
> It's used for the G12A clock controller to setup the CPU clock notifiers.
>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
this will probably work fine, but I want do double check first
are we planning to get rid of meson-eeclk (mid-term)?
Alex has some patches to get rid of all these IN_PREFIX logic.
I'm asking because if we want to get rid of meson-eeclk it may be the
time to do so now to have less logic to migrate later on
Martin
^ permalink raw reply
* Re: [RFC/RFT v3 08/14] clk: meson: g12a: expose CPUB clock ID for G12B
From: Martin Blumenstingl @ 2019-07-02 23:03 UTC (permalink / raw)
To: Neil Armstrong
Cc: jbrunet, khilman, linux-arm-kernel, linux-amlogic, linux-kernel,
linux-clk, linux-gpio
In-Reply-To: <20190701091258.3870-9-narmstrong@baylibre.com>
On Mon, Jul 1, 2019 at 11:13 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> Expose the CPUB clock id to add DVFS to the second CPU cluster of
> the Amlogic G12B SoC.
>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
^ permalink raw reply
* Re: [RFC/RFT v3 12/14] arm64: dts: meson-g12a: enable DVFS on G12A boards
From: Martin Blumenstingl @ 2019-07-02 23:43 UTC (permalink / raw)
To: Neil Armstrong
Cc: jbrunet, khilman, linux-arm-kernel, linux-amlogic, linux-kernel,
linux-clk, linux-gpio
In-Reply-To: <20190701091258.3870-13-narmstrong@baylibre.com>
On Mon, Jul 1, 2019 at 11:13 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> Enable DVFS for the U200, SEI520 and X96-Max Amlogic G12A based board
> by setting the clock, OPP and supply for each CPU cores.
>
> The CPU cluster power supply can achieve 0.73V to 1.01V using a PWM
> output clocked at 800KHz with an inverse duty-cycle.
>
> DVFS has been tested by running the arm64 cpuburn at [1] and cycling
> between all the possible cpufreq translations and checking the final
> frequency using the clock-measurer, script at [2].
>
> [1] https://github.com/ssvb/cpuburn-arm/blob/master/cpuburn-a53.S
> [2] https://gist.github.com/superna9999/d4de964dbc0f84b7d527e1df2ddea25f
>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
^ permalink raw reply
* Re: [RFC/RFT v3 09/14] arm64: dts: move common G12A & G12B modes to meson-g12-common.dtsi
From: Martin Blumenstingl @ 2019-07-02 23:54 UTC (permalink / raw)
To: Neil Armstrong
Cc: jbrunet, khilman, linux-arm-kernel, linux-amlogic, linux-kernel,
linux-clk, linux-gpio
In-Reply-To: <20190701091258.3870-10-narmstrong@baylibre.com>
Hi Neil,
On Mon, Jul 1, 2019 at 11:13 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> To simplify the representation of differences betweem the G12A and G12B
> SoCs, move the common nodes into a meson-g12-common.dtsi file and
> express the CPU nodes and differences in meson-g12a.dtsi and meson-g12b.dtsi.
>
> This separation will help for DVFS and future Amlogic SM1 Family support.
>
> The sd_emmc_a quirk is added in the g12a/g12b since since it's already
> known the sd_emmc_a controller is fixed in the next SM1 SoC family.
too bad they named the upcoming SoC family SM1
does it make sense to name this file "meson-g12a-g12b-sm1-common.dtsi" instead?
do you know whether there will be a successor to G12B and what it's
code-name will be?
Martin
^ permalink raw reply
* Re: [RFC/RFT v3 11/14] arm64: dts: meson-g12a: add cpus OPP table
From: Martin Blumenstingl @ 2019-07-02 23:47 UTC (permalink / raw)
To: Neil Armstrong
Cc: jbrunet, khilman, linux-arm-kernel, linux-amlogic, linux-kernel,
linux-clk, linux-gpio
In-Reply-To: <20190701091258.3870-12-narmstrong@baylibre.com>
Hi Neil,
On Mon, Jul 1, 2019 at 11:13 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> Add the OPP table taken from the vendor u200 and u211 DTS.
>
> The Amlogic G12A SoC seems to available in 3 types :
> - low-speed: up to 1,8GHz
> - mid-speed: up to 1,908GHz
> - high-speed: up to 2.1GHz
>
> And the S905X2 opp voltages are slightly higher than the S905D2
> OPP voltages for the low-speed table.
>
> This adds the conservative OPP table with the S905X2 higher voltages
> and the maximum low-speed OPP frequency.
have you considered all three as separate voltage tables?
you're other patches are assigning the OPP table to the CPU in the
board.dts anyways, so it's easy to use different OPP tables for
different boards
^ permalink raw reply
* Re: [RFC/RFT v3 02/14] clk: core: introduce clk_hw_set_parent()
From: Martin Blumenstingl @ 2019-07-02 23:05 UTC (permalink / raw)
To: Neil Armstrong
Cc: jbrunet, khilman, linux-arm-kernel, linux-amlogic, linux-kernel,
linux-clk, linux-gpio
In-Reply-To: <20190701091258.3870-3-narmstrong@baylibre.com>
On Mon, Jul 1, 2019 at 11:13 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> Introduce the clk_hw_set_parent() provider call to change parent of
> a clock by using the clk_hw pointers.
>
> This eases the clock reparenting from clock rate notifiers and
> implementing DVFS with simpler code avoiding the boilerplates
> functions as __clk_lookup(clk_hw_get_name()) then clk_set_parent().
>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
for the same reason this is handy for the meson8b clock driver as well, so:
Acked-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
^ permalink raw reply
* Re: [RFC/RFT v3 14/14] arm64: dts: meson-g12b-odroid-n2: enable DVFS
From: Martin Blumenstingl @ 2019-07-02 23:45 UTC (permalink / raw)
To: Neil Armstrong
Cc: jbrunet, khilman, linux-arm-kernel, linux-amlogic, linux-kernel,
linux-clk, linux-gpio
In-Reply-To: <20190701091258.3870-15-narmstrong@baylibre.com>
On Mon, Jul 1, 2019 at 11:13 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> Enable DVFS for the Odroid-N2 by setting the clock, OPP and supply
> for each cores of each CPU clusters.
>
> The first cluster uses the "VDDCPU_B" power supply, and the second
> cluster uses the "VDDCPU_A" power supply.
>
> Each power supply can achieve 0.73V to 1.01V using 2 distinct PWM
> outputs clocked at 800KHz with an inverse duty-cycle.
>
> DVFS has been tested by running the arm64 cpuburn at [1] and cycling
> between all the possible cpufreq translations of each cluster and
> checking the final frequency using the clock-measurer, script at [2].
>
> [1] https://github.com/ssvb/cpuburn-arm/blob/master/cpuburn-a53.S
> [2] https://gist.github.com/superna9999/d4de964dbc0f84b7d527e1df2ddea25f
>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
[...]
> + vddcpu_b: regulator-vddcpu-b {
> + /*
> + * Silergy SY8120B1ABC Regulator.
> + */
interesting that they use different regulator ICs for CPU A and CPU B
the public schematics confirm your comments
^ permalink raw reply
* Re: [RFC/RFT v3 05/14] soc: amlogic: meson-clk-measure: protect measure with a mutex
From: Martin Blumenstingl @ 2019-07-02 23:01 UTC (permalink / raw)
To: Neil Armstrong
Cc: jbrunet, khilman, linux-arm-kernel, linux-amlogic, linux-kernel,
linux-clk, linux-gpio
In-Reply-To: <20190701091258.3870-6-narmstrong@baylibre.com>
Hi Neil,
On Mon, Jul 1, 2019 at 11:13 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> In order to protect clock measuring when multiple process asks for
> a measure, protect the main measure function with mutexes.
>
> Reviewed-by: Kevin Hilman <khilman@baylibre.com>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
> drivers/soc/amlogic/meson-clk-measure.c | 12 +++++++++++-
> 1 file changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/soc/amlogic/meson-clk-measure.c b/drivers/soc/amlogic/meson-clk-measure.c
> index 19d4cbc93a17..c470e24f1dfa 100644
> --- a/drivers/soc/amlogic/meson-clk-measure.c
> +++ b/drivers/soc/amlogic/meson-clk-measure.c
> @@ -11,6 +11,8 @@
> #include <linux/debugfs.h>
> #include <linux/regmap.h>
>
> +static DEFINE_MUTEX(measure_lock);
I wonder if that should be part of struct meson_msr for consistency reasons
apart from that:
Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
^ permalink raw reply
* Re: [RFC/RFT v3 06/14] soc: amlogic: meson-clk-measure: add G12B second cluster cpu clk
From: Martin Blumenstingl @ 2019-07-02 22:58 UTC (permalink / raw)
To: Neil Armstrong
Cc: jbrunet, khilman, linux-arm-kernel, linux-amlogic, linux-kernel,
linux-clk, linux-gpio
In-Reply-To: <20190701091258.3870-7-narmstrong@baylibre.com>
On Mon, Jul 1, 2019 at 11:13 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> Add the G12B second CPU cluster CPU and SYS_PLL measure IDs.
>
> These IDs returns 0Hz on G12A.
>
> Reviewed-by: Kevin Hilman <khilman@baylibre.com>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
^ permalink raw reply
* [PATCH 3/4] gpio: stp-xway: get rid of the #include <lantiq_soc.h> dependency
From: Martin Blumenstingl @ 2019-07-02 22:32 UTC (permalink / raw)
To: blogic, linus.walleij, bgolaszewski, linux-gpio
Cc: dev, linux-kernel, Martin Blumenstingl
In-Reply-To: <20190702223248.31934-1-martin.blumenstingl@googlemail.com>
Use the xway_stp_{r,w}32 helpers in xway_stp_w32_mask instead of relying
on ltq_{r,w}32 from the architecture specific <lantiq_soc.h>.
This will allow the driver to be compile-tested on all architectures
that support MMIO.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
drivers/gpio/gpio-stp-xway.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c
index b31e08f84681..9e23a5ae8108 100644
--- a/drivers/gpio/gpio-stp-xway.c
+++ b/drivers/gpio/gpio-stp-xway.c
@@ -15,8 +15,6 @@
#include <linux/clk.h>
#include <linux/err.h>
-#include <lantiq_soc.h>
-
/*
* The Serial To Parallel (STP) is found on MIPS based Lantiq socs. It is a
* peripheral controller used to drive external shift register cascades. At most
@@ -71,8 +69,7 @@
#define xway_stp_r32(m, reg) __raw_readl(m + reg)
#define xway_stp_w32(m, val, reg) __raw_writel(val, m + reg)
#define xway_stp_w32_mask(m, clear, set, reg) \
- ltq_w32((ltq_r32(m + reg) & ~(clear)) | (set), \
- m + reg)
+ xway_stp_w32(m, (xway_stp_r32(m, reg) & ~(clear)) | (set), reg)
struct xway_stp {
struct gpio_chip gc;
--
2.22.0
^ permalink raw reply related
* Re: [RFC/RFT v3 07/14] clk: meson: g12a: add notifiers to handle cpu clock change
From: Martin Blumenstingl @ 2019-07-02 23:28 UTC (permalink / raw)
To: sboyd, Neil Armstrong
Cc: jbrunet, khilman, linux-arm-kernel, linux-amlogic, linux-kernel,
linux-clk, linux-gpio
In-Reply-To: <20190701091258.3870-8-narmstrong@baylibre.com>
Hi Stephen, Hi Neil,
On Mon, Jul 1, 2019 at 11:13 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> In order to implement clock switching for the CLKID_CPU_CLK and
> CLKID_CPUB_CLK, notifiers are added on specific points of the
> clock tree :
>
> cpu_clk / cpub_clk
> | \- cpu_clk_dyn
> | | \- cpu_clk_premux0
> | | |- cpu_clk_postmux0
> | | | |- cpu_clk_dyn0_div
> | | | \- xtal/fclk_div2/fclk_div3
> | | \- xtal/fclk_div2/fclk_div3
> | \- cpu_clk_premux1
> | |- cpu_clk_postmux1
> | | |- cpu_clk_dyn1_div
> | | \- xtal/fclk_div2/fclk_div3
> | \- xtal/fclk_div2/fclk_div3
> \ sys_pll / sys1_pll
>
> This for each cluster, a single one for G12A, two for G12B.
>
> Each cpu_clk_premux1 tree is marked as read-only and CLK_SET_RATE_NO_REPARENT,
> to be used as "parking" clock in a safe clock frequency.
it seems that this is one case where the "coordinated clocks" feature
would come handy: [0]
Stephen, do you know if those patches stopped in March or if there's
still some ongoing effort to get them ready?
[...]
> -/*
> - * Internal sys pll emulation configuration parameters
> - */
> -static const struct reg_sequence g12a_sys_init_regs[] = {
> - { .reg = HHI_SYS_PLL_CNTL1, .def = 0x00000000 },
> - { .reg = HHI_SYS_PLL_CNTL2, .def = 0x00000000 },
> - { .reg = HHI_SYS_PLL_CNTL3, .def = 0x48681c00 },
> - { .reg = HHI_SYS_PLL_CNTL4, .def = 0x88770290 },
> - { .reg = HHI_SYS_PLL_CNTL5, .def = 0x39272000 },
> - { .reg = HHI_SYS_PLL_CNTL6, .def = 0x56540000 },
> +static const struct pll_mult_range g12a_sys_pll_mult_range = {
> + .min = 128,
> + .max = 250,
> };
>
> static struct clk_regmap g12a_sys_pll_dco = {
> @@ -124,14 +118,15 @@ static struct clk_regmap g12a_sys_pll_dco = {
> .shift = 29,
> .width = 1,
> },
> - .init_regs = g12a_sys_init_regs,
> - .init_count = ARRAY_SIZE(g12a_sys_init_regs),
> + .range = &g12a_sys_pll_mult_range,
Neil, I believe that this should be a separate patch with a
description which explains why we don't need the "init regs" anymore
> },
> .hw.init = &(struct clk_init_data){
> .name = "sys_pll_dco",
> - .ops = &meson_clk_pll_ro_ops,
> + .ops = &meson_clk_pll_ops,
> .parent_names = (const char *[]){ IN_PREFIX "xtal" },
> .num_parents = 1,
> + /* This clock feeds the CPU, avoid disabling it */
> + .flags = CLK_IS_CRITICAL,
maybe we should have a separate patch for making the CPU clock tree
mutable as well
[...]
> +/* This divider uses bit 26 to take change in account */
> +static int g12b_cpub_clk_mux0_div_set_rate(struct clk_hw *hw,
> + unsigned long rate,
> + unsigned long parent_rate)
> +{
> + struct clk_regmap *clk = to_clk_regmap(hw);
> + struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk);
> + unsigned int val;
> + int ret;
> +
> + ret = divider_get_val(rate, parent_rate, div->table, div->width,
> + div->flags);
> + if (ret < 0)
> + return ret;
> +
> + val = (unsigned int)ret << div->shift;
> +
> + regmap_update_bits(clk->map, HHI_SYS_CPUB_CLK_CNTL,
> + SYS_CPU_DYN_ENABLE, SYS_CPU_DYN_ENABLE);
> +
> + return regmap_update_bits(clk->map, div->offset,
> + clk_div_mask(div->width) << div->shift |
> + SYS_CPU_DYN_ENABLE, val);
> +};
the public S922X datasheet doesn't mention bit 26
do I understand the semantics correctly?:
- set SYS_CPU_DYN_ENABLE
- update the divider
- unset SYS_CPU_DYN_ENABLE
too bad it's not a gate which we could model with
CLK_SET_RATE_GATE/CLK_SET_RATE_UNGATE
Martin
[0] https://patchwork.kernel.org/patch/10838949/
^ permalink raw reply
* [PATCH v1 2/2] pinctrl: baytrail: Re-use data structures from pinctrl-intel.h
From: Andy Shevchenko @ 2019-07-03 0:30 UTC (permalink / raw)
To: Mika Westerberg, Linus Walleij, linux-gpio, Hans de Goede; +Cc: Andy Shevchenko
In-Reply-To: <20190703003018.75186-1-andriy.shevchenko@linux.intel.com>
We have some data structures duplicated across the drivers.
Let's deduplicate them by using ones that being provided by
pinctrl-intel.h.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
drivers/pinctrl/intel/pinctrl-baytrail.c | 299 +++++------------------
1 file changed, 60 insertions(+), 239 deletions(-)
diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
index c72d831ca8b6..bfde1c710bd9 100644
--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
+++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
@@ -24,6 +24,8 @@
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
+#include "pinctrl-intel.h"
+
/* memory mapped register offsets */
#define BYT_CONF0_REG 0x000
#define BYT_CONF1_REG 0x004
@@ -98,34 +100,6 @@ struct byt_gpio_pin_context {
u32 val;
};
-struct byt_simple_func_mux {
- const char *name;
- unsigned short func;
-};
-
-struct byt_mixed_func_mux {
- const char *name;
- const unsigned short *func_values;
-};
-
-struct byt_pingroup {
- const char *name;
- const unsigned int *pins;
- size_t npins;
- unsigned short has_simple_funcs;
- union {
- const struct byt_simple_func_mux *simple_funcs;
- const struct byt_mixed_func_mux *mixed_funcs;
- };
- size_t nfuncs;
-};
-
-struct byt_function {
- const char *name;
- const char * const *groups;
- size_t ngroups;
-};
-
struct byt_community {
unsigned int pin_base;
size_t npins;
@@ -133,47 +107,6 @@ struct byt_community {
void __iomem *reg_base;
};
-#define SIMPLE_FUNC(n, f) \
- { \
- .name = (n), \
- .func = (f), \
- }
-#define MIXED_FUNC(n, f) \
- { \
- .name = (n), \
- .func_values = (f), \
- }
-
-#define PIN_GROUP_SIMPLE(n, p, f) \
- { \
- .name = (n), \
- .pins = (p), \
- .npins = ARRAY_SIZE((p)), \
- .has_simple_funcs = 1, \
- { \
- .simple_funcs = (f), \
- }, \
- .nfuncs = ARRAY_SIZE((f)), \
- }
-#define PIN_GROUP_MIXED(n, p, f) \
- { \
- .name = (n), \
- .pins = (p), \
- .npins = ARRAY_SIZE((p)), \
- .has_simple_funcs = 0, \
- { \
- .mixed_funcs = (f), \
- }, \
- .nfuncs = ARRAY_SIZE((f)), \
- }
-
-#define FUNCTION(n, g) \
- { \
- .name = (n), \
- .groups = (g), \
- .ngroups = ARRAY_SIZE((g)), \
- }
-
#define COMMUNITY(p, n, map) \
{ \
.pin_base = (p), \
@@ -185,9 +118,9 @@ struct byt_pinctrl_soc_data {
const char *uid;
const struct pinctrl_pin_desc *pins;
size_t npins;
- const struct byt_pingroup *groups;
+ const struct intel_pingroup *groups;
size_t ngroups;
- const struct byt_function *functions;
+ const struct intel_function *functions;
size_t nfunctions;
const struct byt_community *communities;
size_t ncommunities;
@@ -327,20 +260,11 @@ static const unsigned int byt_score_pins_map[BYT_NGPIO_SCORE] = {
/* SCORE groups */
static const unsigned int byt_score_uart1_pins[] = { 70, 71, 72, 73 };
static const unsigned int byt_score_uart2_pins[] = { 74, 75, 76, 77 };
-static const struct byt_simple_func_mux byt_score_uart_mux[] = {
- SIMPLE_FUNC("uart", 1),
-};
static const unsigned int byt_score_pwm0_pins[] = { 94 };
static const unsigned int byt_score_pwm1_pins[] = { 95 };
-static const struct byt_simple_func_mux byt_score_pwm_mux[] = {
- SIMPLE_FUNC("pwm", 1),
-};
static const unsigned int byt_score_sio_spi_pins[] = { 66, 67, 68, 69 };
-static const struct byt_simple_func_mux byt_score_spi_mux[] = {
- SIMPLE_FUNC("spi", 1),
-};
static const unsigned int byt_score_i2c5_pins[] = { 88, 89 };
static const unsigned int byt_score_i2c6_pins[] = { 90, 91 };
@@ -349,50 +273,29 @@ static const unsigned int byt_score_i2c3_pins[] = { 84, 85 };
static const unsigned int byt_score_i2c2_pins[] = { 82, 83 };
static const unsigned int byt_score_i2c1_pins[] = { 80, 81 };
static const unsigned int byt_score_i2c0_pins[] = { 78, 79 };
-static const struct byt_simple_func_mux byt_score_i2c_mux[] = {
- SIMPLE_FUNC("i2c", 1),
-};
static const unsigned int byt_score_ssp0_pins[] = { 8, 9, 10, 11 };
static const unsigned int byt_score_ssp1_pins[] = { 12, 13, 14, 15 };
static const unsigned int byt_score_ssp2_pins[] = { 62, 63, 64, 65 };
-static const struct byt_simple_func_mux byt_score_ssp_mux[] = {
- SIMPLE_FUNC("ssp", 1),
-};
static const unsigned int byt_score_sdcard_pins[] = {
7, 33, 34, 35, 36, 37, 38, 39, 40, 41,
};
-static const unsigned short byt_score_sdcard_mux_values[] = {
+static const unsigned int byt_score_sdcard_mux_values[] = {
2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
-static const struct byt_mixed_func_mux byt_score_sdcard_mux[] = {
- MIXED_FUNC("sdcard", byt_score_sdcard_mux_values),
-};
static const unsigned int byt_score_sdio_pins[] = { 27, 28, 29, 30, 31, 32 };
-static const struct byt_simple_func_mux byt_score_sdio_mux[] = {
- SIMPLE_FUNC("sdio", 1),
-};
static const unsigned int byt_score_emmc_pins[] = {
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
};
-static const struct byt_simple_func_mux byt_score_emmc_mux[] = {
- SIMPLE_FUNC("emmc", 1),
-};
static const unsigned int byt_score_ilb_lpc_pins[] = {
42, 43, 44, 45, 46, 47, 48, 49, 50,
};
-static const struct byt_simple_func_mux byt_score_lpc_mux[] = {
- SIMPLE_FUNC("lpc", 1),
-};
static const unsigned int byt_score_sata_pins[] = { 0, 1, 2 };
-static const struct byt_simple_func_mux byt_score_sata_mux[] = {
- SIMPLE_FUNC("sata", 1),
-};
static const unsigned int byt_score_plt_clk0_pins[] = { 96 };
static const unsigned int byt_score_plt_clk1_pins[] = { 97 };
@@ -400,70 +303,37 @@ static const unsigned int byt_score_plt_clk2_pins[] = { 98 };
static const unsigned int byt_score_plt_clk3_pins[] = { 99 };
static const unsigned int byt_score_plt_clk4_pins[] = { 100 };
static const unsigned int byt_score_plt_clk5_pins[] = { 101 };
-static const struct byt_simple_func_mux byt_score_plt_clk_mux[] = {
- SIMPLE_FUNC("plt_clk", 1),
-};
static const unsigned int byt_score_smbus_pins[] = { 51, 52, 53 };
-static const struct byt_simple_func_mux byt_score_smbus_mux[] = {
- SIMPLE_FUNC("smbus", 1),
-};
-static const struct byt_pingroup byt_score_groups[] = {
- PIN_GROUP_SIMPLE("uart1_grp",
- byt_score_uart1_pins, byt_score_uart_mux),
- PIN_GROUP_SIMPLE("uart2_grp",
- byt_score_uart2_pins, byt_score_uart_mux),
- PIN_GROUP_SIMPLE("pwm0_grp",
- byt_score_pwm0_pins, byt_score_pwm_mux),
- PIN_GROUP_SIMPLE("pwm1_grp",
- byt_score_pwm1_pins, byt_score_pwm_mux),
- PIN_GROUP_SIMPLE("ssp2_grp",
- byt_score_ssp2_pins, byt_score_pwm_mux),
- PIN_GROUP_SIMPLE("sio_spi_grp",
- byt_score_sio_spi_pins, byt_score_spi_mux),
- PIN_GROUP_SIMPLE("i2c5_grp",
- byt_score_i2c5_pins, byt_score_i2c_mux),
- PIN_GROUP_SIMPLE("i2c6_grp",
- byt_score_i2c6_pins, byt_score_i2c_mux),
- PIN_GROUP_SIMPLE("i2c4_grp",
- byt_score_i2c4_pins, byt_score_i2c_mux),
- PIN_GROUP_SIMPLE("i2c3_grp",
- byt_score_i2c3_pins, byt_score_i2c_mux),
- PIN_GROUP_SIMPLE("i2c2_grp",
- byt_score_i2c2_pins, byt_score_i2c_mux),
- PIN_GROUP_SIMPLE("i2c1_grp",
- byt_score_i2c1_pins, byt_score_i2c_mux),
- PIN_GROUP_SIMPLE("i2c0_grp",
- byt_score_i2c0_pins, byt_score_i2c_mux),
- PIN_GROUP_SIMPLE("ssp0_grp",
- byt_score_ssp0_pins, byt_score_ssp_mux),
- PIN_GROUP_SIMPLE("ssp1_grp",
- byt_score_ssp1_pins, byt_score_ssp_mux),
- PIN_GROUP_MIXED("sdcard_grp",
- byt_score_sdcard_pins, byt_score_sdcard_mux),
- PIN_GROUP_SIMPLE("sdio_grp",
- byt_score_sdio_pins, byt_score_sdio_mux),
- PIN_GROUP_SIMPLE("emmc_grp",
- byt_score_emmc_pins, byt_score_emmc_mux),
- PIN_GROUP_SIMPLE("lpc_grp",
- byt_score_ilb_lpc_pins, byt_score_lpc_mux),
- PIN_GROUP_SIMPLE("sata_grp",
- byt_score_sata_pins, byt_score_sata_mux),
- PIN_GROUP_SIMPLE("plt_clk0_grp",
- byt_score_plt_clk0_pins, byt_score_plt_clk_mux),
- PIN_GROUP_SIMPLE("plt_clk1_grp",
- byt_score_plt_clk1_pins, byt_score_plt_clk_mux),
- PIN_GROUP_SIMPLE("plt_clk2_grp",
- byt_score_plt_clk2_pins, byt_score_plt_clk_mux),
- PIN_GROUP_SIMPLE("plt_clk3_grp",
- byt_score_plt_clk3_pins, byt_score_plt_clk_mux),
- PIN_GROUP_SIMPLE("plt_clk4_grp",
- byt_score_plt_clk4_pins, byt_score_plt_clk_mux),
- PIN_GROUP_SIMPLE("plt_clk5_grp",
- byt_score_plt_clk5_pins, byt_score_plt_clk_mux),
- PIN_GROUP_SIMPLE("smbus_grp",
- byt_score_smbus_pins, byt_score_smbus_mux),
+static const struct intel_pingroup byt_score_groups[] = {
+ PIN_GROUP("uart1_grp", byt_score_uart1_pins, 1),
+ PIN_GROUP("uart2_grp", byt_score_uart2_pins, 1),
+ PIN_GROUP("pwm0_grp", byt_score_pwm0_pins, 1),
+ PIN_GROUP("pwm1_grp", byt_score_pwm1_pins, 1),
+ PIN_GROUP("ssp2_grp", byt_score_ssp2_pins, 1),
+ PIN_GROUP("sio_spi_grp", byt_score_sio_spi_pins, 1),
+ PIN_GROUP("i2c5_grp", byt_score_i2c5_pins, 1),
+ PIN_GROUP("i2c6_grp", byt_score_i2c6_pins, 1),
+ PIN_GROUP("i2c4_grp", byt_score_i2c4_pins, 1),
+ PIN_GROUP("i2c3_grp", byt_score_i2c3_pins, 1),
+ PIN_GROUP("i2c2_grp", byt_score_i2c2_pins, 1),
+ PIN_GROUP("i2c1_grp", byt_score_i2c1_pins, 1),
+ PIN_GROUP("i2c0_grp", byt_score_i2c0_pins, 1),
+ PIN_GROUP("ssp0_grp", byt_score_ssp0_pins, 1),
+ PIN_GROUP("ssp1_grp", byt_score_ssp1_pins, 1),
+ PIN_GROUP("sdcard_grp", byt_score_sdcard_pins, byt_score_sdcard_mux_values),
+ PIN_GROUP("sdio_grp", byt_score_sdio_pins, 1),
+ PIN_GROUP("emmc_grp", byt_score_emmc_pins, 1),
+ PIN_GROUP("lpc_grp", byt_score_ilb_lpc_pins, 1),
+ PIN_GROUP("sata_grp", byt_score_sata_pins, 1),
+ PIN_GROUP("plt_clk0_grp", byt_score_plt_clk0_pins, 1),
+ PIN_GROUP("plt_clk1_grp", byt_score_plt_clk1_pins, 1),
+ PIN_GROUP("plt_clk2_grp", byt_score_plt_clk2_pins, 1),
+ PIN_GROUP("plt_clk3_grp", byt_score_plt_clk3_pins, 1),
+ PIN_GROUP("plt_clk4_grp", byt_score_plt_clk4_pins, 1),
+ PIN_GROUP("plt_clk5_grp", byt_score_plt_clk5_pins, 1),
+ PIN_GROUP("smbus_grp", byt_score_smbus_pins, 1),
};
static const char * const byt_score_uart_groups[] = {
@@ -497,10 +367,9 @@ static const char * const byt_score_gpio_groups[] = {
"sdcard_grp", "sdio_grp", "emmc_grp", "lpc_grp", "sata_grp",
"plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp",
"plt_clk4_grp", "plt_clk5_grp", "smbus_grp",
-
};
-static const struct byt_function byt_score_functions[] = {
+static const struct intel_function byt_score_functions[] = {
FUNCTION("uart", byt_score_uart_groups),
FUNCTION("pwm", byt_score_pwm_groups),
FUNCTION("ssp", byt_score_ssp_groups),
@@ -589,38 +458,30 @@ static const unsigned int byt_sus_pins_map[BYT_NGPIO_SUS] = {
};
static const unsigned int byt_sus_usb_over_current_pins[] = { 19, 20 };
-static const struct byt_simple_func_mux byt_sus_usb_oc_mux[] = {
- SIMPLE_FUNC("usb", 0),
- SIMPLE_FUNC("gpio", 1),
-};
+static const unsigned int byt_sus_usb_over_current_mode_values[] = { 0, 0 };
+static const unsigned int byt_sus_usb_over_current_gpio_mode_values[] = { 1, 1 };
static const unsigned int byt_sus_usb_ulpi_pins[] = {
14, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
};
-static const unsigned short byt_sus_usb_ulpi_mode_values[] = {
+static const unsigned int byt_sus_usb_ulpi_mode_values[] = {
2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
-static const unsigned short byt_sus_usb_ulpi_gpio_mode_values[] = {
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-static const struct byt_mixed_func_mux byt_sus_usb_ulpi_mux[] = {
- MIXED_FUNC("usb", byt_sus_usb_ulpi_mode_values),
- MIXED_FUNC("gpio", byt_sus_usb_ulpi_gpio_mode_values),
+static const unsigned int byt_sus_usb_ulpi_gpio_mode_values[] = {
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
static const unsigned int byt_sus_pcu_spi_pins[] = { 21 };
-static const struct byt_simple_func_mux byt_sus_pcu_spi_mux[] = {
- SIMPLE_FUNC("spi", 0),
- SIMPLE_FUNC("gpio", 1),
-};
+static const unsigned int byt_sus_pcu_spi_mode_values[] = { 0 };
+static const unsigned int byt_sus_pcu_spi_gpio_mode_values[] = { 1 };
-static const struct byt_pingroup byt_sus_groups[] = {
- PIN_GROUP_SIMPLE("usb_oc_grp",
- byt_sus_usb_over_current_pins, byt_sus_usb_oc_mux),
- PIN_GROUP_MIXED("usb_ulpi_grp",
- byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_mux),
- PIN_GROUP_SIMPLE("pcu_spi_grp",
- byt_sus_pcu_spi_pins, byt_sus_pcu_spi_mux),
+static const struct intel_pingroup byt_sus_groups[] = {
+ PIN_GROUP("usb_oc_grp", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_mode_values),
+ PIN_GROUP("usb_ulpi_grp", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_mode_values),
+ PIN_GROUP("pcu_spi_grp", byt_sus_pcu_spi_pins, byt_sus_pcu_spi_mode_values),
+ PIN_GROUP("usb_oc_grp_gpio", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_gpio_mode_values),
+ PIN_GROUP("usb_ulpi_grp_gpio", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_gpio_mode_values),
+ PIN_GROUP("pcu_spi_grp_gpio", byt_sus_pcu_spi_pins, byt_sus_pcu_spi_gpio_mode_values),
};
static const char * const byt_sus_usb_groups[] = {
@@ -628,10 +489,10 @@ static const char * const byt_sus_usb_groups[] = {
};
static const char * const byt_sus_spi_groups[] = { "pcu_spi_grp" };
static const char * const byt_sus_gpio_groups[] = {
- "usb_oc_grp", "usb_ulpi_grp", "pcu_spi_grp",
+ "usb_oc_grp_gpio", "usb_ulpi_grp_gpio", "pcu_spi_grp_gpio",
};
-static const struct byt_function byt_sus_functions[] = {
+static const struct intel_function byt_sus_functions[] = {
FUNCTION("usb", byt_sus_usb_groups),
FUNCTION("spi", byt_sus_spi_groups),
FUNCTION("gpio", byt_sus_gpio_groups),
@@ -811,41 +672,9 @@ static int byt_get_function_groups(struct pinctrl_dev *pctldev,
return 0;
}
-static int byt_get_group_simple_mux(const struct byt_pingroup group,
- const char *func_name,
- unsigned short *func)
-{
- int i;
-
- for (i = 0; i < group.nfuncs; i++) {
- if (!strcmp(group.simple_funcs[i].name, func_name)) {
- *func = group.simple_funcs[i].func;
- return 0;
- }
- }
-
- return 1;
-}
-
-static int byt_get_group_mixed_mux(const struct byt_pingroup group,
- const char *func_name,
- const unsigned short **func)
-{
- int i;
-
- for (i = 0; i < group.nfuncs; i++) {
- if (!strcmp(group.mixed_funcs[i].name, func_name)) {
- *func = group.mixed_funcs[i].func_values;
- return 0;
- }
- }
-
- return 1;
-}
-
static void byt_set_group_simple_mux(struct byt_gpio *vg,
- const struct byt_pingroup group,
- unsigned short func)
+ const struct intel_pingroup group,
+ unsigned int func)
{
unsigned long flags;
int i;
@@ -874,8 +703,8 @@ static void byt_set_group_simple_mux(struct byt_gpio *vg,
}
static void byt_set_group_mixed_mux(struct byt_gpio *vg,
- const struct byt_pingroup group,
- const unsigned short *func)
+ const struct intel_pingroup group,
+ const unsigned int *func)
{
unsigned long flags;
int i;
@@ -907,23 +736,15 @@ static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
unsigned int group_selector)
{
struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
- const struct byt_function func = vg->soc_data->functions[func_selector];
- const struct byt_pingroup group = vg->soc_data->groups[group_selector];
- const unsigned short *mixed_func;
- unsigned short simple_func;
- int ret = 1;
-
- if (group.has_simple_funcs)
- ret = byt_get_group_simple_mux(group, func.name, &simple_func);
- else
- ret = byt_get_group_mixed_mux(group, func.name, &mixed_func);
+ const struct intel_function func = vg->soc_data->functions[func_selector];
+ const struct intel_pingroup group = vg->soc_data->groups[group_selector];
- if (ret)
+ if (group.modes)
+ byt_set_group_mixed_mux(vg, group, group.modes);
+ else if (!strcmp(func.name, "gpio"))
byt_set_group_simple_mux(vg, group, BYT_DEFAULT_GPIO_MUX);
- else if (group.has_simple_funcs)
- byt_set_group_simple_mux(vg, group, simple_func);
else
- byt_set_group_mixed_mux(vg, group, mixed_func);
+ byt_set_group_simple_mux(vg, group, group.mode);
return 0;
}
--
2.20.1
^ permalink raw reply related
* [PATCH v1 1/2] pinctrl: baytrail: Use defined macro instead of magic in byt_get_gpio_mux()
From: Andy Shevchenko @ 2019-07-03 0:30 UTC (permalink / raw)
To: Mika Westerberg, Linus Walleij, linux-gpio, Hans de Goede; +Cc: Andy Shevchenko
By the fact byt_get_gpio_mux() returns a value of mux settings as
it is represented in hardware. Use defined macro instead of magic numbers
to clarify this.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
drivers/pinctrl/intel/pinctrl-baytrail.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
index 18d9ad504194..c72d831ca8b6 100644
--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
+++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
@@ -91,6 +91,7 @@
* does not find a match for the requested function.
*/
#define BYT_DEFAULT_GPIO_MUX 0
+#define BYT_ALTER_GPIO_MUX 1
struct byt_gpio_pin_context {
u32 conf0;
@@ -932,14 +933,14 @@ static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned int offset)
/* SCORE pin 92-93 */
if (!strcmp(vg->soc_data->uid, BYT_SCORE_ACPI_UID) &&
offset >= 92 && offset <= 93)
- return 1;
+ return BYT_ALTER_GPIO_MUX;
/* SUS pin 11-21 */
if (!strcmp(vg->soc_data->uid, BYT_SUS_ACPI_UID) &&
offset >= 11 && offset <= 21)
- return 1;
+ return BYT_ALTER_GPIO_MUX;
- return 0;
+ return BYT_DEFAULT_GPIO_MUX;
}
static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned int offset)
--
2.20.1
^ permalink raw reply related
* Re: [PATCH] Revert "spi: gpio: Don't request CS GPIO in DT use-case"
From: Linus Walleij @ 2019-07-02 19:41 UTC (permalink / raw)
To: Mark Brown; +Cc: linux-spi, open list:GPIO SUBSYSTEM, Andrey Smirnov
In-Reply-To: <CACRpkdbng1M=5BnzFuiubRaqM1Bu4eLxqKvb3fCQuqyKsVcBjg@mail.gmail.com>
On Tue, Jul 2, 2019 at 3:08 PM Linus Walleij <linus.walleij@linaro.org> wrote:
> I am trying to rootcause it, I suspect I was just the first to try this
> on real hardware actually.
Ha! I found it. Only affects active high CS GPIO users.
A nasty one. Sent a patch.
Yours,
Linus Walleij
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox