MFD and GPIO for STA2X11
Subsystems (3)
v2 cover MFD and GPIO for STA2X11
These two patches introduce the multi-function device and GPIO support for the STA2X11 I/O Hub. Core PCI support is already in linux-next.
I sent version 1 on Jan 26th as RFC and got no comments back. This new pair fixes a number of minor details and is rebased to the new linux-next.
This time I Cc'd both patches to all interested parties, (last time MFD people only got MFD and GPIO people only got GPIO), because the relative order must be preserved.
Alessandro Rubini (2):
mfd: Add driver for STA2X11 MFD block
gpio: add STA2X11 GPIO block
arch/x86/include/asm/sta2x11.h | 12 + drivers/gpio/Kconfig | 9 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-sta2x11.c | 443 ++++++++++++++++++++++++++++++++++++ drivers/mfd/Kconfig | 6 + drivers/mfd/Makefile | 1 + drivers/mfd/sta2x11-mfd.c | 470 +++++++++++++++++++++++++++++++++++++++ include/linux/mfd/sta2x11-mfd.h | 324 +++++++++++++++++++++++++++ 8 files changed, 1266 insertions(+), 0 deletions(-) create mode 100644 arch/x86/include/asm/sta2x11.h create mode 100644 drivers/gpio/gpio-sta2x11.c create mode 100644 drivers/mfd/sta2x11-mfd.c create mode 100644 include/linux/mfd/sta2x11-mfd.h
Signature · 1 line
1.7.7.2
PATCH v2 1/2 mfd: Add driver for STA2X11 MFD block
This also introduces <asm/sta2x11.h> to export a function that is already in linux-next, and will increase with other prototypes and constants over time.
--- arch/x86/include/asm/sta2x11.h | 12 + drivers/mfd/Kconfig | 6 + drivers/mfd/Makefile | 1 + drivers/mfd/sta2x11-mfd.c | 470 +++++++++++++++++++++++++++++++++++++++ include/linux/mfd/sta2x11-mfd.h | 324 +++++++++++++++++++++++++++ 5 files changed, 813 insertions(+), 0 deletions(-) create mode 100644 arch/x86/include/asm/sta2x11.h create mode 100644 drivers/mfd/sta2x11-mfd.c create mode 100644 include/linux/mfd/sta2x11-mfd.h
arch/x86/include/asm/sta2x11.h new file +12 -0
@@ -0,0 +1,12 @@ +/* +* Header file for STMicroelectronics ConneXt (STA2X11) IOHub +*/ +#ifndef __ASM_STA2X11_H +#define __ASM_STA2X11_H + +#include <linux/pci.h> + +/* This needs to be called from the MFD to configure its sub-devices */ +struct sta2x11_instance *sta2x11_get_instance (struct pci_dev *pdev); + +#endif /* __ASM_STA2X11_H */
drivers/mfd/Kconfig +6 -0
@@ -830,6 +830,12 @@ config MFD_INTEL_MSIC Passage) chip. This chip embeds audio, battery, GPIO, etc. devices used in Intel Medfield platforms. +config MFD_STA2X11 + bool "STA2X11 multi function device support" + depends on STA2X11 + select MFD_CORE + select GPIO_STA2X11 + endmenu endif
drivers/mfd/Makefile +1 -0
@@ -15,6 +15,7 @@ obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o obj-$(CONFIG_MFD_TI_SSP) += ti-ssp.o +obj-$(CONFIG_MFD_STA2X11) += sta2x11-mfd.o obj-$(CONFIG_MFD_STMPE) += stmpe.o obj-$(CONFIG_STMPE_I2C) += stmpe-i2c.o obj-$(CONFIG_STMPE_SPI) += stmpe-spi.o
drivers/mfd/sta2x11-mfd.c new file +470 -0
470 lines not on this page · raw message
include/linux/mfd/sta2x11-mfd.h new file +324 -0
324 lines not on this page · raw message
Signature · 1 line
1.7.7.2
Re: [PATCH V2 1/2] mfd: Add driver for STA2X11 MFD block
Quoted 5 lines · Alessandro Rubini
+config
MFD_STA2X11
+ bool "STA2X11 multi function device support"
+ depends on STA2X11
+ selectMFD_CORE
+ selectGPIO_STA2X11
Note: this selects a non-existent driver at this point. (OK no big deal.)
include/linux/mfd/sta2x11-mfd.h line 54
Quoted 4 lines
include/linux/mfd/sta2x11-mfd.h new file +4
-0+/* Give names to GPIO pins, like PXA does, taken from the manual */ +#define GPIO0 0 +#define GPIO1 1 +#define GPIO2 2
(...)
These are too general names I think. It should be clear that this is the GPIO number relative to this one controller, so I would prefix them like STA2X11_GPIO0 etc.
Overall the MFD core for STA2X11 is looking pretty good!
Yours,
Linus Walleij
Re: [PATCH V2 1/2] mfd: Add driver for STA2X11 MFD block
In reply to Alessandro RubiniHi Alessandro,
A few minor comments, since it seems you're going to re-spin this one:
drivers/mfd/Kconfig config MFD_INTEL_MSIC · line 837
Quoted 11 lines · Alessandro Rubini
drivers/mfd/Kconfig +5
-0@@ -830,6 +830,12 @@ config MFD_INTEL_MSIC Passage) chip. This chip embeds audio, battery, GPIO, etc. devices used in Intel Medfield platforms. +config MFD_STA2X11 + bool "STA2X11 multi function device support" + depends on STA2X11 + select MFD_CORE + select GPIO_STA2X11
I think it's better to have your GPIO driver depend on MFD_STA2X11. With the above code, you could end up trying to build your GPIO driver with GPIOLIB not being selected.
Quoted 4 lines
drivers/mfd/Kconfig +4
-0+/* + * What follows is the PCI device that hosts the above two pdevs. + * Each logic block is 4kB and they are all consecutive: we use this info. + */
drivers/mfd/Kconfig config MFD_INTEL_MSIC
Quoted 10 lines
drivers/mfd/Kconfig +10
-0+ +/* Bar 0 */ +enum bar0_cells { + GPIO_0 = 0, + GPIO_1, + GPIO_2, + GPIO_3, + SCTL, + SCR, + TIME,
As Linus said, I'd protect that with a namespace.
Quoted 17 lines
drivers/mfd/Kconfig +17
-0+static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev, + const struct pci_device_id *pci_id) +{ + int err, i; + struct sta2x11_gpio_pdata *gpio_data; + + dev_info(&pdev->dev, "%s\n", __func__); + + err = pci_enable_device(pdev); + if (err) { + dev_err(&pdev->dev, "Can't enable device.\n"); + return err; + } + + err = pci_enable_msi(pdev); + if (err) + dev_info(&pdev->dev, "Enable msi failed\n");
drivers/mfd/Kconfig
Quoted 10 lines
drivers/mfd/Kconfig +10
-0+ + /* Read gpio config data as pci device's platform data */ + gpio_data = dev_get_platdata(&pdev->dev); + if (!gpio_data) + dev_warn(&pdev->dev, "no gpio configuration\n"); + +#if 1 + dev_dbg(&pdev->dev, "%s, gpio_data = %p (%p)\n", __func__, + gpio_data, &gpio_data); +#endif
You can get rid of the #if #endif here.
drivers/mfd/Kconfig
Quoted 3 lines
drivers/mfd/Kconfig +3
-0+ dev_dbg(&pdev->dev, "%s, pdev = %p (%p)\n", __func__, + pdev, &pdev); +
Extra line here
Quoted 28 lines
drivers/mfd/Kconfig +28
-0+ /* platform data is the pci device for all of them */ + for (i = 0; i < ARRAY_SIZE(sta2x11_mfd_bar0); i++) { + sta2x11_mfd_bar0[i].pdata_size = sizeof(pdev); + sta2x11_mfd_bar0[i].platform_data = &pdev; + } + sta2x11_mfd_bar1[0].pdata_size = sizeof(pdev); + sta2x11_mfd_bar1[0].platform_data = &pdev; + + /* Record this pdev before mfd_add_devices: their probe looks for it */ + sta2x11_mfd_add(pdev, GFP_ATOMIC); + + + err = mfd_add_devices(&pdev->dev, -1, + sta2x11_mfd_bar0, + ARRAY_SIZE(sta2x11_mfd_bar0), + &pdev->resource[0], + 0); + if (err) { + dev_err(&pdev->dev, "mfd_add_devices[0] failed: %d\n", err); + goto err_disable; + } + + err = mfd_add_devices(&pdev->dev, -1, + sta2x11_mfd_bar1, + ARRAY_SIZE(sta2x11_mfd_bar1), + &pdev->resource[1], + 0); + if (err) {
drivers/mfd/Kconfig
Quoted 10 lines
drivers/mfd/Kconfig +10
-0+ dev_err(&pdev->dev, "mfd_add_devices[1] failed: %d\n", err); + goto err_disable; + } + + return 0; + +err_disable: + pci_disable_device(pdev); + pci_disable_msi(pdev); + /* mfd_remove(pdev); -- it is in an exit section, I can't call it */
Why can't you call mfd_remove_devices() here ?
Cheers,
Samuel.
Signature · 2 lines
Intel Open Source Technology Centre http://oss.intel.com/
Re: [PATCH V2 1/2] mfd: Add driver for STA2X11 MFD block
Quoted 1 line
A few minor comments, since it seems you're going to re-spin this one:
Thanks. Will do. The "#if 1" is clearly an oversight. I should be able to resping it over the weekeend.
/alessandro
PATCH v2 2/2 gpio: add STA2X11 GPIO block
In reply to Alessandro RubiniThis introduces 128 gpio bits (for each PCI device installed) with working interrupt support.
--- drivers/gpio/Kconfig | 9 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-sta2x11.c | 443 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 453 insertions(+), 0 deletions(-) create mode 100644 drivers/gpio/gpio-sta2x11.c
drivers/gpio/Kconfig +9 -0
@@ -149,6 +149,14 @@ config GPIO_PXA help Say yes here to support the PXA GPIO device +config GPIO_STA2X11 + bool "STA2x11/ConneXt GPIO support" + depends on MFD_STA2X11 + select GENERIC_IRQ_CHIP + help + Say yes here to support the STA2x11/ConneXt GPIO device. + The GPIO module has 128 GPIO pins with alternate functions. + config GPIO_XILINX bool "Xilinx GPIO support" depends on PPC_OF || MICROBLAZE
@@ -503,4 +511,5 @@ config GPIO_TPS65910 help Select this option to enable GPIO driver for the TPS65910 chip family. + endif
drivers/gpio/Makefile +1 -0
@@ -47,6 +47,7 @@ obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o obj-$(CONFIG_GPIO_SCH) += gpio-sch.o obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o +obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o
drivers/gpio/gpio-sta2x11.c new file +443 -0
443 lines not on this page · raw message
Signature · 1 line
1.7.7.2
Re: [PATCH V2 2/2] gpio: add STA2X11 GPIO block
Quoted 7 lines · Alessandro Rubini
drivers/gpio/gpio-sta2x11.c new file +7
-0+/* +* Special method: alternate functions and pullup/pulldown. This will +* need to be exported to other drivers, adding a way to retrieve +* the gsta_gpio structure from their own pci device +*/ +void gsta_set_config (struct gsta_gpio *chip,int nr,unsigned cfg) +{
(...)
Quoted 1 line
+ if (cfg ==
PINMUX_TYPE_NONE)
(...)
Quoted 1 line
+ if (cfg ==
PINMUX_TYPE_FUNCTION)
(...)
Quoted 1 line
+ if (cfg ==
PINMUX_TYPE_FUNCTION) {
(...)
Quoted 1 line
+ case
PINMUX_TYPE_OUTPUT_LOW:
(...)
Quoted 1 line
+ case
PINMUX_TYPE_OUTPUT_HIGH:
(...)
Quoted 1 line
+ case
PINMUX_TYPE_INPUT:
(...)
Quoted 1 line
+ case
PINMUX_TYPE_INPUT_PULLUP:
(...)
Quoted 1 line
+ case
PINMUX_TYPE_INPUT_PULLDOWN:
We have created the pin control subsystem to handle things like this. (Muxing and complex control.)
Please create a driver in drivers/pinctrl/pinctrl-sta2x11.c that expose both a pinctrl and a GPIOlib interface. The GPIOlib interface can call into the pin control portions just fine.
We've had some refactoring in the pin control subsystem recently so check linux-next for the latest API. The documentation in Documentation/pinctrl.txt should be pretty uptodate, else tell me!
I'm giving a talk about pin control at ELC tomorrow, mail me if you want a copy of the slides!
Yours,
Linus Walleij
Re: [PATCH V2 2/2] gpio: add STA2X11 GPIO block
Quoted 2 lines
We have created the pin control subsystem to handle things like this. (Muxing and complex control.)
Ok, I'll use it.
Thanks
/alessandro
Re: [PATCH V2 2/2] gpio: add STA2X11 GPIO block
In reply to Linus WalleijQuoted 10 lines
Quoted 1 line
+ if (cfg ==
PINMUX_TYPE_FUNCTION) {(...)
Quoted 1 line
+ case
PINMUX_TYPE_OUTPUT_LOW:(...)
Quoted 1 line
+ case
PINMUX_TYPE_OUTPUT_HIGH:(...)
Quoted 1 line
+ case
PINMUX_TYPE_INPUT:(...)
Quoted 1 line
+ case
PINMUX_TYPE_INPUT_PULLUP:(...)
Quoted 8 lines
Quoted 1 line
+ case
PINMUX_TYPE_INPUT_PULLDOWN:We have created the pin control subsystem to handle things like this. (Muxing and complex control.)
Please create a driver in
drivers/pinctrl/pinctrl-sta2x11.cthat expose both a pinctrl and a GPIOlib interface. The GPIOlib interface can call into the pin control portions just fine.
I'm sorry, after digging in it for a while I'm really lost. This pinctrl file should be there _instead_ of the gpio file or in addition to it? I see tegra has both, but u300 has only one.
Also, this pinctrl depends on CONFIG_EXPERIMENTAL at this point in time. Is it wise the make the whole sta2x11 thing depend on experimental?
Thanks
/alessandro
Re: [PATCH V2 2/2] gpio: add STA2X11 GPIO block
Quoted 15 lines · Alessandro Rubini
Quoted 15 lines
Quoted 1 line
+ if (cfg ==
PINMUX_TYPE_FUNCTION) {(...)
Quoted 1 line
+ case
PINMUX_TYPE_OUTPUT_LOW:(...)
Quoted 1 line
+ case
PINMUX_TYPE_OUTPUT_HIGH:(...)
Quoted 1 line
+ case
PINMUX_TYPE_INPUT:(...)
Quoted 1 line
+ case
PINMUX_TYPE_INPUT_PULLUP:(...)
Quoted 1 line
+ case
PINMUX_TYPE_INPUT_PULLDOWN:We have created the pin control subsystem to handle things like this. (Muxing and complex control.)
Quoted 7 lines
Quoted 3 lines
Please create a driver in
drivers/pinctrl/pinctrl-sta2x11.cthat expose both a pinctrl and a GPIOlib interface. The GPIOlib interface can call into the pin control portions just fine.I'm sorry, after digging in it for a while I'm really lost. This pinctrl file should be there _instead_ of the gpio file or in addition to it? I see tegra has both, but u300 has only one.
Instead. Just expose three interfaces from it:
struct gpio_chip
struct irc_chip (iff it supports IRQs)
struct pinctrl_desc
Quoted 2 lines
Also, this pinctrl depends on
CONFIG_EXPERIMENTALat this point in time. Is it wise the make the whole sta2x11 thing depend on experimental?
Another option is to wait for it to be marked non-experimental and help fixing it up I guess, we've created it due to shortcomings in drivers/gpio...
Yours,
Linus Walleij
Re: [PATCH V2 2/2] gpio: add STA2X11 GPIO block
In reply to Alessandro Rubinidrivers/gpio/gpio-sta2x11.c line 134
Quoted 7 lines · Alessandro Rubini
drivers/gpio/gpio-sta2x11.c new file +7
-0+static void gsta_gpio_setup (struct gsta_gpio *chip)/* called from probe */ +{ + struct gpio_chip *gpio = &chip->gpio; + + /* +* ARCH_NR_GPIOS is currently 256 and dynamic allocation starts +* from the end. However, for compatiility, we need the first
[Nitpick: spelling]
Quoted 6 lines
+ * ConneXt device to start from gpio 0: it's the main chipset
+ * on most boards so documents and drivers assume gpio0..gpio127
+ */
+ static intgpio_base;
+
+gpio->label=dev_name(chip->dev);
Quoted 8 lines
+
gpio->owner=THIS_MODULE;
+gpio->direction_input=gsta_gpio_direction_input;
+gpio->get=gsta_gpio_get;
+gpio->direction_output=gsta_gpio_direction_output;
+gpio->set=gsta_gpio_set;
+gpio->dbg_show= NULL;
+gpio->base=gpio_base;
+gpio->base= 0;
What are you doing here?
It seems like you first use the provided base, then hard code it to zero.
The GPIO pin number space is global and you need to be able to handle the case where several controllers of this kind are plugged in, will you not?
This looks like it assumes you only ever have one card on the system.
Make sure that the global GPIO numberspace is properly handled on these systems, alas I am a bit worried that this may not be that very easy.
Yours,
Linus Walleij
Re: [PATCH V2 2/2] gpio: add STA2X11 GPIO block
Thank Linus for this and the others.
Quoted 1 line
[Nitpick: spelling]
ack
Quoted 4 lines
drivers/gpio/gpio-sta2x11.c line 148
Quoted 2 lines
drivers/gpio/gpio-sta2x11.c new file +2
-0+ gpio->base = gpio_base; + gpio->base =0 ;What are you doing here?
An error. Sorry. the latter line must be removed. I'll resend.
Quoted 3 lines
The GPIO pin number space is global and you need to be able to handle the case where several controllers of this kind are plugged in, will you not?
Yes, I'm pretty careful about this, and it's one of the concerns I have with the code I got. Unfortunately I only have 1 card plugged in a PC (and one standalone system where the sta2x11 is the main chipset and no more chan be plugged). Here I simply made a mistake.
Quoted 3 lines
Make sure that the global GPIO numberspace is properly handled on these systems, alas I am a bit worried that this may not be that very easy.
No, it was not. But, despite tha extra line from earlier code, it should work properly with this code layout.
/alessandro
Re: [PATCH V2 2/2] gpio: add STA2X11 GPIO block
In reply to Alessandro RubiniQuoted 33 lines · Alessandro Rubini
This introduces 128 gpio bits (for each PCI device installed) with working interrupt support.
Signed-off-by Alessandro Rubini <[email protected]>Cc Alan Cox <[email protected]>--- drivers/gpio/Kconfig | 9 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-sta2x11.c | 443 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 453 insertions(+), 0 deletions(-) create mode 100644 drivers/gpio/gpio-sta2x11.cdrivers/gpio/Kconfig +8
-0@@ -149,6 +149,14 @@ config GPIO_PXA help Say yes here to support the PXA GPIO device +config GPIO_STA2X11 + bool "STA2x11/ConneXt GPIO support" + depends on MFD_STA2X11 + select GENERIC_IRQ_CHIP + help + Say yes here to support the STA2x11/ConneXt GPIO device. + The GPIO module has 128 GPIO pins with alternate functions. + config GPIO_XILINX bool "Xilinx GPIO support" depends on PPC_OF || MICROBLAZE
drivers/gpio/Kconfig config GPIO_TPS65910 · line 515
Quoted 5 lines
drivers/gpio/Kconfig +1
-0@@ -503,4 +511,5 @@ config GPIO_TPS65910 help Select this option to enable GPIO driver for the TPS65910 chip family. + endif
Unrelated whitespace change; please remove from patch
Quoted 62 lines
drivers/gpio/Makefile +1
-0@@ -47,6 +47,7 @@ obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o obj-$(CONFIG_GPIO_SCH) += gpio-sch.o obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o +obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.odrivers/gpio/gpio-sta2x11.c new file +44
-0@@ -0,0 +1,443 @@ +/* +* STMicroelectronics ConneXt (STA2X11) GPIO driver +* +* Copyright 2012 ST Microelectronics (Alessandro Rubini) +* Based on gpio-ml-ioh.c, Copyright 2010 OKI Semiconductors Ltd. +* Also based on previous sta2x11 work, Copyright 2011 Wind River Systems, Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/gpio.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/pci.h> +#include <linux/platform_device.h> +#include <linux/mfd/sta2x11-mfd.h> + +struct gsta_regs { +u32 dat;/* 0x00 */ +u32 dats; +u32 datc; +u32 pdis; +u32 dir;/* 0x10 */ +u32 dirs; +u32 dirc; +u32 unused_1c; +u32 afsela;/* 0x20 */ +u32 unused_24[7 ]; +u32 rimsc;/* 0x40 */
drivers/gpio/gpio-sta2x11.c line 54
Quoted 10 lines
drivers/gpio/gpio-sta2x11.c new file +10
-0+u32 fimsc; +u32 is; +u32 ic; +}; + +struct gsta_gpio { +spinlock_t lock; +struct device *dev; +void __iomem *reg_base; +struct gsta_regs *regs[GSTA_NR_BLOCKS ];
__iomem?
Quoted 55 lines
drivers/gpio/gpio-sta2x11.c new file +55
-0+struct gpio_chip gpio; +int irq_base; +/* FIXME: save the whole config here (AF, ...) */ +unsigned irq_type[GSTA_NR_GPIO ]; +}; + +static inline struct gsta_regs __iomem *__regs (struct gsta_gpio *chip,int nr) +{ +return chip->regs[nr /GSTA_GPIO_PER_BLOCK ]; +} + +static inline u32 __bit (int nr) +{ +return 1U << (nr %GSTA_GPIO_PER_BLOCK ); +} + +/* +* gpio methods +*/ + +static void gsta_gpio_set (struct gpio_chip *gpio,unsigned nr,int val) +{ + struct gsta_gpio *chip = container_of(gpio, struct gsta_gpio, gpio); +struct gsta_regs __iomem *regs =__regs (chip, nr); +u32 bit =__bit (nr); + +if (val) +writel (bit, ®s->dats); +else +writel (bit, ®s->datc); +} + +static int gsta_gpio_get (struct gpio_chip *gpio,unsigned nr) +{ + struct gsta_gpio *chip = container_of(gpio, struct gsta_gpio, gpio); +struct gsta_regs __iomem *regs =__regs (chip, nr); +u32 bit =__bit (nr); + +return readl (®s->dat) & bit; +} + +static int gsta_gpio_direction_output (struct gpio_chip *gpio,unsigned nr, +int val) +{ + struct gsta_gpio *chip = container_of(gpio, struct gsta_gpio, gpio); +struct gsta_regs __iomem *regs =__regs (chip, nr); +u32 bit =__bit (nr); + +writel (bit, ®s->dirs); +/* Data register after direction, otherwise pullup/down is selected */ +if (val) +writel (bit, ®s->dats); +else +writel (bit, ®s->datc); +return 0 ;
drivers/gpio/gpio-sta2x11.c line 119
Quoted 10 lines
drivers/gpio/gpio-sta2x11.c new file +10
-0+} + +static int gsta_gpio_direction_input (struct gpio_chip *gpio,unsigned nr) +{ + struct gsta_gpio *chip = container_of(gpio, struct gsta_gpio, gpio); +struct gsta_regs __iomem *regs =__regs (chip, nr); +u32 bit =__bit (nr); + +writel (bit, ®s->dirc); +return 0 ;
These are plain-vanilla gpio accessors. Can you use the gpio-generic.c library?
Quoted 46 lines
drivers/gpio/gpio-sta2x11.c new file +46
-0+} + +static int gsta_gpio_to_irq (struct gpio_chip *gpio,unsigned offset) +{ + struct gsta_gpio *chip = container_of(gpio, struct gsta_gpio, gpio); +return chip->irq_base + offset; +} + +static void gsta_gpio_setup (struct gsta_gpio *chip)/* called from probe */ +{ +struct gpio_chip *gpio = &chip->gpio; + +/* +* ARCH_NR_GPIOS is currently 256 and dynamic allocation starts +* from the end. However, for compatiility, we need the first +* ConneXt device to start from gpio 0: it's the main chipset +* on most boards so documents and drivers assume gpio0..gpio127 +*/ +static int gpio_base; + + gpio->label =dev_name (chip->dev); + gpio->owner =THIS_MODULE ; + gpio->direction_input = gsta_gpio_direction_input; + gpio->get = gsta_gpio_get; + gpio->direction_output = gsta_gpio_direction_output; + gpio->set = gsta_gpio_set; + gpio->dbg_show =NULL ; + gpio->base = gpio_base; + gpio->base =0 ; + gpio->ngpio =GSTA_NR_GPIO ; + gpio->can_sleep =0 ; + gpio->to_irq = gsta_gpio_to_irq; + + +/* +* After the first device, turn to dynamic gpio numbers. +* With ARCH_NR_GPIOS = 256 we can fit for example two steval cards +*/ +if (!gpio_base) + gpio_base =1 ; +} + +/* +* Special method: alternate functions and pullup/pulldown. This will +* need to be exported to other drivers, adding a way to retrieve +* the gsta_gpio structure from their own pci device
drivers/gpio/gpio-sta2x11.c line 175
Quoted 10 lines
drivers/gpio/gpio-sta2x11.c new file +10
-0+*/ +void gsta_set_config (struct gsta_gpio *chip,int nr,unsigned cfg) +{ +struct gsta_regs __iomem *regs =__regs (chip, nr); +unsigned long flags; +u32 bit =__bit (nr); +u32 val; +int err =0 ; + +printk ("%s: %p %i %i\n" , __func__, chip, nr, cfg);
pr_info()
Quoted 52 lines
drivers/gpio/gpio-sta2x11.c new file +52
-0+ +if (cfg ==PINMUX_TYPE_NONE ) +return ; + +/* Alternate function or not? */ +spin_lock_irqsave (&chip->lock, flags); + val =readl (®s->afsela); +if (cfg ==PINMUX_TYPE_FUNCTION ) + val |= bit; +else + val &= ~bit; +writel (val | bit, ®s->afsela); +if (cfg ==PINMUX_TYPE_FUNCTION ) { +spin_unlock_irqrestore (&chip->lock, flags); +return ; + } + +/* not alternate function: set details */ +switch (cfg) { +case PINMUX_TYPE_OUTPUT_LOW : +writel (bit, ®s->dirs); +writel (bit, ®s->datc); +break ; +case PINMUX_TYPE_OUTPUT_HIGH : +writel (bit, ®s->dirs); +writel (bit, ®s->dats); +break ; +case PINMUX_TYPE_INPUT : +writel (bit, ®s->dirc); + val =readl (®s->pdis) | bit; +writel (val, ®s->pdis); +break ; +case PINMUX_TYPE_INPUT_PULLUP : +writel (bit, ®s->dirc); + val =readl (®s->pdis) &~ bit; +writel (val, ®s->pdis); +writel (bit, ®s->dats); +break ; +case PINMUX_TYPE_INPUT_PULLDOWN : +writel (bit, ®s->dirc); + val =readl (®s->pdis) &~ bit; +writel (val, ®s->pdis); +writel (bit, ®s->datc); +break ; +default : + err =1 ; + } +spin_unlock_irqrestore (&chip->lock, flags); +if (err) +pr_err ("%s: chip %p, pin %i, cfg %i is invalid\n" , + __func__, chip, nr, cfg); +}
drivers/gpio/gpio-sta2x11.c line 237
Quoted 10 lines
drivers/gpio/gpio-sta2x11.c new file +10
-0+ +/* +* Irq methods +*/ + +static void gsta_irq_disable (struct irq_data *data) +{ +struct irq_chip_generic *gc =irq_data_get_irq_chip_data (data); +struct gsta_gpio *chip = gc->private; +int nr = data->irq - chip->irq_base;
we have data->hwirq now. Use it. In fact, you should look at using irqdomain to manage the hwirq to linuxirq number mapping for you. irqdomain will be merged for v3.4.
Quoted 129 lines
drivers/gpio/gpio-sta2x11.c new file +129
-0+struct gsta_regs __iomem *regs =__regs (chip, nr); +u32 bit =__bit (nr); +u32 val; +unsigned long flags; + +spin_lock_irqsave (&chip->lock, flags); +if (chip->irq_type[nr] &IRQ_TYPE_EDGE_RISING ) { + val =readl (®s->rimsc) & ~bit; +writel (val, ®s->rimsc); + } +if (chip->irq_type[nr] &IRQ_TYPE_EDGE_FALLING ) { + val =readl (®s->fimsc) & ~bit; +writel (val, ®s->fimsc); + } +spin_unlock_irqrestore (&chip->lock, flags); +return ; +} + +static void gsta_irq_enable (struct irq_data *data) +{ +struct irq_chip_generic *gc =irq_data_get_irq_chip_data (data); +struct gsta_gpio *chip = gc->private; +int nr = data->irq - chip->irq_base; +struct gsta_regs __iomem *regs =__regs (chip, nr); +u32 bit =__bit (nr); +u32 val; +int type; +unsigned long flags; + + type = chip->irq_type[nr]; + +spin_lock_irqsave (&chip->lock, flags); + val =readl (®s->rimsc); +if (type &IRQ_TYPE_EDGE_RISING ) +writel (val | bit, ®s->rimsc); +else +writel (val & ~bit, ®s->rimsc); + val =readl (®s->rimsc); +if (type &IRQ_TYPE_EDGE_FALLING ) +writel (val | bit, ®s->fimsc); +else +writel (val & ~bit, ®s->fimsc); +spin_unlock_irqrestore (&chip->lock, flags); +return ; +} + +static int gsta_irq_type (struct irq_data *d,unsigned int type) +{ +struct irq_chip_generic *gc =irq_data_get_irq_chip_data (d); +struct gsta_gpio *chip = gc->private; +int nr = d->irq - chip->irq_base; + +/* We only support edge interrupts */ +if (!(type & (IRQ_TYPE_EDGE_RISING |IRQ_TYPE_EDGE_FALLING ))) { +pr_debug ("%s: unsupported type 0x%x\n" , __func__, type); +return -EINVAL ; + } + + chip->irq_type[nr] = type;/* used for enable/disable */ + +gsta_irq_enable (d); +return 0 ; +} + +static irqreturn_t gsta_gpio_handler (int irq,void *dev_id) +{ +struct gsta_gpio *chip = dev_id; +struct gsta_regs __iomem *regs; +u32 is; +int i, nr, base; +irqreturn_t ret =IRQ_NONE ; + +for (i =0 ; i <GSTA_NR_BLOCKS ; i++) { + regs = chip->regs[i]; + base = chip->irq_base + i *GSTA_GPIO_PER_BLOCK ; +while ((is =readl (®s->is))) { + nr =__ffs (is); + irq = base + nr; +generic_handle_irq (irq); +writel (1 << nr, ®s->ic); + ret =IRQ_HANDLED ; + } + } +return ret; +} + +static __devinit void gsta_alloc_irq_chip (struct gsta_gpio *chip) +{ +struct irq_chip_generic *gc; +struct irq_chip_type *ct; + + gc =irq_alloc_generic_chip (KBUILD_MODNAME ,1 , chip->irq_base, + chip->reg_base, handle_simple_irq); + gc->private = chip; + ct = gc->chip_types; + + ct->chip.irq_set_type = gsta_irq_type; + ct->chip.irq_disable = gsta_irq_disable; + ct->chip.irq_enable = gsta_irq_enable; + +/* FIXME: this makes at most 32 interrupts. Request 0 by now */ +irq_setup_generic_chip (gc,0 /* IRQ_MSK(GSTA_GPIO_PER_BLOCK) */ ,0 , +IRQ_NOREQUEST |IRQ_NOPROBE ,0 ); + +/* Set up all all 128 interrupts: code from setup_generic_chip */ + { +struct irq_chip_type *ct = gc->chip_types; +int i, j; +for (j =0 ; j <GSTA_NR_GPIO ; j++) { + i = chip->irq_base + j; +irq_set_chip_and_handler (i, &ct->chip, ct->handler); +irq_set_chip_data (i, gc); +irq_modify_status (i,IRQ_NOREQUEST |IRQ_NOPROBE ,0 ); + } + gc->irq_cnt = i - gc->irq_base; + } +} + +/* The platform device used here is instantiated by the MFD device */ +static int __devinit gsta_probe (struct platform_device *dev) +{ +int i, err; +struct pci_dev *pdev; +struct sta2x11_gpio_pdata *gpio_pdata; +struct gsta_gpio *chip; +struct resource *res; + + pdev = *(struct pci_dev **)(dev->dev.platform_data); + gpio_pdata =dev_get_platdata (&pdev->dev);
drivers/gpio/gpio-sta2x11.c line 376
Quoted 10 lines
drivers/gpio/gpio-sta2x11.c new file +10
-0+ +if (gpio_pdata ==NULL ) +dev_err (&dev->dev,"no gpio config\n" ); +printk ("gpio config: %p\n" , gpio_pdata); + + res =platform_get_resource (dev,IORESOURCE_MEM ,0 ); +request_mem_region (res->start,resource_size (res),KBUILD_MODNAME ); + + + chip =kzalloc (sizeof (*chip),GFP_KERNEL );
devm_kzalloc() will make this code simpler (don't need to kfree on error or remove).
drivers/gpio/gpio-sta2x11.c line 379
Quoted 3 lines
drivers/gpio/gpio-sta2x11.c new file +3
-0+ chip->dev = &dev->dev; + chip->reg_base =ioremap (res->start,resource_size (res)); + chip->irq_base =-1 ;
This line is meaningless.
Quoted 10 lines
drivers/gpio/gpio-sta2x11.c new file +10
-0+for (i =0 ; i <GSTA_NR_BLOCKS ; i++) { + chip->regs[i] = chip->reg_base + i *4096 ; +/* disable all irqs */ +writel (0 , &chip->regs[i]->rimsc); +writel (0 , &chip->regs[i]->fimsc); +writel (~0 , &chip->regs[i]->ic); + } +spin_lock_init (&chip->lock); +gsta_gpio_setup (chip); +for (i =0 ; i <GSTA_NR_GPIO ; i++)
drivers/gpio/gpio-sta2x11.c line 399
Quoted 10 lines
drivers/gpio/gpio-sta2x11.c new file +10
-0+gsta_set_config (chip, i, gpio_pdata->pinconfig[i]); + err =gpiochip_add (&chip->gpio); +if (err <0 ) { +dev_err (&dev->dev,"sta2x11 gpio: Can't register (%i)\n" , + -err); +kfree (chip); +return err; + } +/* 384 was used in previous code: be compatible for other drivers */ + err =irq_alloc_descs (-1 ,384 ,GSTA_NR_GPIO ,NUMA_NO_NODE );
That's a lot of irqs. Will they all be used? How do other drivers determine which irq number to use (is it statically assigned, or is there a dynamic mechanism)? If only a portion are used, then the irq_domain linear mapping would be a win here.
Quoted 31 lines
drivers/gpio/gpio-sta2x11.c new file +31
-0+ +if (err <0 ) { +dev_warn (&dev->dev,"sta2x11 gpio: Can't get irq base (%i)\n" , + -err); + goto err_out; + } + chip->irq_base = err; +gsta_alloc_irq_chip (chip); + + err =request_irq (pdev->irq, gsta_gpio_handler, +IRQF_SHARED ,KBUILD_MODNAME , chip); +if (err <0 ) { +dev_err (&dev->dev,"sta2x11 gpio: Can't request irq (%i)\n" , + -err); + goto err_out; + } + +platform_set_drvdata (dev, chip); +return 0 ; + +err_out: +if (chip->irq_base >0 ) +irq_free_descs (chip->irq_base,GSTA_NR_GPIO ); +kfree (chip); +return err; +} + +static struct platform_driver sta2x11_gpio_platform_driver = { + .driver = { + .name ="sta2x11-gpio" , + .owner =THIS_MODULE ,
drivers/gpio/gpio-sta2x11.c line 440
Quoted 10 lines
drivers/gpio/gpio-sta2x11.c new file +10
-0+ }, + .probe = gsta_probe, +}; + +static int __init sta2x11_gpio_init (void ) +{ +return platform_driver_register (&sta2x11_gpio_platform_driver); +} + +module_init (sta2x11_gpio_init);
module_platform_driver()
Quoted 5 lines
drivers/gpio/gpio-sta2x11.c new file +3
-0+ +MODULE_LICENSE ("GPL v2" ); +MODULE_DESCRIPTION ("sta2x11_gpio GPIO driver" );Signature · 1 line
1.7.7.2
Signature · 1 line
email sent from notmuch.vim plugin
Re: [PATCH V2 2/2] gpio: add STA2X11 GPIO block
Thank you Grant for your comments. Agreed with all of them.
Quoted 4 lines
drivers/gpio/gpio-sta2x11.c line 399
Quoted 2 lines
drivers/gpio/gpio-sta2x11.c new file +2
-0+/* 384 was used in previous code: be compatible for other drivers */ + err =irq_alloc_descs (-1 ,384 ,GSTA_NR_GPIO ,NUMA_NO_NODE );That's a lot of irqs. Will they all be used?
384 is the starting point, isn't it? The number is 128. One per gpio pin. We have change-detect for mmc and other stuff that live in high gpio numbers.
Quoted 4 lines
How do other drivers determine which irq number to use (is it statically assigned, or is there a dynamic mechanism)? If only a portion are used, then the
irq_domainlinear mapping would be a win here.
The code I received uses static numbers. The chip is the main chipset in the typical use case, so only one is there even if it is PCI. I also have a PCIe card to use it as slave device, and I'm careful to allow several of them, even if it's not the main use case. Maybe here I fell short. I'm reposting soon, with a full change log.
This "compatibility" is something I need to run the boards with existing code for the parts that are not cleaned up for upstream, yet.
/alessandro