Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1705354 > unrolled thread
| Started by | Michal Simek <michal.simek@xilinx.com> |
|---|---|
| First post | 2017-08-07 13:10 +0200 |
| Last post | 2017-08-07 13:10 +0200 |
| Articles | 7 — 1 participant |
Back to article view | Back to linux.kernel
[PATCH 0/8] Zynq GPIO driver changes Michal Simek <michal.simek@xilinx.com> - 2017-08-07 13:10 +0200
[PATCH 1/8] gpio: zynq: Add support for suspend resume Michal Simek <michal.simek@xilinx.com> - 2017-08-07 13:10 +0200
[PATCH 6/8] gpio: zynq: Fix empty lines in driver Michal Simek <michal.simek@xilinx.com> - 2017-08-07 13:10 +0200
[PATCH 3/8] gpio: zynq: Shift zynq_gpio_init() to subsys_initcall level Michal Simek <michal.simek@xilinx.com> - 2017-08-07 13:10 +0200
[PATCH 2/8] gpio: zynq: Wakeup gpio controller when it is used as IRQ controller Michal Simek <michal.simek@xilinx.com> - 2017-08-07 13:10 +0200
[PATCH 7/8] gpio: zynq: Fix warnings in the driver Michal Simek <michal.simek@xilinx.com> - 2017-08-07 13:10 +0200
[PATCH 8/8] gpio: zynq: Fix driver function parameters alignment Michal Simek <michal.simek@xilinx.com> - 2017-08-07 13:10 +0200
| From | Michal Simek <michal.simek@xilinx.com> |
|---|---|
| Date | 2017-08-07 13:10 +0200 |
| Subject | [PATCH 0/8] Zynq GPIO driver changes |
| Message-ID | <ubO53-7rt-3@gated-at.bofh.it> |
Hi, the patchset contains several patches which adding new functionality to the driver (irq wakeup, suspend/resume) and fixing issue with DATA_RO reg. The rest of changes are fixing kernel-doc and checkpatch warnings. Thanks, Michal Borsodi Petr (1): gpio: zynq: Wakeup gpio controller when it is used as IRQ controller Michal Simek (2): gpio: zynq: Fix empty lines in driver gpio: zynq: Fix driver function parameters alignment Nava kishore Manne (3): gpio: zynq: Shift zynq_gpio_init() to subsys_initcall level gpio: zynq: Fix kernel doc warnings gpio: zynq: Fix warnings in the driver Shubhrajyoti Datta (1): gpio: zynq: Add support for suspend resume Swapna Manupati (1): gpio: zynq: Provided workaround for GPIO drivers/gpio/gpio-zynq.c | 201 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 176 insertions(+), 25 deletions(-) -- 1.9.1
[toc] | [next] | [standalone]
| From | Michal Simek <michal.simek@xilinx.com> |
|---|---|
| Date | 2017-08-07 13:10 +0200 |
| Subject | [PATCH 1/8] gpio: zynq: Add support for suspend resume |
| Message-ID | <ubO53-7rt-13@gated-at.bofh.it> |
| In reply to | #1705354 |
From: Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
Add support for suspend resume. Now that we can lose context across
a suspend/ resume cycle. Add support for the context restore.
Signed-off-by: Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
---
drivers/gpio/gpio-zynq.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 79 insertions(+), 3 deletions(-)
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c
index df0851464006..064033803449 100644
--- a/drivers/gpio/gpio-zynq.c
+++ b/drivers/gpio/gpio-zynq.c
@@ -99,6 +99,17 @@
/* set to differentiate zynq from zynqmp, 0=zynqmp, 1=zynq */
#define ZYNQ_GPIO_QUIRK_IS_ZYNQ BIT(0)
+struct gpio_regs {
+ u32 datamsw[ZYNQMP_GPIO_MAX_BANK];
+ u32 datalsw[ZYNQMP_GPIO_MAX_BANK];
+ u32 dirm[ZYNQMP_GPIO_MAX_BANK];
+ u32 outen[ZYNQMP_GPIO_MAX_BANK];
+ u32 int_en[ZYNQMP_GPIO_MAX_BANK];
+ u32 int_dis[ZYNQMP_GPIO_MAX_BANK];
+ u32 int_type[ZYNQMP_GPIO_MAX_BANK];
+ u32 int_polarity[ZYNQMP_GPIO_MAX_BANK];
+ u32 int_any[ZYNQMP_GPIO_MAX_BANK];
+};
/**
* struct zynq_gpio - gpio device private data structure
* @chip: instance of the gpio_chip
@@ -106,6 +117,7 @@
* @clk: clock resource for this controller
* @irq: interrupt for the GPIO device
* @p_data: pointer to platform data
+ * @context: context registers
*/
struct zynq_gpio {
struct gpio_chip chip;
@@ -113,6 +125,7 @@ struct zynq_gpio {
struct clk *clk;
int irq;
const struct zynq_platform_data *p_data;
+ struct gpio_regs context;
};
/**
@@ -560,14 +573,72 @@ static void zynq_gpio_irqhandler(struct irq_desc *desc)
chained_irq_exit(irqchip, desc);
}
+static void zynq_gpio_save_context(struct zynq_gpio *gpio)
+{
+ unsigned int bank_num;
+
+ for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) {
+ gpio->context.datalsw[bank_num] =
+ readl_relaxed(gpio->base_addr +
+ ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num));
+ gpio->context.datamsw[bank_num] =
+ readl_relaxed(gpio->base_addr +
+ ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num));
+ gpio->context.dirm[bank_num] = readl_relaxed(gpio->base_addr +
+ ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+ gpio->context.int_en[bank_num] = readl_relaxed(gpio->base_addr +
+ ZYNQ_GPIO_INTMASK_OFFSET(bank_num));
+ gpio->context.int_type[bank_num] =
+ readl_relaxed(gpio->base_addr +
+ ZYNQ_GPIO_INTTYPE_OFFSET(bank_num));
+ gpio->context.int_polarity[bank_num] =
+ readl_relaxed(gpio->base_addr +
+ ZYNQ_GPIO_INTPOL_OFFSET(bank_num));
+ gpio->context.int_any[bank_num] =
+ readl_relaxed(gpio->base_addr +
+ ZYNQ_GPIO_INTANY_OFFSET(bank_num));
+ }
+}
+
+static void zynq_gpio_restore_context(struct zynq_gpio *gpio)
+{
+ unsigned int bank_num;
+
+ for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) {
+ writel_relaxed(gpio->context.datalsw[bank_num],
+ gpio->base_addr +
+ ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num));
+ writel_relaxed(gpio->context.datamsw[bank_num],
+ gpio->base_addr +
+ ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num));
+ writel_relaxed(gpio->context.dirm[bank_num],
+ gpio->base_addr +
+ ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+ writel_relaxed(gpio->context.int_en[bank_num],
+ gpio->base_addr +
+ ZYNQ_GPIO_INTEN_OFFSET(bank_num));
+ writel_relaxed(gpio->context.int_type[bank_num],
+ gpio->base_addr +
+ ZYNQ_GPIO_INTTYPE_OFFSET(bank_num));
+ writel_relaxed(gpio->context.int_polarity[bank_num],
+ gpio->base_addr +
+ ZYNQ_GPIO_INTPOL_OFFSET(bank_num));
+ writel_relaxed(gpio->context.int_any[bank_num],
+ gpio->base_addr +
+ ZYNQ_GPIO_INTANY_OFFSET(bank_num));
+ }
+}
static int __maybe_unused zynq_gpio_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
int irq = platform_get_irq(pdev, 0);
struct irq_data *data = irq_get_irq_data(irq);
+ struct zynq_gpio *gpio = platform_get_drvdata(pdev);
- if (!irqd_is_wakeup_set(data))
+ if (!irqd_is_wakeup_set(data)) {
+ zynq_gpio_save_context(gpio);
return pm_runtime_force_suspend(dev);
+ }
return 0;
}
@@ -577,9 +648,14 @@ static int __maybe_unused zynq_gpio_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
int irq = platform_get_irq(pdev, 0);
struct irq_data *data = irq_get_irq_data(irq);
+ struct zynq_gpio *gpio = platform_get_drvdata(pdev);
+ int ret;
- if (!irqd_is_wakeup_set(data))
- return pm_runtime_force_resume(dev);
+ if (!irqd_is_wakeup_set(data)) {
+ ret = pm_runtime_force_resume(dev);
+ zynq_gpio_restore_context(gpio);
+ return ret;
+ }
return 0;
}
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Michal Simek <michal.simek@xilinx.com> |
|---|---|
| Date | 2017-08-07 13:10 +0200 |
| Subject | [PATCH 6/8] gpio: zynq: Fix empty lines in driver |
| Message-ID | <ubO53-7rt-15@gated-at.bofh.it> |
| In reply to | #1705354 |
Remove one additional line and add two new. All are reported by checkpatch.
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
empty
---
drivers/gpio/gpio-zynq.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c
index 573bd8303d5d..2d9f27e34d31 100644
--- a/drivers/gpio/gpio-zynq.c
+++ b/drivers/gpio/gpio-zynq.c
@@ -63,7 +63,6 @@
#define ZYNQ_GPIO_BANK5_PIN_MAX(str) (ZYNQ_GPIO_BANK5_PIN_MIN(str) + \
ZYNQ##str##_GPIO_BANK5_NGPIO - 1)
-
/* Register offsets for the GPIO device */
/* LSW Mask & Data -WO */
#define ZYNQ_GPIO_DATA_LSW_OFFSET(BANK) (0x000 + (8 * BANK))
@@ -115,6 +114,7 @@ struct gpio_regs {
u32 int_polarity[ZYNQMP_GPIO_MAX_BANK];
u32 int_any[ZYNQMP_GPIO_MAX_BANK];
};
+
/**
* struct zynq_gpio - gpio device private data structure
* @chip: instance of the gpio_chip
@@ -700,6 +700,7 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio)
ZYNQ_GPIO_INTANY_OFFSET(bank_num));
}
}
+
static int __maybe_unused zynq_gpio_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Michal Simek <michal.simek@xilinx.com> |
|---|---|
| Date | 2017-08-07 13:10 +0200 |
| Subject | [PATCH 3/8] gpio: zynq: Shift zynq_gpio_init() to subsys_initcall level |
| Message-ID | <ubO54-7rt-17@gated-at.bofh.it> |
| In reply to | #1705354 |
From: Nava kishore Manne <nava.manne@xilinx.com>
In general situation on-SoC GPIO controller drivers should be probed
after pinctrl/pinmux controller driver, because on-SoC GPIOs utilize a
pin/pad as a resource provided and controlled by pinctrl subsystem.
GPIO must come after pinctrl as gpios may need to mux pins....etc
Looking at Xilinx SoC series pinctrl drivers, zynq*_pinctrl_init()
functions are called at arch_initcall init levels,
so the change of initcall level for gpio-zynq driver from
postcore_initcall to subsys_initcall level is sufficient. Also note
that the most of GPIO controller drivers settled at subsys_initcall
level.
If pinctrl subsystem manages pads with GPIO functions, the change is
needed to avoid unwanted driver probe deferrals during kernel boot.
Signed-off-by: Nava kishore Manne <navam@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
---
drivers/gpio/gpio-zynq.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c
index 5198fa6e016a..bcf11f0ef5c3 100644
--- a/drivers/gpio/gpio-zynq.c
+++ b/drivers/gpio/gpio-zynq.c
@@ -929,7 +929,7 @@ static int __init zynq_gpio_init(void)
{
return platform_driver_register(&zynq_gpio_driver);
}
-postcore_initcall(zynq_gpio_init);
+subsys_initcall(zynq_gpio_init);
static void __exit zynq_gpio_exit(void)
{
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Michal Simek <michal.simek@xilinx.com> |
|---|---|
| Date | 2017-08-07 13:10 +0200 |
| Subject | [PATCH 2/8] gpio: zynq: Wakeup gpio controller when it is used as IRQ controller |
| Message-ID | <ubO54-7rt-27@gated-at.bofh.it> |
| In reply to | #1705354 |
From: Borsodi Petr <Petr.Borsodi@i.cz>
There is a problem with GPIO driver when used as IRQ controller.
It is not working because the module is sleeping (clock is disabled).
The patch enables clocks when IP is used as IRQ controller.
Signed-off-by: Borsodi Petr <Petr.Borsodi@i.cz>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
---
drivers/gpio/gpio-zynq.c | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c
index 064033803449..5198fa6e016a 100644
--- a/drivers/gpio/gpio-zynq.c
+++ b/drivers/gpio/gpio-zynq.c
@@ -11,6 +11,7 @@
#include <linux/bitops.h>
#include <linux/clk.h>
+#include <linux/gpio.h>
#include <linux/gpio/driver.h>
#include <linux/init.h>
#include <linux/interrupt.h>
@@ -20,6 +21,8 @@
#include <linux/pm_runtime.h>
#include <linux/of.h>
+#include "gpiolib.h"
+
#define DRIVER_NAME "zynq-gpio"
/* Maximum banks */
@@ -498,6 +501,38 @@ static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on)
return 0;
}
+static int zynq_gpio_irq_request_resources(struct irq_data *d)
+{
+ struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+ int ret;
+
+ if (!try_module_get(chip->gpiodev->owner))
+ return -ENODEV;
+
+ ret = pm_runtime_get_sync(chip->parent);
+ if (ret < 0) {
+ module_put(chip->gpiodev->owner);
+ return ret;
+ }
+
+ if (gpiochip_lock_as_irq(chip, d->hwirq)) {
+ chip_err(chip, "unable to lock HW IRQ %lu for IRQ\n", d->hwirq);
+ pm_runtime_put(chip->parent);
+ module_put(chip->gpiodev->owner);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void zynq_gpio_irq_release_resources(struct irq_data *d)
+{
+ struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+
+ gpiochip_unlock_as_irq(chip, d->hwirq);
+ pm_runtime_put(chip->parent);
+ module_put(chip->gpiodev->owner);
+}
+
/* irq chip descriptor */
static struct irq_chip zynq_gpio_level_irqchip = {
.name = DRIVER_NAME,
@@ -507,6 +542,8 @@ static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on)
.irq_unmask = zynq_gpio_irq_unmask,
.irq_set_type = zynq_gpio_set_irq_type,
.irq_set_wake = zynq_gpio_set_wake,
+ .irq_request_resources = zynq_gpio_irq_request_resources,
+ .irq_release_resources = zynq_gpio_irq_release_resources,
.flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED |
IRQCHIP_MASK_ON_SUSPEND,
};
@@ -519,6 +556,8 @@ static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on)
.irq_unmask = zynq_gpio_irq_unmask,
.irq_set_type = zynq_gpio_set_irq_type,
.irq_set_wake = zynq_gpio_set_wake,
+ .irq_request_resources = zynq_gpio_irq_request_resources,
+ .irq_release_resources = zynq_gpio_irq_release_resources,
.flags = IRQCHIP_MASK_ON_SUSPEND,
};
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Michal Simek <michal.simek@xilinx.com> |
|---|---|
| Date | 2017-08-07 13:10 +0200 |
| Subject | [PATCH 7/8] gpio: zynq: Fix warnings in the driver |
| Message-ID | <ubO54-7rt-29@gated-at.bofh.it> |
| In reply to | #1705354 |
From: Nava kishore Manne <nava.manne@xilinx.com>
This patch fixes the below warning
-->Block comments should align the * on each line.
-->suspect code indent for conditional statements.
-->Prefer 'unsigned int' to bare use of 'unsigned'
Signed-off-by: Nava kishore Manne <navam@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
---
drivers/gpio/gpio-zynq.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c
index 2d9f27e34d31..26653bf89e58 100644
--- a/drivers/gpio/gpio-zynq.c
+++ b/drivers/gpio/gpio-zynq.c
@@ -198,10 +198,10 @@ static inline void zynq_gpio_get_bank_pin(unsigned int pin_num,
for (bank = 0; bank < gpio->p_data->max_bank; bank++) {
if ((pin_num >= gpio->p_data->bank_min[bank]) &&
(pin_num <= gpio->p_data->bank_max[bank])) {
- *bank_num = bank;
- *bank_pin_num = pin_num -
- gpio->p_data->bank_min[bank];
- return;
+ *bank_num = bank;
+ *bank_pin_num = pin_num -
+ gpio->p_data->bank_min[bank];
+ return;
}
}
@@ -751,7 +751,7 @@ static int __maybe_unused zynq_gpio_runtime_resume(struct device *dev)
return clk_prepare_enable(gpio->clk);
}
-static int zynq_gpio_request(struct gpio_chip *chip, unsigned offset)
+static int zynq_gpio_request(struct gpio_chip *chip, unsigned int offset)
{
int ret;
@@ -764,7 +764,7 @@ static int zynq_gpio_request(struct gpio_chip *chip, unsigned offset)
return ret < 0 ? ret : 0;
}
-static void zynq_gpio_free(struct gpio_chip *chip, unsigned offset)
+static void zynq_gpio_free(struct gpio_chip *chip, unsigned int offset)
{
pm_runtime_put(chip->parent);
}
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Michal Simek <michal.simek@xilinx.com> |
|---|---|
| Date | 2017-08-07 13:10 +0200 |
| Subject | [PATCH 8/8] gpio: zynq: Fix driver function parameters alignment |
| Message-ID | <ubO54-7rt-31@gated-at.bofh.it> |
| In reply to | #1705354 |
Fix function parameters alignment reported by checkpatch.
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
---
drivers/gpio/gpio-zynq.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c
index 26653bf89e58..97b53e557c15 100644
--- a/drivers/gpio/gpio-zynq.c
+++ b/drivers/gpio/gpio-zynq.c
@@ -197,7 +197,7 @@ static inline void zynq_gpio_get_bank_pin(unsigned int pin_num,
for (bank = 0; bank < gpio->p_data->max_bank; bank++) {
if ((pin_num >= gpio->p_data->bank_min[bank]) &&
- (pin_num <= gpio->p_data->bank_max[bank])) {
+ (pin_num <= gpio->p_data->bank_max[bank])) {
*bank_num = bank;
*bank_pin_num = pin_num -
gpio->p_data->bank_min[bank];
@@ -313,7 +313,7 @@ static int zynq_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
* as inputs.
*/
if (zynq_gpio_is_zynq(gpio) && bank_num == 0 &&
- (bank_pin_num == 7 || bank_pin_num == 8))
+ (bank_pin_num == 7 || bank_pin_num == 8))
return -EINVAL;
/* clear the bit in direction mode reg to set the pin as input */
@@ -514,13 +514,14 @@ static int zynq_gpio_set_irq_type(struct irq_data *irq_data, unsigned int type)
writel_relaxed(int_any,
gpio->base_addr + ZYNQ_GPIO_INTANY_OFFSET(bank_num));
- if (type & IRQ_TYPE_LEVEL_MASK) {
+ if (type & IRQ_TYPE_LEVEL_MASK)
irq_set_chip_handler_name_locked(irq_data,
- &zynq_gpio_level_irqchip, handle_fasteoi_irq, NULL);
- } else {
+ &zynq_gpio_level_irqchip,
+ handle_fasteoi_irq, NULL);
+ else
irq_set_chip_handler_name_locked(irq_data,
- &zynq_gpio_edge_irqchip, handle_level_irq, NULL);
- }
+ &zynq_gpio_edge_irqchip,
+ handle_level_irq, NULL);
return 0;
}
@@ -772,7 +773,7 @@ static void zynq_gpio_free(struct gpio_chip *chip, unsigned int offset)
static const struct dev_pm_ops zynq_gpio_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(zynq_gpio_suspend, zynq_gpio_resume)
SET_RUNTIME_PM_OPS(zynq_gpio_runtime_suspend,
- zynq_gpio_runtime_resume, NULL)
+ zynq_gpio_runtime_resume, NULL)
};
static const struct zynq_platform_data zynqmp_gpio_def = {
--
1.9.1
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web