* [PATCH v2 0/3] Add support for PCI mapped devices and rmmod @ 2014-12-10 13:21 Ricardo Ribalda Delgado 2014-12-10 13:21 ` [PATCH v2 1/3] gpio/xilinx: Remove offset property Ricardo Ribalda Delgado ` (2 more replies) 0 siblings, 3 replies; 9+ messages in thread From: Ricardo Ribalda Delgado @ 2014-12-10 13:21 UTC (permalink / raw) To: Linus Walleij, Alexandre Courbot, Michal Simek, Sören Brinkmann, linux-gpio, linux-kernel Cc: Ricardo Ribalda Delgado The main purpose of this patchset is to use the driver on a PCI mapped fpga. This patchset also converts the driver to platform device, so it will support hot plugged devices and rmmod. Changeset: v2 Suggested by Alexandre Courbot <gnurou@gmail.com> Merge 2 and 3 (convert to platform device and implement remove) Ricardo Ribalda Delgado (3): gpio/xilinx: Remove offset property gpio/xilinx: Convert the driver to platform device interface gpio/xilinx: Add support for X86 Arch drivers/gpio/Kconfig | 4 +- drivers/gpio/gpio-xilinx.c | 114 ++++++++++++++++++++++++++++----------------- 2 files changed, 73 insertions(+), 45 deletions(-) -- 2.1.3 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 1/3] gpio/xilinx: Remove offset property 2014-12-10 13:21 [PATCH v2 0/3] Add support for PCI mapped devices and rmmod Ricardo Ribalda Delgado @ 2014-12-10 13:21 ` Ricardo Ribalda Delgado 2014-12-10 14:18 ` Michal Simek 2014-12-10 13:21 ` [PATCH v2 2/3] gpio/xilinx: Convert the driver to platform device interface Ricardo Ribalda Delgado 2014-12-10 13:21 ` [PATCH v2 3/3] gpio/xilinx: Add support for X86 Arch Ricardo Ribalda Delgado 2 siblings, 1 reply; 9+ messages in thread From: Ricardo Ribalda Delgado @ 2014-12-10 13:21 UTC (permalink / raw) To: Linus Walleij, Alexandre Courbot, Michal Simek, Sören Brinkmann, linux-gpio, linux-kernel Cc: Ricardo Ribalda Delgado Instead of calculating the register offset per call, pre-calculate it on probe time. Acked-by: Alexandre Courbot <acourbot@nvidia.com> Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> --- v2: Add Acked-by drivers/gpio/gpio-xilinx.c | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index ba18b06..9483950 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -50,7 +50,6 @@ struct xgpio_instance { struct of_mm_gpio_chip mmchip; u32 gpio_state; u32 gpio_dir; - u32 offset; spinlock_t gpio_lock; }; @@ -65,12 +64,8 @@ struct xgpio_instance { static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct xgpio_instance *chip = - container_of(mm_gc, struct xgpio_instance, mmchip); - void __iomem *regs = mm_gc->regs + chip->offset; - - return !!(xgpio_readreg(regs + XGPIO_DATA_OFFSET) & BIT(gpio)); + return !!(xgpio_readreg(mm_gc->regs + XGPIO_DATA_OFFSET) & BIT(gpio)); } /** @@ -88,7 +83,6 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct xgpio_instance *chip = container_of(mm_gc, struct xgpio_instance, mmchip); - void __iomem *regs = mm_gc->regs; spin_lock_irqsave(&chip->gpio_lock, flags); @@ -98,8 +92,7 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) else chip->gpio_state &= ~BIT(gpio); - xgpio_writereg(regs + chip->offset + XGPIO_DATA_OFFSET, - chip->gpio_state); + xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); spin_unlock_irqrestore(&chip->gpio_lock, flags); } @@ -119,13 +112,12 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct xgpio_instance *chip = container_of(mm_gc, struct xgpio_instance, mmchip); - void __iomem *regs = mm_gc->regs; spin_lock_irqsave(&chip->gpio_lock, flags); /* Set the GPIO bit in shadow register and set direction as input */ chip->gpio_dir |= BIT(gpio); - xgpio_writereg(regs + chip->offset + XGPIO_TRI_OFFSET, chip->gpio_dir); + xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); spin_unlock_irqrestore(&chip->gpio_lock, flags); @@ -148,7 +140,6 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct xgpio_instance *chip = container_of(mm_gc, struct xgpio_instance, mmchip); - void __iomem *regs = mm_gc->regs; spin_lock_irqsave(&chip->gpio_lock, flags); @@ -157,12 +148,11 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) chip->gpio_state |= BIT(gpio); else chip->gpio_state &= ~BIT(gpio); - xgpio_writereg(regs + chip->offset + XGPIO_DATA_OFFSET, - chip->gpio_state); + xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); /* Clear the GPIO bit in shadow register and set direction as output */ chip->gpio_dir &= ~BIT(gpio); - xgpio_writereg(regs + chip->offset + XGPIO_TRI_OFFSET, chip->gpio_dir); + xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); spin_unlock_irqrestore(&chip->gpio_lock, flags); @@ -178,10 +168,8 @@ static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc) struct xgpio_instance *chip = container_of(mm_gc, struct xgpio_instance, mmchip); - xgpio_writereg(mm_gc->regs + chip->offset + XGPIO_DATA_OFFSET, - chip->gpio_state); - xgpio_writereg(mm_gc->regs + chip->offset + XGPIO_TRI_OFFSET, - chip->gpio_dir); + xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); + xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); } /** @@ -247,9 +235,6 @@ static int xgpio_of_probe(struct device_node *np) if (!chip) return -ENOMEM; - /* Add dual channel offset */ - chip->offset = XGPIO_CHANNEL_OFFSET; - /* Update GPIO state shadow register with default value */ of_property_read_u32(np, "xlnx,dout-default-2", &chip->gpio_state); @@ -285,6 +270,10 @@ static int xgpio_of_probe(struct device_node *np) np->full_name, status); return status; } + + /* Add dual channel offset */ + chip->mmchip.regs += XGPIO_CHANNEL_OFFSET; + pr_info("XGpio: %s: dual channel registered, base is %d\n", np->full_name, chip->mmchip.gc.base); } -- 2.1.3 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/3] gpio/xilinx: Remove offset property 2014-12-10 13:21 ` [PATCH v2 1/3] gpio/xilinx: Remove offset property Ricardo Ribalda Delgado @ 2014-12-10 14:18 ` Michal Simek 2014-12-10 14:25 ` Ricardo Ribalda Delgado 0 siblings, 1 reply; 9+ messages in thread From: Michal Simek @ 2014-12-10 14:18 UTC (permalink / raw) To: Ricardo Ribalda Delgado, Linus Walleij, Alexandre Courbot, Michal Simek, Sören Brinkmann, linux-gpio, linux-kernel On 12/10/2014 02:21 PM, Ricardo Ribalda Delgado wrote: > Instead of calculating the register offset per call, pre-calculate it on > probe time. > > Acked-by: Alexandre Courbot <acourbot@nvidia.com> > Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> > --- > > v2: Add Acked-by > > drivers/gpio/gpio-xilinx.c | 33 +++++++++++---------------------- > 1 file changed, 11 insertions(+), 22 deletions(-) > > diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c > index ba18b06..9483950 100644 > --- a/drivers/gpio/gpio-xilinx.c > +++ b/drivers/gpio/gpio-xilinx.c > @@ -50,7 +50,6 @@ struct xgpio_instance { > struct of_mm_gpio_chip mmchip; > u32 gpio_state; > u32 gpio_dir; > - u32 offset; when you remove offset property you should also remove offset from comment above of this structure. > spinlock_t gpio_lock; > }; > > @@ -65,12 +64,8 @@ struct xgpio_instance { > static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) > { > struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); > - struct xgpio_instance *chip = > - container_of(mm_gc, struct xgpio_instance, mmchip); > > - void __iomem *regs = mm_gc->regs + chip->offset; > - > - return !!(xgpio_readreg(regs + XGPIO_DATA_OFFSET) & BIT(gpio)); > + return !!(xgpio_readreg(mm_gc->regs + XGPIO_DATA_OFFSET) & BIT(gpio)); > } > > /** > @@ -88,7 +83,6 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) > struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); > struct xgpio_instance *chip = > container_of(mm_gc, struct xgpio_instance, mmchip); > - void __iomem *regs = mm_gc->regs; > > spin_lock_irqsave(&chip->gpio_lock, flags); > > @@ -98,8 +92,7 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) > else > chip->gpio_state &= ~BIT(gpio); > > - xgpio_writereg(regs + chip->offset + XGPIO_DATA_OFFSET, > - chip->gpio_state); > + xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); > > spin_unlock_irqrestore(&chip->gpio_lock, flags); > } > @@ -119,13 +112,12 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) > struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); > struct xgpio_instance *chip = > container_of(mm_gc, struct xgpio_instance, mmchip); > - void __iomem *regs = mm_gc->regs; > > spin_lock_irqsave(&chip->gpio_lock, flags); > > /* Set the GPIO bit in shadow register and set direction as input */ > chip->gpio_dir |= BIT(gpio); > - xgpio_writereg(regs + chip->offset + XGPIO_TRI_OFFSET, chip->gpio_dir); > + xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); > > spin_unlock_irqrestore(&chip->gpio_lock, flags); > > @@ -148,7 +140,6 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) > struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); > struct xgpio_instance *chip = > container_of(mm_gc, struct xgpio_instance, mmchip); > - void __iomem *regs = mm_gc->regs; > > spin_lock_irqsave(&chip->gpio_lock, flags); > > @@ -157,12 +148,11 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) > chip->gpio_state |= BIT(gpio); > else > chip->gpio_state &= ~BIT(gpio); > - xgpio_writereg(regs + chip->offset + XGPIO_DATA_OFFSET, > - chip->gpio_state); > + xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); > > /* Clear the GPIO bit in shadow register and set direction as output */ > chip->gpio_dir &= ~BIT(gpio); > - xgpio_writereg(regs + chip->offset + XGPIO_TRI_OFFSET, chip->gpio_dir); > + xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); > > spin_unlock_irqrestore(&chip->gpio_lock, flags); > > @@ -178,10 +168,8 @@ static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc) > struct xgpio_instance *chip = > container_of(mm_gc, struct xgpio_instance, mmchip); > > - xgpio_writereg(mm_gc->regs + chip->offset + XGPIO_DATA_OFFSET, > - chip->gpio_state); > - xgpio_writereg(mm_gc->regs + chip->offset + XGPIO_TRI_OFFSET, > - chip->gpio_dir); > + xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); > + xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); > } > > /** > @@ -247,9 +235,6 @@ static int xgpio_of_probe(struct device_node *np) > if (!chip) > return -ENOMEM; > > - /* Add dual channel offset */ > - chip->offset = XGPIO_CHANNEL_OFFSET; > - > /* Update GPIO state shadow register with default value */ > of_property_read_u32(np, "xlnx,dout-default-2", > &chip->gpio_state); > @@ -285,6 +270,10 @@ static int xgpio_of_probe(struct device_node *np) > np->full_name, status); > return status; > } > + > + /* Add dual channel offset */ > + chip->mmchip.regs += XGPIO_CHANNEL_OFFSET; > + > pr_info("XGpio: %s: dual channel registered, base is %d\n", > np->full_name, chip->mmchip.gc.base); > } > Thanks, Michal ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/3] gpio/xilinx: Remove offset property 2014-12-10 14:18 ` Michal Simek @ 2014-12-10 14:25 ` Ricardo Ribalda Delgado 0 siblings, 0 replies; 9+ messages in thread From: Ricardo Ribalda Delgado @ 2014-12-10 14:25 UTC (permalink / raw) To: Michal Simek Cc: Linus Walleij, Alexandre Courbot, Sören Brinkmann, linux-gpio@vger.kernel.org, LKML Hello Michal Thanks for the review I wait for more comments and then I will resend the patchet with this fixed. I guess is fine to add your reviewed-by? Thanks! On Wed, Dec 10, 2014 at 3:18 PM, Michal Simek <michal.simek@xilinx.com> wrote: > On 12/10/2014 02:21 PM, Ricardo Ribalda Delgado wrote: >> Instead of calculating the register offset per call, pre-calculate it on >> probe time. >> >> Acked-by: Alexandre Courbot <acourbot@nvidia.com> >> Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> >> --- >> >> v2: Add Acked-by >> >> drivers/gpio/gpio-xilinx.c | 33 +++++++++++---------------------- >> 1 file changed, 11 insertions(+), 22 deletions(-) >> >> diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c >> index ba18b06..9483950 100644 >> --- a/drivers/gpio/gpio-xilinx.c >> +++ b/drivers/gpio/gpio-xilinx.c >> @@ -50,7 +50,6 @@ struct xgpio_instance { >> struct of_mm_gpio_chip mmchip; >> u32 gpio_state; >> u32 gpio_dir; >> - u32 offset; > > when you remove offset property you should also remove offset from comment > above of this structure. > >> spinlock_t gpio_lock; >> }; >> >> @@ -65,12 +64,8 @@ struct xgpio_instance { >> static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) >> { >> struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); >> - struct xgpio_instance *chip = >> - container_of(mm_gc, struct xgpio_instance, mmchip); >> >> - void __iomem *regs = mm_gc->regs + chip->offset; >> - >> - return !!(xgpio_readreg(regs + XGPIO_DATA_OFFSET) & BIT(gpio)); >> + return !!(xgpio_readreg(mm_gc->regs + XGPIO_DATA_OFFSET) & BIT(gpio)); >> } >> >> /** >> @@ -88,7 +83,6 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) >> struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); >> struct xgpio_instance *chip = >> container_of(mm_gc, struct xgpio_instance, mmchip); >> - void __iomem *regs = mm_gc->regs; >> >> spin_lock_irqsave(&chip->gpio_lock, flags); >> >> @@ -98,8 +92,7 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) >> else >> chip->gpio_state &= ~BIT(gpio); >> >> - xgpio_writereg(regs + chip->offset + XGPIO_DATA_OFFSET, >> - chip->gpio_state); >> + xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); >> >> spin_unlock_irqrestore(&chip->gpio_lock, flags); >> } >> @@ -119,13 +112,12 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) >> struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); >> struct xgpio_instance *chip = >> container_of(mm_gc, struct xgpio_instance, mmchip); >> - void __iomem *regs = mm_gc->regs; >> >> spin_lock_irqsave(&chip->gpio_lock, flags); >> >> /* Set the GPIO bit in shadow register and set direction as input */ >> chip->gpio_dir |= BIT(gpio); >> - xgpio_writereg(regs + chip->offset + XGPIO_TRI_OFFSET, chip->gpio_dir); >> + xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); >> >> spin_unlock_irqrestore(&chip->gpio_lock, flags); >> >> @@ -148,7 +140,6 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) >> struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); >> struct xgpio_instance *chip = >> container_of(mm_gc, struct xgpio_instance, mmchip); >> - void __iomem *regs = mm_gc->regs; >> >> spin_lock_irqsave(&chip->gpio_lock, flags); >> >> @@ -157,12 +148,11 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) >> chip->gpio_state |= BIT(gpio); >> else >> chip->gpio_state &= ~BIT(gpio); >> - xgpio_writereg(regs + chip->offset + XGPIO_DATA_OFFSET, >> - chip->gpio_state); >> + xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); >> >> /* Clear the GPIO bit in shadow register and set direction as output */ >> chip->gpio_dir &= ~BIT(gpio); >> - xgpio_writereg(regs + chip->offset + XGPIO_TRI_OFFSET, chip->gpio_dir); >> + xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); >> >> spin_unlock_irqrestore(&chip->gpio_lock, flags); >> >> @@ -178,10 +168,8 @@ static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc) >> struct xgpio_instance *chip = >> container_of(mm_gc, struct xgpio_instance, mmchip); >> >> - xgpio_writereg(mm_gc->regs + chip->offset + XGPIO_DATA_OFFSET, >> - chip->gpio_state); >> - xgpio_writereg(mm_gc->regs + chip->offset + XGPIO_TRI_OFFSET, >> - chip->gpio_dir); >> + xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); >> + xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); >> } >> >> /** >> @@ -247,9 +235,6 @@ static int xgpio_of_probe(struct device_node *np) >> if (!chip) >> return -ENOMEM; >> >> - /* Add dual channel offset */ >> - chip->offset = XGPIO_CHANNEL_OFFSET; >> - >> /* Update GPIO state shadow register with default value */ >> of_property_read_u32(np, "xlnx,dout-default-2", >> &chip->gpio_state); >> @@ -285,6 +270,10 @@ static int xgpio_of_probe(struct device_node *np) >> np->full_name, status); >> return status; >> } >> + >> + /* Add dual channel offset */ >> + chip->mmchip.regs += XGPIO_CHANNEL_OFFSET; >> + >> pr_info("XGpio: %s: dual channel registered, base is %d\n", >> np->full_name, chip->mmchip.gc.base); >> } >> > > Thanks, > Michal -- Ricardo Ribalda ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 2/3] gpio/xilinx: Convert the driver to platform device interface 2014-12-10 13:21 [PATCH v2 0/3] Add support for PCI mapped devices and rmmod Ricardo Ribalda Delgado 2014-12-10 13:21 ` [PATCH v2 1/3] gpio/xilinx: Remove offset property Ricardo Ribalda Delgado @ 2014-12-10 13:21 ` Ricardo Ribalda Delgado 2014-12-10 14:36 ` Michal Simek 2014-12-10 13:21 ` [PATCH v2 3/3] gpio/xilinx: Add support for X86 Arch Ricardo Ribalda Delgado 2 siblings, 1 reply; 9+ messages in thread From: Ricardo Ribalda Delgado @ 2014-12-10 13:21 UTC (permalink / raw) To: Linus Walleij, Alexandre Courbot, Michal Simek, Sören Brinkmann, linux-gpio, linux-kernel Cc: Ricardo Ribalda Delgado This way we do not need to transverse the device tree manually and we support hot plugged devices. Also Implement remove callback so the driver can be unloaded Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> --- v2: Suggested by Alexandre Courbot <gnurou@gmail.com> Merge convert to platform device and implement remove callback in one patch drivers/gpio/gpio-xilinx.c | 79 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index 9483950..f946d96 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -51,6 +51,11 @@ struct xgpio_instance { u32 gpio_state; u32 gpio_dir; spinlock_t gpio_lock; + bool inited; +}; + +struct xgpio { + struct xgpio_instance port[2]; }; /** @@ -173,24 +178,57 @@ static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc) } /** + * xgpio_remove - Remove method for the GPIO device. + * @pdev: pointer to the platform device + * + * This function remove gpiochips and frees all the allocated resources. + */ +static int xgpio_remove(struct platform_device *pdev) +{ + struct xgpio *xgpio = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < 2; i++) { + if (!xgpio->port[i].inited) + continue; + gpiochip_remove(&xgpio->port[i].mmchip.gc); + + if (i == 1) + xgpio->port[i].mmchip.regs -= XGPIO_CHANNEL_OFFSET; + + iounmap(xgpio->port[i].mmchip.regs); + kfree(xgpio->port[i].mmchip.gc.label); + } + + return 0; +} + +/** * xgpio_of_probe - Probe method for the GPIO device. - * @np: pointer to device tree node + * @pdev: pointer to the platform device * * This function probes the GPIO device in the device tree. It initializes the * driver data structure. It returns 0, if the driver is bound to the GPIO * device, or a negative value if there is an error. */ -static int xgpio_of_probe(struct device_node *np) +static int xgpio_probe(struct platform_device *pdev) { + struct xgpio *xgpio; struct xgpio_instance *chip; int status = 0; + struct device_node *np = pdev->dev.of_node; const u32 *tree_info; u32 ngpio; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) + xgpio = (struct xgpio *) devm_kzalloc(&pdev->dev, sizeof(*xgpio), + GFP_KERNEL); + if (!xgpio) return -ENOMEM; + platform_set_drvdata(pdev, xgpio); + + chip = &xgpio->port[0]; + /* Update GPIO state shadow register with default value */ of_property_read_u32(np, "xlnx,dout-default", &chip->gpio_state); @@ -210,6 +248,7 @@ static int xgpio_of_probe(struct device_node *np) spin_lock_init(&chip->gpio_lock); + chip->mmchip.gc.dev = &pdev->dev; chip->mmchip.gc.direction_input = xgpio_dir_in; chip->mmchip.gc.direction_output = xgpio_dir_out; chip->mmchip.gc.get = xgpio_get; @@ -220,20 +259,18 @@ static int xgpio_of_probe(struct device_node *np) /* Call the OF gpio helper to setup and register the GPIO device */ status = of_mm_gpiochip_add(np, &chip->mmchip); if (status) { - kfree(chip); pr_err("%s: error in probe function with status %d\n", np->full_name, status); return status; } + chip->inited = true; pr_info("XGpio: %s: registered, base is %d\n", np->full_name, chip->mmchip.gc.base); tree_info = of_get_property(np, "xlnx,is-dual", NULL); if (tree_info && be32_to_cpup(tree_info)) { - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) - return -ENOMEM; + chip = &xgpio->port[1]; /* Update GPIO state shadow register with default value */ of_property_read_u32(np, "xlnx,dout-default-2", @@ -255,6 +292,7 @@ static int xgpio_of_probe(struct device_node *np) spin_lock_init(&chip->gpio_lock); + chip->mmchip.gc.dev = &pdev->dev; chip->mmchip.gc.direction_input = xgpio_dir_in; chip->mmchip.gc.direction_output = xgpio_dir_out; chip->mmchip.gc.get = xgpio_get; @@ -265,7 +303,7 @@ static int xgpio_of_probe(struct device_node *np) /* Call the OF gpio helper to setup and register the GPIO dev */ status = of_mm_gpiochip_add(np, &chip->mmchip); if (status) { - kfree(chip); + xgpio_remove(pdev); pr_err("%s: error in probe function with status %d\n", np->full_name, status); return status; @@ -273,6 +311,7 @@ static int xgpio_of_probe(struct device_node *np) /* Add dual channel offset */ chip->mmchip.regs += XGPIO_CHANNEL_OFFSET; + chip->inited = true; pr_info("XGpio: %s: dual channel registered, base is %d\n", np->full_name, chip->mmchip.gc.base); @@ -286,19 +325,19 @@ static const struct of_device_id xgpio_of_match[] = { { /* end of list */ }, }; -static int __init xgpio_init(void) -{ - struct device_node *np; - - for_each_matching_node(np, xgpio_of_match) - xgpio_of_probe(np); +MODULE_DEVICE_TABLE(of, xgpio_of_match); - return 0; -} +static struct platform_driver xgpio_plat_driver = { + .probe = xgpio_probe, + .remove = xgpio_remove, + .driver = { + .name = "gpio-xilinx", + .owner = THIS_MODULE, + .of_match_table = xgpio_of_match, + }, +}; -/* Make sure we get initialized before anyone else tries to use us */ -subsys_initcall(xgpio_init); -/* No exit call at the moment as we cannot unregister of GPIO chips */ +module_platform_driver(xgpio_plat_driver); MODULE_AUTHOR("Xilinx, Inc."); MODULE_DESCRIPTION("Xilinx GPIO driver"); -- 2.1.3 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 2/3] gpio/xilinx: Convert the driver to platform device interface 2014-12-10 13:21 ` [PATCH v2 2/3] gpio/xilinx: Convert the driver to platform device interface Ricardo Ribalda Delgado @ 2014-12-10 14:36 ` Michal Simek 2014-12-10 15:15 ` Ricardo Ribalda Delgado 0 siblings, 1 reply; 9+ messages in thread From: Michal Simek @ 2014-12-10 14:36 UTC (permalink / raw) To: Ricardo Ribalda Delgado, Linus Walleij, Alexandre Courbot, Michal Simek, Sören Brinkmann, linux-gpio, linux-kernel On 12/10/2014 02:21 PM, Ricardo Ribalda Delgado wrote: > This way we do not need to transverse the device tree manually and we > support hot plugged devices. > > Also Implement remove callback so the driver can be unloaded > > Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> > --- > > v2: Suggested by Alexandre Courbot <gnurou@gmail.com> > > Merge convert to platform device and implement remove callback in one patch > > drivers/gpio/gpio-xilinx.c | 79 ++++++++++++++++++++++++++++++++++------------ > 1 file changed, 59 insertions(+), 20 deletions(-) > > diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c > index 9483950..f946d96 100644 > --- a/drivers/gpio/gpio-xilinx.c > +++ b/drivers/gpio/gpio-xilinx.c > @@ -51,6 +51,11 @@ struct xgpio_instance { > u32 gpio_state; > u32 gpio_dir; > spinlock_t gpio_lock; > + bool inited; like before - you should document it. I know it is not proper kernel-doc format but I think you can simple create one more patch before 1/3 and fix kernel-doc format first and then do your changes. btw: this kernel-doc fixup is in xilinx git repo. > +}; > + > +struct xgpio { > + struct xgpio_instance port[2]; > }; > > /** > @@ -173,24 +178,57 @@ static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc) > } > > /** > + * xgpio_remove - Remove method for the GPIO device. > + * @pdev: pointer to the platform device > + * > + * This function remove gpiochips and frees all the allocated resources. > + */ > +static int xgpio_remove(struct platform_device *pdev) > +{ > + struct xgpio *xgpio = platform_get_drvdata(pdev); > + int i; > + > + for (i = 0; i < 2; i++) { > + if (!xgpio->port[i].inited) > + continue; > + gpiochip_remove(&xgpio->port[i].mmchip.gc); > + > + if (i == 1) > + xgpio->port[i].mmchip.regs -= XGPIO_CHANNEL_OFFSET; > + > + iounmap(xgpio->port[i].mmchip.regs); > + kfree(xgpio->port[i].mmchip.gc.label); > + } > + > + return 0; > +} > + > +/** > * xgpio_of_probe - Probe method for the GPIO device. > - * @np: pointer to device tree node > + * @pdev: pointer to the platform device > * > * This function probes the GPIO device in the device tree. It initializes the > * driver data structure. It returns 0, if the driver is bound to the GPIO > * device, or a negative value if there is an error. > */ > -static int xgpio_of_probe(struct device_node *np) > +static int xgpio_probe(struct platform_device *pdev) > { > + struct xgpio *xgpio; > struct xgpio_instance *chip; > int status = 0; > + struct device_node *np = pdev->dev.of_node; > const u32 *tree_info; > u32 ngpio; > > - chip = kzalloc(sizeof(*chip), GFP_KERNEL); > - if (!chip) > + xgpio = (struct xgpio *) devm_kzalloc(&pdev->dev, sizeof(*xgpio), > + GFP_KERNEL); don't need to recast it here. > + if (!xgpio) > return -ENOMEM; > > + platform_set_drvdata(pdev, xgpio); > + > + chip = &xgpio->port[0]; > + > /* Update GPIO state shadow register with default value */ > of_property_read_u32(np, "xlnx,dout-default", &chip->gpio_state); > > @@ -210,6 +248,7 @@ static int xgpio_of_probe(struct device_node *np) > > spin_lock_init(&chip->gpio_lock); > > + chip->mmchip.gc.dev = &pdev->dev; > chip->mmchip.gc.direction_input = xgpio_dir_in; > chip->mmchip.gc.direction_output = xgpio_dir_out; > chip->mmchip.gc.get = xgpio_get; > @@ -220,20 +259,18 @@ static int xgpio_of_probe(struct device_node *np) > /* Call the OF gpio helper to setup and register the GPIO device */ > status = of_mm_gpiochip_add(np, &chip->mmchip); > if (status) { > - kfree(chip); > pr_err("%s: error in probe function with status %d\n", > np->full_name, status); > return status; > } > + chip->inited = true; > > pr_info("XGpio: %s: registered, base is %d\n", np->full_name, > chip->mmchip.gc.base); > > tree_info = of_get_property(np, "xlnx,is-dual", NULL); > if (tree_info && be32_to_cpup(tree_info)) { > - chip = kzalloc(sizeof(*chip), GFP_KERNEL); > - if (!chip) > - return -ENOMEM; > + chip = &xgpio->port[1]; > > /* Update GPIO state shadow register with default value */ > of_property_read_u32(np, "xlnx,dout-default-2", > @@ -255,6 +292,7 @@ static int xgpio_of_probe(struct device_node *np) > > spin_lock_init(&chip->gpio_lock); > > + chip->mmchip.gc.dev = &pdev->dev; > chip->mmchip.gc.direction_input = xgpio_dir_in; > chip->mmchip.gc.direction_output = xgpio_dir_out; > chip->mmchip.gc.get = xgpio_get; > @@ -265,7 +303,7 @@ static int xgpio_of_probe(struct device_node *np) > /* Call the OF gpio helper to setup and register the GPIO dev */ > status = of_mm_gpiochip_add(np, &chip->mmchip); > if (status) { > - kfree(chip); > + xgpio_remove(pdev); > pr_err("%s: error in probe function with status %d\n", > np->full_name, status); > return status; > @@ -273,6 +311,7 @@ static int xgpio_of_probe(struct device_node *np) > > /* Add dual channel offset */ > chip->mmchip.regs += XGPIO_CHANNEL_OFFSET; > + chip->inited = true; > > pr_info("XGpio: %s: dual channel registered, base is %d\n", > np->full_name, chip->mmchip.gc.base); > @@ -286,19 +325,19 @@ static const struct of_device_id xgpio_of_match[] = { > { /* end of list */ }, > }; > > -static int __init xgpio_init(void) > -{ > - struct device_node *np; > - > - for_each_matching_node(np, xgpio_of_match) > - xgpio_of_probe(np); > +MODULE_DEVICE_TABLE(of, xgpio_of_match); > > - return 0; > -} > +static struct platform_driver xgpio_plat_driver = { > + .probe = xgpio_probe, > + .remove = xgpio_remove, > + .driver = { > + .name = "gpio-xilinx", > + .owner = THIS_MODULE, remove this line - it was the part of resent cleanup > + .of_match_table = xgpio_of_match, > + }, > +}; > > -/* Make sure we get initialized before anyone else tries to use us */ > -subsys_initcall(xgpio_init); > -/* No exit call at the moment as we cannot unregister of GPIO chips */ > +module_platform_driver(xgpio_plat_driver); subsys is 4. module_platform is different level that's why you are changing order here. You shouldn't do it. Just keep the same level because some drivers can depend on it. Thanks, Michal ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 2/3] gpio/xilinx: Convert the driver to platform device interface 2014-12-10 14:36 ` Michal Simek @ 2014-12-10 15:15 ` Ricardo Ribalda Delgado 0 siblings, 0 replies; 9+ messages in thread From: Ricardo Ribalda Delgado @ 2014-12-10 15:15 UTC (permalink / raw) To: Michal Simek Cc: Linus Walleij, Alexandre Courbot, Sören Brinkmann, linux-gpio@vger.kernel.org, LKML Agree on all :) Regarding the kernel-doc patch I rather add it after the other changes. Will resend in a second, tell me if you want your reviewed-by or ack-by for any of the 3 patches Thanks! -- Ricardo Ribalda ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 3/3] gpio/xilinx: Add support for X86 Arch 2014-12-10 13:21 [PATCH v2 0/3] Add support for PCI mapped devices and rmmod Ricardo Ribalda Delgado 2014-12-10 13:21 ` [PATCH v2 1/3] gpio/xilinx: Remove offset property Ricardo Ribalda Delgado 2014-12-10 13:21 ` [PATCH v2 2/3] gpio/xilinx: Convert the driver to platform device interface Ricardo Ribalda Delgado @ 2014-12-10 13:21 ` Ricardo Ribalda Delgado 2014-12-10 14:38 ` Michal Simek 2 siblings, 1 reply; 9+ messages in thread From: Ricardo Ribalda Delgado @ 2014-12-10 13:21 UTC (permalink / raw) To: Linus Walleij, Alexandre Courbot, Michal Simek, Sören Brinkmann, linux-gpio, linux-kernel Cc: Ricardo Ribalda Delgado Core can be accessed via PCIe on X86 platform. Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> --- v2: Minor change on title drivers/gpio/Kconfig | 4 ++-- drivers/gpio/gpio-xilinx.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 0959ca9..7f8ba83 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -343,8 +343,8 @@ config GPIO_XGENE here to enable the GFC GPIO functionality. config GPIO_XILINX - bool "Xilinx GPIO support" - depends on PPC_OF || MICROBLAZE || ARCH_ZYNQ + tristate "Xilinx GPIO support" + depends on OF_GPIO && (PPC_OF || MICROBLAZE || ARCH_ZYNQ || ARCH_X86) help Say yes here to support the Xilinx FPGA GPIO device diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index f946d96..5463540 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -30,7 +30,7 @@ #define XGPIO_CHANNEL_OFFSET 0x8 /* Read/Write access to the GPIO registers */ -#ifdef CONFIG_ARCH_ZYNQ +#if defined(CONFIG_ARCH_ZYNQ) || defined(CONFIG_X86) # define xgpio_readreg(offset) readl(offset) # define xgpio_writereg(offset, val) writel(val, offset) #else -- 2.1.3 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 3/3] gpio/xilinx: Add support for X86 Arch 2014-12-10 13:21 ` [PATCH v2 3/3] gpio/xilinx: Add support for X86 Arch Ricardo Ribalda Delgado @ 2014-12-10 14:38 ` Michal Simek 0 siblings, 0 replies; 9+ messages in thread From: Michal Simek @ 2014-12-10 14:38 UTC (permalink / raw) To: Ricardo Ribalda Delgado, Linus Walleij, Alexandre Courbot, Michal Simek, Sören Brinkmann, linux-gpio, linux-kernel On 12/10/2014 02:21 PM, Ricardo Ribalda Delgado wrote: > Core can be accessed via PCIe on X86 platform. > You should also describe also that you are changing that this driver can be used as module. > Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> > --- Thanks, Michal ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2014-12-10 15:15 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-12-10 13:21 [PATCH v2 0/3] Add support for PCI mapped devices and rmmod Ricardo Ribalda Delgado 2014-12-10 13:21 ` [PATCH v2 1/3] gpio/xilinx: Remove offset property Ricardo Ribalda Delgado 2014-12-10 14:18 ` Michal Simek 2014-12-10 14:25 ` Ricardo Ribalda Delgado 2014-12-10 13:21 ` [PATCH v2 2/3] gpio/xilinx: Convert the driver to platform device interface Ricardo Ribalda Delgado 2014-12-10 14:36 ` Michal Simek 2014-12-10 15:15 ` Ricardo Ribalda Delgado 2014-12-10 13:21 ` [PATCH v2 3/3] gpio/xilinx: Add support for X86 Arch Ricardo Ribalda Delgado 2014-12-10 14:38 ` Michal Simek
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).