This patch series does the following:
-Add clock support
-Add interrupt support
-Add support for suspend and resume
-Add remove support
-Add MAINTAINERS fragment
---
Changes in V3:
-Created separate patch to arrange headers in sorting order.
-Updated dt-bindings.
-Created separate patch for Clock changes and runtime resume.
and suspend.
-Created separate patch for spinlock changes.
-Created separate patch for remove support.
-Fixed coverity errors.
-Updated minor review comments.
Changes in V2:
-Added check for return value of platform_get_irq() API.
-Updated code to support rising edge and falling edge.
-Added xgpio_xlate() API to support switch.
-Added MAINTAINERS fragment.
Tested Below scenarios:
-Tested Loop Back.(channel 1.0 connected to channel 2.0)
-Tested External switch(Used DIP switch)
-Tested Cascade scenario(Here gpio controller acting as
an interrupt controller).
---
Srinivas Neeli (9):
gpio: gpio-xilinx: Arrange headers in sorting order
dt-bindings: gpio: gpio-xilinx: Add clk support to xilinx soft gpio IP
gpio: gpio-xilinx: Add clock support
gpio: gpio-xilinx: Reduce spinlock array to single
gpio: gpio-xilinx: Add interrupt support
gpio: gpio-xilinx: Add remove function
gpio: gpio-xilinx: Add support for suspend and resume
gpio: gpio-xilinx: Check return value of of_property_read_u32
MAINTAINERS: add fragment for xilinx GPIO drivers
.../devicetree/bindings/gpio/gpio-xilinx.txt | 2 +
MAINTAINERS | 10 +
drivers/gpio/Kconfig | 2 +
drivers/gpio/gpio-xilinx.c | 398 +++++++++++++++++++--
4 files changed, 390 insertions(+), 22 deletions(-)
--
2.7.4
Adds clock support to the Xilinx GPIO driver.
Signed-off-by: Srinivas Neeli <[email protected]>
---
Chnages in V3:
-Created separate patch for Clock changes.
---
drivers/gpio/gpio-xilinx.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c
index 17a8a8f90d84..99d603bfb6f0 100644
--- a/drivers/gpio/gpio-xilinx.c
+++ b/drivers/gpio/gpio-xilinx.c
@@ -6,6 +6,7 @@
*/
#include <linux/bitops.h>
+#include <linux/clk.h>
#include <linux/errno.h>
#include <linux/gpio/driver.h>
#include <linux/init.h>
@@ -38,6 +39,7 @@
* @gpio_state: GPIO state shadow register
* @gpio_dir: GPIO direction shadow register
* @gpio_lock: Lock used for synchronization
+ * @clk: clock resource for this driver
*/
struct xgpio_instance {
struct gpio_chip gc;
@@ -46,6 +48,7 @@ struct xgpio_instance {
u32 gpio_state[2];
u32 gpio_dir[2];
spinlock_t gpio_lock[2];
+ struct clk *clk;
};
static inline int xgpio_index(struct xgpio_instance *chip, int gpio)
@@ -333,11 +336,25 @@ static int xgpio_probe(struct platform_device *pdev)
return PTR_ERR(chip->regs);
}
+ chip->clk = devm_clk_get_optional(&pdev->dev, NULL);
+ if (IS_ERR(chip->clk)) {
+ if (PTR_ERR(chip->clk) != -EPROBE_DEFER)
+ dev_dbg(&pdev->dev, "Input clock not found\n");
+ return PTR_ERR(chip->clk);
+ }
+
+ status = clk_prepare_enable(chip->clk);
+ if (status < 0) {
+ dev_err(&pdev->dev, "Failed to prepare clk\n");
+ return status;
+ }
+
xgpio_save_regs(chip);
status = devm_gpiochip_add_data(&pdev->dev, &chip->gc, chip);
if (status) {
dev_err(&pdev->dev, "failed to add GPIO chip\n");
+ clk_disable_unprepare(chip->clk);
return status;
}
--
2.7.4
Add support for suspend and resume, pm runtime suspend and resume.
Added free and request calls.
Signed-off-by: Srinivas Neeli <[email protected]>
---
Changes in V3:
-Created new patch for suspend and resume.
---
drivers/gpio/gpio-xilinx.c | 89 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 87 insertions(+), 2 deletions(-)
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c
index 9abef56eca32..48f2a6c894f5 100644
--- a/drivers/gpio/gpio-xilinx.c
+++ b/drivers/gpio/gpio-xilinx.c
@@ -17,6 +17,7 @@
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
/* Register Offset Definitions */
@@ -275,6 +276,39 @@ static void xgpio_save_regs(struct xgpio_instance *chip)
chip->gpio_dir[1]);
}
+static int xgpio_request(struct gpio_chip *chip, unsigned int offset)
+{
+ int ret;
+
+ ret = pm_runtime_get_sync(chip->parent);
+ /*
+ * If the device is already active pm_runtime_get() will return 1 on
+ * success, but gpio_request still needs to return 0.
+ */
+ return ret < 0 ? ret : 0;
+}
+
+static void xgpio_free(struct gpio_chip *chip, unsigned int offset)
+{
+ pm_runtime_put(chip->parent);
+}
+
+static int __maybe_unused xgpio_suspend(struct device *dev)
+{
+ struct xgpio_instance *gpio = dev_get_drvdata(dev);
+ struct irq_data *data = irq_get_irq_data(gpio->irq);
+
+ if (!data) {
+ dev_err(dev, "irq_get_irq_data() failed\n");
+ return -EINVAL;
+ }
+
+ if (!irqd_is_wakeup_set(data))
+ return pm_runtime_force_suspend(dev);
+
+ return 0;
+}
+
/**
* xgpio_irq_ack - Acknowledge a child GPIO interrupt.
* @irq_data: per IRQ and chip data passed down to chip functions
@@ -285,6 +319,46 @@ static void xgpio_irq_ack(struct irq_data *irq_data)
{
}
+static int __maybe_unused xgpio_resume(struct device *dev)
+{
+ struct xgpio_instance *gpio = dev_get_drvdata(dev);
+ struct irq_data *data = irq_get_irq_data(gpio->irq);
+
+ if (!data) {
+ dev_err(dev, "irq_get_irq_data() failed\n");
+ return -EINVAL;
+ }
+
+ if (!irqd_is_wakeup_set(data))
+ return pm_runtime_force_resume(dev);
+
+ return 0;
+}
+
+static int __maybe_unused xgpio_runtime_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct xgpio_instance *gpio = platform_get_drvdata(pdev);
+
+ clk_disable(gpio->clk);
+
+ return 0;
+}
+
+static int __maybe_unused xgpio_runtime_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct xgpio_instance *gpio = platform_get_drvdata(pdev);
+
+ return clk_enable(gpio->clk);
+}
+
+static const struct dev_pm_ops xgpio_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(xgpio_suspend, xgpio_resume)
+ SET_RUNTIME_PM_OPS(xgpio_runtime_suspend,
+ xgpio_runtime_resume, NULL)
+};
+
/**
* xgpio_irq_mask - Write the specified signal of the GPIO device.
* @irq_data: per IRQ and chip data passed down to chip functions
@@ -544,6 +618,8 @@ static int xgpio_probe(struct platform_device *pdev)
chip->gc.of_gpio_n_cells = cells;
chip->gc.get = xgpio_get;
chip->gc.set = xgpio_set;
+ chip->gc.request = xgpio_request;
+ chip->gc.free = xgpio_free;
chip->gc.set_multiple = xgpio_set_multiple;
chip->gc.label = dev_name(&pdev->dev);
@@ -566,6 +642,10 @@ static int xgpio_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Failed to prepare clk\n");
return status;
}
+ pm_runtime_enable(&pdev->dev);
+ status = pm_runtime_get_sync(&pdev->dev);
+ if (status < 0)
+ goto err_unprepare_clk;
xgpio_save_regs(chip);
@@ -590,7 +670,7 @@ static int xgpio_probe(struct platform_device *pdev)
GFP_KERNEL);
if (!girq->parents) {
status = -ENOMEM;
- goto err_unprepare_clk;
+ goto err_pm_put;
}
girq->parents[0] = chip->irq;
girq->default_type = IRQ_TYPE_NONE;
@@ -600,12 +680,16 @@ static int xgpio_probe(struct platform_device *pdev)
status = devm_gpiochip_add_data(&pdev->dev, &chip->gc, chip);
if (status) {
dev_err(&pdev->dev, "failed to add GPIO chip\n");
- goto err_unprepare_clk;
+ goto err_pm_put;
}
+ pm_runtime_put(&pdev->dev);
return 0;
+err_pm_put:
+ pm_runtime_put_sync(&pdev->dev);
err_unprepare_clk:
+ pm_runtime_disable(&pdev->dev);
clk_disable_unprepare(chip->clk);
return status;
}
@@ -623,6 +707,7 @@ static struct platform_driver xgpio_plat_driver = {
.driver = {
.name = "gpio-xilinx",
.of_match_table = xgpio_of_match,
+ .pm = &xgpio_dev_pm_ops,
},
};
--
2.7.4
Added remove function support.
Signed-off-by: Srinivas Neeli <[email protected]>
---
Changes in V3:
-Created new patch for remove function.
---
drivers/gpio/gpio-xilinx.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c
index 855550a06ded..9abef56eca32 100644
--- a/drivers/gpio/gpio-xilinx.c
+++ b/drivers/gpio/gpio-xilinx.c
@@ -453,6 +453,24 @@ static void xgpio_irqhandler(struct irq_desc *desc)
}
/**
+ * xgpio_remove - Remove method for the GPIO device.
+ * @pdev: pointer to the platform device
+ *
+ * This function remove gpiochips and frees all the allocated resources.
+ *
+ * Return: 0 always
+ */
+static int xgpio_remove(struct platform_device *pdev)
+{
+ struct xgpio_instance *gpio = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(gpio->clk);
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+}
+
+/**
* xgpio_of_probe - Probe method for the GPIO device.
* @pdev: pointer to the platform device
*
@@ -601,6 +619,7 @@ MODULE_DEVICE_TABLE(of, xgpio_of_match);
static struct platform_driver xgpio_plat_driver = {
.probe = xgpio_probe,
+ .remove = xgpio_remove,
.driver = {
.name = "gpio-xilinx",
.of_match_table = xgpio_of_match,
--
2.7.4
In two different instances the return value of "of_property_read_u32"
API was neither captured nor checked.
Fixed it by capturing the return value and then checking for any error.
Addresses-Coverity: "check_return"
Signed-off-by: Srinivas Neeli <[email protected]>
---
Changes in V3:
-Created new patch to fix coverity warnings.
---
drivers/gpio/gpio-xilinx.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c
index 48f2a6c894f5..8a5f0a0265e6 100644
--- a/drivers/gpio/gpio-xilinx.c
+++ b/drivers/gpio/gpio-xilinx.c
@@ -569,7 +569,8 @@ static int xgpio_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, chip);
/* Update GPIO state shadow register with default value */
- of_property_read_u32(np, "xlnx,dout-default", &chip->gpio_state[0]);
+ if (of_property_read_u32(np, "xlnx,dout-default", &chip->gpio_state[0]))
+ chip->gpio_state[0] = 0x0;
/* Update GPIO direction shadow register with default value */
if (of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir[0]))
@@ -593,8 +594,9 @@ static int xgpio_probe(struct platform_device *pdev)
if (is_dual) {
/* Update GPIO state shadow register with default value */
- of_property_read_u32(np, "xlnx,dout-default-2",
- &chip->gpio_state[1]);
+ if (of_property_read_u32(np, "xlnx,dout-default-2",
+ &chip->gpio_state[1]))
+ chip->gpio_state[1] = 0x0;
/* Update GPIO direction shadow register with default value */
if (of_property_read_u32(np, "xlnx,tri-default-2",
--
2.7.4
Added entry for xilinx GPIO drivers.
Signed-off-by: Srinivas Neeli <[email protected]>
Acked-by: Shubhrajyoti Datta <[email protected]>
---
Changes in V3:
-None
---
MAINTAINERS | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 87452fca5235..89a7c045a213 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19283,6 +19283,16 @@ S: Maintained
F: Documentation/devicetree/bindings/net/can/xilinx_can.txt
F: drivers/net/can/xilinx_can.c
+XILINX GPIO DRIVER
+M: Shubhrajyoti Datta <[email protected]>
+R: Srinivas Neeli <[email protected]>
+R: Michal Simek <[email protected]>
+S: Maintained
+F: Documentation/devicetree/bindings/gpio/gpio-xilinx.txt
+F: Documentation/devicetree/bindings/gpio/gpio-zynq.txt
+F: drivers/gpio/gpio-xilinx.c
+F: drivers/gpio/gpio-zynq.c
+
XILINX SD-FEC IP CORES
M: Derek Kiernan <[email protected]>
M: Dragan Cvetic <[email protected]>
--
2.7.4
On 12. 11. 20 18:12, Srinivas Neeli wrote:
> This patch series does the following:
> -Add clock support
> -Add interrupt support
> -Add support for suspend and resume
> -Add remove support
> -Add MAINTAINERS fragment
> ---
> Changes in V3:
> -Created separate patch to arrange headers in sorting order.
> -Updated dt-bindings.
> -Created separate patch for Clock changes and runtime resume.
> and suspend.
> -Created separate patch for spinlock changes.
> -Created separate patch for remove support.
> -Fixed coverity errors.
> -Updated minor review comments.
>
> Changes in V2:
> -Added check for return value of platform_get_irq() API.
> -Updated code to support rising edge and falling edge.
> -Added xgpio_xlate() API to support switch.
> -Added MAINTAINERS fragment.
>
> Tested Below scenarios:
> -Tested Loop Back.(channel 1.0 connected to channel 2.0)
> -Tested External switch(Used DIP switch)
> -Tested Cascade scenario(Here gpio controller acting as
> an interrupt controller).
> ---
>
> Srinivas Neeli (9):
> gpio: gpio-xilinx: Arrange headers in sorting order
> dt-bindings: gpio: gpio-xilinx: Add clk support to xilinx soft gpio IP
> gpio: gpio-xilinx: Add clock support
> gpio: gpio-xilinx: Reduce spinlock array to single
> gpio: gpio-xilinx: Add interrupt support
> gpio: gpio-xilinx: Add remove function
> gpio: gpio-xilinx: Add support for suspend and resume
> gpio: gpio-xilinx: Check return value of of_property_read_u32
> MAINTAINERS: add fragment for xilinx GPIO drivers
>
> .../devicetree/bindings/gpio/gpio-xilinx.txt | 2 +
> MAINTAINERS | 10 +
> drivers/gpio/Kconfig | 2 +
> drivers/gpio/gpio-xilinx.c | 398 +++++++++++++++++++--
> 4 files changed, 390 insertions(+), 22 deletions(-)
>
For the whole series.
Acked-by: Michal Simek <[email protected]>
Thanks,
Michal
On Thu, Nov 12, 2020 at 6:13 PM Srinivas Neeli
<[email protected]> wrote:
> Adds clock support to the Xilinx GPIO driver.
>
> Signed-off-by: Srinivas Neeli <[email protected]>
(...)
> + chip->clk = devm_clk_get_optional(&pdev->dev, NULL);
> + if (IS_ERR(chip->clk)) {
> + if (PTR_ERR(chip->clk) != -EPROBE_DEFER)
> + dev_dbg(&pdev->dev, "Input clock not found\n");
> + return PTR_ERR(chip->clk);
> + }
You can now use return dev_err_probe(dev, ret, "failed to get clock\n");
to avoid all the comparing with -EPROBE_DEFER.
Yours,
Linus Walleij
On Wed, Nov 18, 2020 at 12:53 AM Linus Walleij <[email protected]> wrote:
> On Thu, Nov 12, 2020 at 6:13 PM Srinivas Neeli
> <[email protected]> wrote:
>
> > Adds clock support to the Xilinx GPIO driver.
> >
> > Signed-off-by: Srinivas Neeli <[email protected]>
>
> (...)
> > + chip->clk = devm_clk_get_optional(&pdev->dev, NULL);
> > + if (IS_ERR(chip->clk)) {
> > + if (PTR_ERR(chip->clk) != -EPROBE_DEFER)
> > + dev_dbg(&pdev->dev, "Input clock not found\n");
> > + return PTR_ERR(chip->clk);
> > + }
>
> You can now use return dev_err_probe(dev, ret, "failed to get clock\n");
> to avoid all the comparing with -EPROBE_DEFER.
Patch applied anyways, this can be done separately.
Yours,
Linus Walleij
On Thu, Nov 12, 2020 at 6:13 PM Srinivas Neeli
<[email protected]> wrote:
> Added remove function support.
>
> Signed-off-by: Srinivas Neeli <[email protected]>
> ---
> Changes in V3:
> -Created new patch for remove function.
Patch applied despite not applying 4 or 5: this needs to go
in with the clock support.
Yours,
Linus Walleij
Hi Srinivas,
On Thu, Nov 12, 2020 at 6:13 PM Srinivas Neeli
<[email protected]> wrote:
> Add support for suspend and resume, pm runtime suspend and resume.
> Added free and request calls.
>
> Signed-off-by: Srinivas Neeli <[email protected]>
> ---
> Changes in V3:
> -Created new patch for suspend and resume.
(...)
I'm following the idea here I think.
> @@ -544,6 +618,8 @@ static int xgpio_probe(struct platform_device *pdev)
> + pm_runtime_enable(&pdev->dev);
> + status = pm_runtime_get_sync(&pdev->dev);
> + if (status < 0)
> + goto err_unprepare_clk;
Now the clock is enabled a second time. Because
runtime PM kicks in.
Do this instead:
pm_runtime_get_noresume()
pm_runtime_set_active()
pm_runtime_enable()
Now runtime PM knows it is active and will not call
runtime resume and enable the clock a second time.
> + pm_runtime_put(&pdev->dev);
> return 0;
This is right, now pm runtime will gate the clock
until the first GPIO is requested.
> +err_pm_put:
> + pm_runtime_put_sync(&pdev->dev);
> err_unprepare_clk:
> + pm_runtime_disable(&pdev->dev);
> clk_disable_unprepare(chip->clk);
> return status;
Use this on the errorpath instead:
pm_runtime_put_noidle()
pm_runtime_disable()
clk_disable_unprepare();
Now the code will not call runtime suspend to
gate the clock a second time.
Double-check the references to the clock and check
in debugfs that the clock really gets disabled if you're
not using any GPIOs.
Yours,
Linus Walleij
On Thu, Nov 12, 2020 at 6:13 PM Srinivas Neeli
<[email protected]> wrote:
> In two different instances the return value of "of_property_read_u32"
> API was neither captured nor checked.
> Fixed it by capturing the return value and then checking for any error.
>
> Addresses-Coverity: "check_return"
> Signed-off-by: Srinivas Neeli <[email protected]>
Patch applied.
Yours,
Linus Walleij
On Thu, Nov 12, 2020 at 6:13 PM Srinivas Neeli
<[email protected]> wrote:
> Added entry for xilinx GPIO drivers.
>
> Signed-off-by: Srinivas Neeli <[email protected]>
> Acked-by: Shubhrajyoti Datta <[email protected]>
Patch applied.
Yours,
Linus Walleij
On Thu, Nov 12, 2020 at 6:13 PM Srinivas Neeli
<[email protected]> wrote:
> Srinivas Neeli (9):
> gpio: gpio-xilinx: Arrange headers in sorting order
> dt-bindings: gpio: gpio-xilinx: Add clk support to xilinx soft gpio IP
> gpio: gpio-xilinx: Add clock support
> gpio: gpio-xilinx: Reduce spinlock array to single
> gpio: gpio-xilinx: Add interrupt support
> gpio: gpio-xilinx: Add remove function
> gpio: gpio-xilinx: Add support for suspend and resume
> gpio: gpio-xilinx: Check return value of of_property_read_u32
> MAINTAINERS: add fragment for xilinx GPIO drivers
So I applied patches 1, 2, 3, 6, 8, 9 now so you can
focus on developing and resending the remaining patches.
Yours,
Linus Walleij
Hi Linus,
> -----Original Message-----
> From: Linus Walleij <[email protected]>
> Sent: Wednesday, November 18, 2020 6:12 AM
> To: Srinivas Neeli <[email protected]>
> Cc: Bartosz Golaszewski <[email protected]>; Michal Simek
> <[email protected]>; Shubhrajyoti Datta <[email protected]>; Srinivas
> Goud <[email protected]>; Robert Hancock <[email protected]>;
> open list:GPIO SUBSYSTEM <[email protected]>; Linux ARM <linux-
> [email protected]>; [email protected]; git
> <[email protected]>
> Subject: Re: [LINUX PATCH V3 0/9] gpio-xilinx: Update on xilinx gpio driver
>
> On Thu, Nov 12, 2020 at 6:13 PM Srinivas Neeli <[email protected]>
> wrote:
>
> > Srinivas Neeli (9):
>
> > gpio: gpio-xilinx: Arrange headers in sorting order
> > dt-bindings: gpio: gpio-xilinx: Add clk support to xilinx soft gpio IP
> > gpio: gpio-xilinx: Add clock support
> > gpio: gpio-xilinx: Reduce spinlock array to single
> > gpio: gpio-xilinx: Add interrupt support
> > gpio: gpio-xilinx: Add remove function
> > gpio: gpio-xilinx: Add support for suspend and resume
> > gpio: gpio-xilinx: Check return value of of_property_read_u32
> > MAINTAINERS: add fragment for xilinx GPIO drivers
>
> So I applied patches 1, 2, 3, 6, 8, 9 now so you can focus on developing and
> resending the remaining patches.
Will address remaining patches in V4 series.
>
> Yours,
> Linus Walleij