* [PATCH] IBM GPIO driver for PowerPC 4xx is back from the dead
@ 2006-09-29 7:46 Jean-Baptiste Maneyrol
2006-09-29 16:42 ` Eugene Surovegin
0 siblings, 1 reply; 5+ messages in thread
From: Jean-Baptiste Maneyrol @ 2006-09-29 7:46 UTC (permalink / raw)
To: linuxppc-embedded
Here is a patch for linux 2.6.18 that makes come back the old ibm gpio
driver from 2.6.10.
It is mainly useful for compatibility with old linux 2.4 from Montavista
I think, because direct memory access seems the new way to go.
Signed-off-by: Jean-Baptiste Maneyrol
<jean-baptiste.maneyrol@teamlog.com>
Jean-Baptiste Maneyrol
Teamlog - France
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] IBM GPIO driver for PowerPC 4xx is back from the dead
2006-09-29 7:46 [PATCH] IBM GPIO driver for PowerPC 4xx is back from the dead Jean-Baptiste Maneyrol
@ 2006-09-29 16:42 ` Eugene Surovegin
0 siblings, 0 replies; 5+ messages in thread
From: Eugene Surovegin @ 2006-09-29 16:42 UTC (permalink / raw)
To: Jean-Baptiste Maneyrol; +Cc: linuxppc-embedded
On Fri, Sep 29, 2006 at 09:46:04AM +0200, Jean-Baptiste Maneyrol wrote:
> Here is a patch for linux 2.6.18 that makes come back the old ibm gpio
> driver from 2.6.10.
>
> It is mainly useful for compatibility with old linux 2.4 from Montavista
> I think, because direct memory access seems the new way to go.
In my opinion it should stay dead. And no, direct memory access isn't
a way to go - how are you gonna provide synchronization in this case?
Think about different processes mucking with GPIO registers.
I think such low-level functionality should never be exported to the
user-space in the first place. If your user-space needs such access
make it explicit through procfs/sysfs (e.g.
/proc/sys/dev/my_board/reset_that_device for GPIO pin wired to some
chip reset) or just make a specific driver for your hardware.
--
Eugene
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH] IBM GPIO driver for PowerPC 4xx is back from the dead
@ 2006-09-29 8:29 Jean-Baptiste Maneyrol
2006-09-29 9:06 ` Arnd Bergmann
0 siblings, 1 reply; 5+ messages in thread
From: Jean-Baptiste Maneyrol @ 2006-09-29 8:29 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 346 bytes --]
Here is a patch for linux 2.6.18 that makes come back the old ibm gpio
driver from 2.6.10.
It is mainly useful for compatibility with old linux 2.4 from Montavista
I think, because direct memory access seems the new way to go.
Signed-off-by: Jean-Baptiste Maneyrol
<jean-baptiste.maneyrol@teamlog.com>
Jean-Baptiste Maneyrol
Teamlog - France
[-- Attachment #2: ibm_gpio.patch --]
[-- Type: text/x-patch, Size: 12617 bytes --]
diff -Naur linux-2.6.18_gpio/drivers/char/ibm_gpio.c tlgate_gpio/drivers/char/ibm_gpio.c
--- linux-2.6.18_gpio/drivers/char/ibm_gpio.c 1970-01-01 01:00:00.000000000 +0100
+++ tlgate_gpio/drivers/char/ibm_gpio.c 2006-09-28 16:46:42.000000000 +0200
@@ -0,0 +1,349 @@
+/*
+ * FILE NAME ibm_gpio.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ * API for IBM PowerPC 4xx GPIO device.
+ * Driver for IBM PowerPC 4xx GPIO device.
+ *
+ * Armin Kuster akuster@pacbell.net
+ * Sept, 2001
+ *
+ * Orignial driver
+ * Author: MontaVista Software, Inc. <source@mvista.com>
+ * Frank Rowand <frank_rowand@mvista.com>
+ * Debbie Chu <debbie_chu@mvista.com>
+ *
+ * Copyright 2000,2001,2002 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * TODO: devfs
+ *
+ * Version: 02/01/12 - Armin
+ * converted to ocp and using ioremap
+ *
+ * 1.2 02/21/01 - Armin
+ * minor compiler warning fixes
+ *
+ * 1.3 02/22/01 - Armin
+ * added apm
+ *
+ * 1.4 05/07/02 - Armin/David Mueller
+ * coverted to core_ocp[];
+ *
+ * 1.5 05/25/02 - Armin
+ * name change from *_driver to *_dev
+ *
+ * 1.6 06/04/02 - Matt Porter
+ * ioremap paddr. Comment as 4xx generic driver.
+ * Fix header to be userland safe and locate in
+ * an accessible area. Add ioctl to configure
+ * multiplexed GPIO pins.
+ *
+ * 1.7 07/25/02 - Armin
+ * added CPM to enable/disable in init/exit
+ *
+ */
+
+#define VUFX "07.25.02"
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>
+#include <asm/ibm_gpio.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ocp.h>
+#include <asm/ibm4xx.h>
+
+struct miscdevice ibm_gpio_miscdev;
+static struct gpio_regs *gpiop;
+
+int
+ibm_gpio_config(__u32 device, __u32 mask, __u32 data)
+{
+ u32 cfg_reg;
+
+ if (device != 0)
+ return -ENXIO;
+
+#ifdef CONFIG_40x
+#ifdef DCRN_CHCR0
+ /*
+ * PPC405 uses CPC0_CR0 to select multiplexed GPIO pins.
+ */
+ cfg_reg = mfdcr(DCRN_CHCR0);
+ cfg_reg = (cfg_reg & ~mask) | (data & mask);
+ mtdcr(DCRN_CHCR0, cfg_reg);
+#endif
+#elif CONFIG_440GP
+ /*
+ * PPC440GP uses CPC0_GPIO to select multiplexed GPIO pins.
+ */
+ cfg_reg = mfdcr(DCRN_CPC0_GPIO);
+ cfg_reg = (cfg_reg & ~mask) | (data & mask);
+ mtdcr(DCRN_CPC0_GPIO, cfg_reg);
+#elif CONFIG_440GX
+ /*
+ * PPC440GX uses SDR0_PFC0 to select multiplexed GPIO pins
+ */
+ cfg_reg = SDR_READ(DCRN_SDR_PFC0);
+ cfg_reg = (cfg_reg & ~mask) | (data & mask);
+ SDR_WRITE(DCRN_SDR_PFC0, cfg_reg);
+#else
+#error This driver is only supported on PPC40x and PPC440 CPUs
+#endif
+
+ return 0;
+}
+
+int
+ibm_gpio_tristate(__u32 device, __u32 mask, __u32 data)
+{
+ if (device != 0)
+ return -ENXIO;
+ gpiop->tcr = (gpiop->tcr & ~mask) | (data & mask);
+ return 0;
+}
+
+int
+ibm_gpio_open_drain(__u32 device, __u32 mask, __u32 data)
+{
+ if (device != 0)
+ return -ENXIO;
+ gpiop->odr = (gpiop->odr & ~mask) | (data & mask);
+
+ return 0;
+}
+
+int
+ibm_gpio_in(__u32 device, __u32 mask, volatile __u32 * data)
+{
+ if (device != 0)
+ return -ENXIO;
+ gpiop->tcr = gpiop->tcr & ~mask;
+ eieio();
+
+ /*
+ ** If the previous state was OUT, and gpiop->ir is read once, then the
+ ** data that was being OUTput will be read. One way to get the right
+ ** data is to read gpiop->ir twice.
+ */
+
+ *data = gpiop->ir;
+ *data = gpiop->ir & mask;
+ eieio();
+ return 0;
+}
+
+int
+ibm_gpio_out(__u32 device, __u32 mask, __u32 data)
+{
+ if (device != 0)
+ return -ENXIO;
+ gpiop->or = (gpiop->or & ~mask) | (data & mask);
+ eieio();
+ gpiop->tcr = gpiop->tcr | mask;
+ eieio();
+ return 0;
+}
+
+static int
+ibm_gpio_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int
+ibm_gpio_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int
+ibm_gpio_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ static struct ibm_gpio_ioctl_data ioctl_data;
+ int status;
+
+ switch (cmd) {
+ case IBMGPIO_IN:
+ if (copy_from_user(&ioctl_data,
+ (struct ibm_gpio_ioctl_data *) arg,
+ sizeof (ioctl_data))) {
+ return -EFAULT;
+ }
+
+ status = ibm_gpio_in(ioctl_data.device,
+ ioctl_data.mask, &ioctl_data.data);
+ if (status != 0)
+ return status;
+
+ if (copy_to_user((struct ibm_gpio_ioctl_data *) arg,
+ &ioctl_data, sizeof (ioctl_data))) {
+ return -EFAULT;
+ }
+
+ break;
+
+ case IBMGPIO_OUT:
+ if (copy_from_user(&ioctl_data,
+ (struct ibm_gpio_ioctl_data *) arg,
+ sizeof (ioctl_data))) {
+ return -EFAULT;
+ }
+
+ return ibm_gpio_out(ioctl_data.device,
+ ioctl_data.mask, ioctl_data.data);
+
+ break;
+
+ case IBMGPIO_OPEN_DRAIN:
+ if (copy_from_user(&ioctl_data,
+ (struct ibm_gpio_ioctl_data *) arg,
+ sizeof (ioctl_data))) {
+ return -EFAULT;
+ }
+
+ return ibm_gpio_open_drain(ioctl_data.device,
+ ioctl_data.mask, ioctl_data.data);
+
+ break;
+
+ case IBMGPIO_TRISTATE:
+ if (copy_from_user(&ioctl_data,
+ (struct ibm_gpio_ioctl_data *) arg,
+ sizeof (ioctl_data)))
+ return -EFAULT;
+
+ return ibm_gpio_tristate(ioctl_data.device,
+ ioctl_data.mask, ioctl_data.data);
+
+ break;
+
+ case IBMGPIO_CFG:
+ if (copy_from_user(&ioctl_data,
+ (struct ibm_gpio_ioctl_data *) arg,
+ sizeof (ioctl_data)))
+ return -EFAULT;
+
+ return ibm_gpio_config(ioctl_data.device,
+ ioctl_data.mask, ioctl_data.data);
+
+ break;
+
+ default:
+ return -ENOIOCTLCMD;
+
+ }
+ return 0;
+}
+
+static struct file_operations ibm_gpio_fops = {
+ .owner = THIS_MODULE,
+ .ioctl = ibm_gpio_ioctl,
+ .open = ibm_gpio_open,
+ .release = ibm_gpio_release,
+};
+
+static int __init
+ibm_gpio_probe(struct ocp_device *ocp)
+{
+ ibm_gpio_miscdev.minor = GPIO_MINOR;
+ ibm_gpio_miscdev.name = ocp->name;
+ ibm_gpio_miscdev.fops = &ibm_gpio_fops;
+ misc_register(&ibm_gpio_miscdev);
+
+ if (!request_mem_region(ocp->def->paddr, sizeof(struct gpio_regs), "ibm_gpio"))
+ return -EBUSY;
+
+ gpiop = (struct gpio_regs *) ioremap(ocp->def->paddr,
+ sizeof(struct gpio_regs));
+ if (!gpiop) {
+ release_mem_region(ocp->def->paddr, sizeof(struct gpio_regs));
+ return -ENOMEM;
+ }
+
+ printk("GPIO #%d at 0x%lx\n", ocp->def->index,
+ (unsigned long) gpiop);
+
+ return 0;
+}
+
+static void __exit
+ibm_gpio_remove(struct ocp_device *ocp)
+{
+ misc_deregister(&ibm_gpio_miscdev);
+
+ iounmap(gpiop);
+ gpiop = NULL;
+
+ release_mem_region(ocp->def->paddr, sizeof(struct gpio_regs));
+}
+
+static struct ocp_device_id ibm_gpio_ids[] __devinitdata =
+{
+ { .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_GPIO },
+ { .vendor = OCP_VENDOR_INVALID }
+};
+
+MODULE_DEVICE_TABLE(ocp, ibm_gpio_ids);
+
+static struct ocp_driver ibm_gpio_driver =
+{
+ .name = "ibm_gpio",
+ .id_table = ibm_gpio_ids,
+ .probe = ibm_gpio_probe,
+ .remove = __devexit_p(ibm_gpio_remove),
+#if defined(CONFIG_PM)
+ .suspend = NULL,
+ .resume = NULL,
+#endif
+};
+
+static int __init
+ibm_gpio_init(void)
+{
+ printk("IBM GPIO driver version %s\n", VUFX);
+ return ocp_register_driver(&ibm_gpio_driver);
+}
+
+static void __exit
+ibm_gpio_exit(void)
+{
+ ocp_unregister_driver(&ibm_gpio_driver);
+}
+
+module_init(ibm_gpio_init);
+module_exit(ibm_gpio_exit);
+
+EXPORT_SYMBOL(ibm_gpio_tristate);
+EXPORT_SYMBOL(ibm_gpio_open_drain);
+EXPORT_SYMBOL(ibm_gpio_in);
+EXPORT_SYMBOL(ibm_gpio_out);
+
+MODULE_LICENSE("GPL");
diff -Naur linux-2.6.18_gpio/drivers/char/Kconfig tlgate_gpio/drivers/char/Kconfig
--- linux-2.6.18_gpio/drivers/char/Kconfig 2006-09-28 16:47:53.000000000 +0200
+++ tlgate_gpio/drivers/char/Kconfig 2006-09-28 16:50:15.000000000 +0200
@@ -936,6 +936,15 @@
To compile this driver as a module, choose M here: the
module will be called mwave.
+config IBM_GPIO
+ tristate "IBM PowerPC 4xx GPIO Support"
+ depends on IBM_OCP
+ help
+ Give userspace access to the GPIO pins on the PowerPC
+ 4xx processors.
+
+ If compiled as a module, it will be called ibm_gpio.
+
config SCx200_GPIO
tristate "NatSemi SCx200 GPIO Support"
depends on SCx200
diff -Naur linux-2.6.18_gpio/drivers/char/Makefile tlgate_gpio/drivers/char/Makefile
--- linux-2.6.18_gpio/drivers/char/Makefile 2006-09-28 16:47:57.000000000 +0200
+++ tlgate_gpio/drivers/char/Makefile 2006-09-28 16:46:42.000000000 +0200
@@ -81,6 +81,7 @@
obj-$(CONFIG_PPDEV) += ppdev.o
obj-$(CONFIG_NWBUTTON) += nwbutton.o
obj-$(CONFIG_NWFLASH) += nwflash.o
+obj-$(CONFIG_IBM_GPIO) += ibm_gpio.o
obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o
obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o
diff -Naur linux-2.6.18_gpio/include/asm-ppc/ibm_gpio.h tlgate_gpio/include/asm-ppc/ibm_gpio.h
--- linux-2.6.18_gpio/include/asm-ppc/ibm_gpio.h 1970-01-01 01:00:00.000000000 +0100
+++ tlgate_gpio/include/asm-ppc/ibm_gpio.h 2006-09-28 16:47:09.000000000 +0200
@@ -0,0 +1,71 @@
+/*
+ * FILE NAME ibm_ocp_gpio.h
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Generic gpio.
+ *
+ * Armin Kuster akuster@pacbell.net
+ * Sept, 2001
+ *
+ * Orignial driver
+ * Author: MontaVista Software, Inc. <source@mvista.com>
+ * Frank Rowand <frank_rowand@mvista.com>
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __IBM_OCP_GPIO_H
+#define __IBM_OCP_GPIO_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#ifdef __KERNEL__
+
+typedef struct gpio_regs {
+ u32 or;
+ u32 tcr;
+ u32 pad[4];
+ u32 odr;
+ u32 ir;
+} gpio_t;
+
+#define GPIO_MINOR 185
+
+#endif /* __KERNEL__ */
+
+struct ibm_gpio_ioctl_data {
+ __u32 device;
+ __u32 mask;
+ __u32 data;
+};
+
+#define IBMGPIO_IOCTL_BASE 'Z'
+
+#define IBMGPIO_IN _IOWR(IBMGPIO_IOCTL_BASE, 0, struct ibm_gpio_ioctl_data)
+#define IBMGPIO_OUT _IOW (IBMGPIO_IOCTL_BASE, 1, struct ibm_gpio_ioctl_data)
+#define IBMGPIO_OPEN_DRAIN _IOW (IBMGPIO_IOCTL_BASE, 2, struct ibm_gpio_ioctl_data)
+#define IBMGPIO_TRISTATE _IOW (IBMGPIO_IOCTL_BASE, 3, struct ibm_gpio_ioctl_data)
+#define IBMGPIO_CFG _IOW (IBMGPIO_IOCTL_BASE, 4, struct ibm_gpio_ioctl_data)
+
+#endif
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] IBM GPIO driver for PowerPC 4xx is back from the dead
2006-09-29 8:29 Jean-Baptiste Maneyrol
@ 2006-09-29 9:06 ` Arnd Bergmann
2006-09-29 16:46 ` Eugene Surovegin
0 siblings, 1 reply; 5+ messages in thread
From: Arnd Bergmann @ 2006-09-29 9:06 UTC (permalink / raw)
To: linuxppc-embedded; +Cc: Jean-Baptiste Maneyrol
On Friday 29 September 2006 10:29, Jean-Baptiste Maneyrol wrote:
> diff -Naur linux-2.6.18_gpio/drivers/char/ibm_gpio.c tlgate_gpio/drivers/=
char/ibm_gpio.c
> --- linux-2.6.18_gpio/drivers/char/ibm_gpio.c=A0=A0=A01970-01-01 01:00:00=
=2E000000000 +0100
> +++ tlgate_gpio/drivers/char/ibm_gpio.c=A02006-09-28 16:46:42.000000000 +=
0200
> @@ -0,0 +1,349 @@
> +/*
> + * FILE NAME ibm_gpio.c
<insert usual comment about removing the file name from the file>
> + * BRIEF MODULE DESCRIPTION
> + * =A0API for IBM PowerPC 4xx GPIO device.
> + * =A0Driver for IBM PowerPC 4xx GPIO device.
> + *
> + * =A0Armin Kuster akuster@pacbell.net
> + * =A0Sept, 2001
> + *
> + * =A0Orignial driver
> + * =A0Author: MontaVista Software, Inc. =A0<source@mvista.com>
> + * =A0 =A0 =A0 =A0 =A0Frank Rowand <frank_rowand@mvista.com>
> + * =A0 =A0 =A0 =A0 =A0Debbie Chu =A0 <debbie_chu@mvista.com>
> + *
> + * Copyright 2000,2001,2002 MontaVista Software Inc.
Any new copyright year?
> + *=A0=A0=A0=A0=A0TODO: devfs
surely not.
> + *=A0=A0=A0=A0=A0Version: 02/01/12 - Armin
> + *=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 conver=
ted to ocp and using ioremap
> + *
> + *=A0=A0=A0=A0=A01.2 02/21/01 - Armin
> + *=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0minor compiler warning fixes
> + *
> + *=A0=A0=A0=A0=A01.3 02/22/01 - Armin
> + *=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0added apm
> + *
> + *=A0=A0=A0=A0=A01.4 05/07/02 - Armin/David Mueller
> + *=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0coverted to core_ocp[];
> + *
> + *=A0=A0=A0=A0=A01.5 05/25/02 - Armin
> + *=A0=A0=A0=A0=A0 name change from *_driver to *_dev
> + *
> + *=A0=A0=A0=A0=A01.6 06/04/02 - Matt Porter
> + *=A0=A0=A0=A0=A0ioremap paddr. Comment as 4xx generic driver.
> + *=A0=A0=A0=A0=A0Fix header to be userland safe and locate in
> + *=A0=A0=A0=A0=A0an accessible area. =A0Add ioctl to configure
> + *=A0=A0=A0=A0=A0multiplexed GPIO pins.
> + *
> + *=A0=A0=A0=A0=A01.7 07/25/02 - Armin
> + *=A0=A0=A0=A0=A0added CPM to enable/disable in init/exit
kill that changelog
> + */
> +
> +#define VUFX "07.25.02"
should be MODULE_VERSION()
> +#include <linux/module.h>
> +#include <linux/types.h>
> +#include <linux/kernel.h>
> +#include <linux/miscdevice.h>
> +#include <linux/init.h>
> +#include <linux/ioctl.h>
> +#include <linux/fs.h>
> +#include <asm/ibm_gpio.h>
> +#include <asm/uaccess.h>
> +#include <asm/io.h>
> +#include <asm/machdep.h>
> +#include <asm/ocp.h>
> +#include <asm/ibm4xx.h>
> +
> +struct miscdevice ibm_gpio_miscdev;
> +static struct gpio_regs *gpiop;
> +
> +int
> +ibm_gpio_config(__u32 device, __u32 mask, __u32 data)
any symbols should be static. Function arguments are not
visible to users, so they should be 'u32' instead of '__u32'.
> +{
> +=A0=A0=A0=A0=A0=A0=A0u32 cfg_reg;
> +
> +=A0=A0=A0=A0=A0=A0=A0if (device !=3D 0)
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0return -ENXIO;
> +
> +#ifdef CONFIG_40x
> +#ifdef DCRN_CHCR0
> +=A0=A0=A0=A0=A0=A0=A0/*
> +=A0=A0=A0=A0=A0=A0=A0 * PPC405 uses CPC0_CR0 to select multiplexed GPIO =
pins.
> +=A0=A0=A0=A0=A0=A0=A0 */
> +=A0=A0=A0=A0=A0=A0=A0cfg_reg =3D mfdcr(DCRN_CHCR0);
> +=A0=A0=A0=A0=A0=A0=A0cfg_reg =3D (cfg_reg & ~mask) | (data & mask);
> +=A0=A0=A0=A0=A0=A0=A0mtdcr(DCRN_CHCR0, cfg_reg);
> +#endif
> +#elif CONFIG_440GP
> +=A0=A0=A0=A0=A0=A0=A0/*
> +=A0=A0=A0=A0=A0=A0=A0 * PPC440GP uses CPC0_GPIO to select multiplexed GP=
IO pins.
> +=A0=A0=A0=A0=A0=A0=A0 */
> +=A0=A0=A0=A0=A0=A0=A0cfg_reg =3D mfdcr(DCRN_CPC0_GPIO);
> +=A0=A0=A0=A0=A0=A0=A0cfg_reg =3D (cfg_reg & ~mask) | (data & mask);
> +=A0=A0=A0=A0=A0=A0=A0mtdcr(DCRN_CPC0_GPIO, cfg_reg);
> +#elif CONFIG_440GX
> +=A0=A0=A0=A0=A0=A0=A0/*
> +=A0=A0=A0=A0=A0=A0=A0 * PPC440GX uses SDR0_PFC0 to select multiplexed GP=
IO pins
> +=A0=A0=A0=A0=A0=A0=A0 */
> +=A0=A0=A0=A0=A0=A0=A0cfg_reg =3D SDR_READ(DCRN_SDR_PFC0);
> +=A0=A0=A0=A0=A0=A0=A0cfg_reg =3D (cfg_reg & ~mask) | (data & mask);
> +=A0=A0=A0=A0=A0=A0=A0SDR_WRITE(DCRN_SDR_PFC0, cfg_reg);
> +#else
> +#error This driver is only supported on PPC40x and PPC440 CPUs
> +#endif
This prevents building a single kernel for multiple 440 version.
Please use a run-time check, or better get the necessary information
from the device tree.
> +int
> +ibm_gpio_in(__u32 device, __u32 mask, volatile __u32 * data)
> +{
> +=A0=A0=A0=A0=A0=A0=A0if (device !=3D 0)
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0return -ENXIO;
> +=A0=A0=A0=A0=A0=A0=A0gpiop->tcr =3D gpiop->tcr & ~mask;
> +=A0=A0=A0=A0=A0=A0=A0eieio();
> +
> +=A0=A0=A0=A0=A0=A0=A0/*
> +=A0=A0=A0=A0=A0=A0=A0 =A0 ** If the previous state was OUT, and gpiop->i=
r is read once, then the
> +=A0=A0=A0=A0=A0=A0=A0 =A0 ** data that was being OUTput will be read. =
=A0One way to get the right
> +=A0=A0=A0=A0=A0=A0=A0 =A0 ** data is to read gpiop->ir twice.
> +=A0=A0=A0=A0=A0=A0=A0 */
> +
> +=A0=A0=A0=A0=A0=A0=A0*data =3D gpiop->ir;
> +=A0=A0=A0=A0=A0=A0=A0*data =3D gpiop->ir & mask;
> +=A0=A0=A0=A0=A0=A0=A0eieio();
> +=A0=A0=A0=A0=A0=A0=A0return 0;
> +}
Don't just assign *data, make that an __iomem pointer and use
an appropriate accessor function (out_be32 or such).
> +
> +static int
> +ibm_gpio_open(struct inode *inode, struct file *file)
> +{
> +=A0=A0=A0=A0=A0=A0=A0return 0;
> +}
> +
> +static int
> +ibm_gpio_release(struct inode *inode, struct file *file)
> +{
> +=A0=A0=A0=A0=A0=A0=A0return 0;
> +}
You don't need these.
> +static int
> +ibm_gpio_ioctl(struct inode *inode, struct file *file,
> +=A0=A0=A0=A0=A0=A0=A0 =A0 =A0 =A0 unsigned int cmd, unsigned long arg)
> +{
> +=A0=A0=A0=A0=A0=A0=A0static struct ibm_gpio_ioctl_data ioctl_data;
> +=A0=A0=A0=A0=A0=A0=A0int status;
> +
> +=A0=A0=A0=A0=A0=A0=A0switch (cmd) {
> +=A0=A0=A0=A0=A0=A0=A0case IBMGPIO_IN:
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0if (copy_from_user(&ioctl_d=
ata,
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=
=A0=A0=A0=A0=A0=A0=A0 =A0 (struct ibm_gpio_ioctl_data *) arg,
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=
=A0=A0=A0=A0=A0=A0=A0 =A0 sizeof (ioctl_data))) {
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0ret=
urn -EFAULT;
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0}
Just do the copy_from_user() once, in the beginning here, instead
of each case.
> +
> +static int __init
> +ibm_gpio_probe(struct ocp_device *ocp)
> +{
> +=A0=A0=A0=A0=A0=A0=A0ibm_gpio_miscdev.minor =3D GPIO_MINOR;
> +=A0=A0=A0=A0=A0=A0=A0ibm_gpio_miscdev.name =3D ocp->name;
> +=A0=A0=A0=A0=A0=A0=A0ibm_gpio_miscdev.fops =3D &ibm_gpio_fops;
> +=A0=A0=A0=A0=A0=A0=A0misc_register(&ibm_gpio_miscdev);
> +
> +=A0=A0=A0=A0=A0=A0=A0if (!request_mem_region(ocp->def->paddr, sizeof(str=
uct gpio_regs), "ibm_gpio"))
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0return -EBUSY;
> +=A0=A0=A0=A0=A0=A0=A0
> +=A0=A0=A0=A0=A0=A0=A0gpiop =3D (struct gpio_regs *) ioremap(ocp->def->pa=
ddr,
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0siz=
eof(struct gpio_regs));
> +=A0=A0=A0=A0=A0=A0=A0if (!gpiop) {
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0release_mem_region(ocp->def=
=2D>paddr, sizeof(struct gpio_regs));
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0return -ENOMEM;
> +=A0=A0=A0=A0=A0=A0=A0}
> +=A0=A0=A0=A0=A0=A0=A0
> +=A0=A0=A0=A0=A0=A0=A0printk("GPIO #%d at 0x%lx\n", ocp->def->index,
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0(un=
signed long) gpiop);
> +
> +=A0=A0=A0=A0=A0=A0=A0return 0;
> +}
> +
> +static void __exit
> +ibm_gpio_remove(struct ocp_device *ocp)
> +{
> +=A0=A0=A0=A0=A0=A0=A0misc_deregister(&ibm_gpio_miscdev);
> +
> +=A0=A0=A0=A0=A0=A0=A0iounmap(gpiop);
> +=A0=A0=A0=A0=A0=A0=A0gpiop =3D NULL;
> +=A0=A0=A0=A0=A0=A0=A0
> +=A0=A0=A0=A0=A0=A0=A0release_mem_region(ocp->def->paddr, sizeof(struct g=
pio_regs));
> +}
> +
> +static struct ocp_device_id ibm_gpio_ids[] __devinitdata =3D
> +{
> +=A0=A0=A0=A0=A0=A0=A0{ .vendor =3D OCP_VENDOR_IBM, .function =3D OCP_FUN=
C_GPIO },
> +=A0=A0=A0=A0=A0=A0=A0{ .vendor =3D OCP_VENDOR_INVALID }
> +};
> +
> +MODULE_DEVICE_TABLE(ocp, ibm_gpio_ids);
> +
> +static struct ocp_driver ibm_gpio_driver =3D
> +{
> +=A0=A0=A0=A0=A0=A0=A0.name =A0 =A0 =A0 =A0 =A0 =3D "ibm_gpio",
> +=A0=A0=A0=A0=A0=A0=A0.id_table =A0 =A0 =A0 =3D ibm_gpio_ids,
> +=A0=A0=A0=A0=A0=A0=A0.probe =A0 =A0 =A0 =A0 =A0=3D ibm_gpio_probe,
> +=A0=A0=A0=A0=A0=A0=A0.remove =A0 =A0 =A0 =A0 =3D __devexit_p(ibm_gpio_re=
move),
> +#if defined(CONFIG_PM)
> +=A0=A0=A0=A0=A0=A0=A0.suspend =A0 =A0 =A0 =A0=3D NULL,
> +=A0=A0=A0=A0=A0=A0=A0.resume =A0 =A0 =A0 =A0 =3D NULL,
> +#endif
> +};
> +
> +static int __init
> +ibm_gpio_init(void)
> +{
> +=A0=A0=A0=A0=A0=A0=A0printk("IBM GPIO driver version %s\n", VUFX);
> +=A0=A0=A0=A0=A0=A0=A0return ocp_register_driver(&ibm_gpio_driver);
> +}
> +
> +static void __exit
> +ibm_gpio_exit(void)
> +{
> +=A0=A0=A0=A0=A0=A0=A0ocp_unregister_driver(&ibm_gpio_driver);
> +}
ocp will die a painful death soon, when 440 has been converted over
to use the device tree and of_device.
> +EXPORT_SYMBOL(ibm_gpio_tristate);
> +EXPORT_SYMBOL(ibm_gpio_open_drain);
> +EXPORT_SYMBOL(ibm_gpio_in);
> +EXPORT_SYMBOL(ibm_gpio_out);
Why export these at all? They don't seem to be used elsewhere?
If you need to export them, make it EXPORT_SYMBOL_GPL and put that
line directly under the functions.
> +
> +struct ibm_gpio_ioctl_data {
> + =A0 =A0 =A0 =A0__u32 device;
> + =A0 =A0 =A0 =A0__u32 mask;
> + =A0 =A0 =A0 =A0__u32 data;
> +};
> +
> +#define IBMGPIO_IOCTL_BASE=A0=A0=A0=A0=A0'Z'
> +
> +#define IBMGPIO_IN=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0_IOWR(IBMGPIO_I=
OCTL_BASE, 0, struct ibm_gpio_ioctl_data)
> +#define IBMGPIO_OUT=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0_IOW (IBMGPIO_IOC=
TL_BASE, 1, struct ibm_gpio_ioctl_data)
> +#define IBMGPIO_OPEN_DRAIN=A0=A0=A0=A0=A0_IOW (IBMGPIO_IOCTL_BASE, 2, st=
ruct ibm_gpio_ioctl_data)
> +#define IBMGPIO_TRISTATE=A0=A0=A0=A0=A0=A0=A0_IOW (IBMGPIO_IOCTL_BASE, 3=
, struct ibm_gpio_ioctl_data)
> +#define IBMGPIO_CFG=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0_IOW (IBMGPIO_IOC=
TL_BASE, 4, struct ibm_gpio_ioctl_data)
Is that the same ioctl interface as for the other gpio drivers?
> +#endif
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] IBM GPIO driver for PowerPC 4xx is back from the dead
2006-09-29 9:06 ` Arnd Bergmann
@ 2006-09-29 16:46 ` Eugene Surovegin
0 siblings, 0 replies; 5+ messages in thread
From: Eugene Surovegin @ 2006-09-29 16:46 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: Jean-Baptiste Maneyrol, linuxppc-embedded
On Fri, Sep 29, 2006 at 11:06:19AM +0200, Arnd Bergmann wrote:
>
> > +{
> > + u32 cfg_reg;
> > +
> > + if (device != 0)
> > + return -ENXIO;
> > +
> > +#ifdef CONFIG_40x
> > +#ifdef DCRN_CHCR0
> > + /*
> > + * PPC405 uses CPC0_CR0 to select multiplexed GPIO pins.
> > + */
> > + cfg_reg = mfdcr(DCRN_CHCR0);
> > + cfg_reg = (cfg_reg & ~mask) | (data & mask);
> > + mtdcr(DCRN_CHCR0, cfg_reg);
> > +#endif
> > +#elif CONFIG_440GP
> > + /*
> > + * PPC440GP uses CPC0_GPIO to select multiplexed GPIO pins.
> > + */
> > + cfg_reg = mfdcr(DCRN_CPC0_GPIO);
> > + cfg_reg = (cfg_reg & ~mask) | (data & mask);
> > + mtdcr(DCRN_CPC0_GPIO, cfg_reg);
> > +#elif CONFIG_440GX
> > + /*
> > + * PPC440GX uses SDR0_PFC0 to select multiplexed GPIO pins
> > + */
> > + cfg_reg = SDR_READ(DCRN_SDR_PFC0);
> > + cfg_reg = (cfg_reg & ~mask) | (data & mask);
> > + SDR_WRITE(DCRN_SDR_PFC0, cfg_reg);
> > +#else
> > +#error This driver is only supported on PPC40x and PPC440 CPUs
> > +#endif
>
> This prevents building a single kernel for multiple 440 version.
> Please use a run-time check, or better get the necessary information
> from the device tree.
440 kernels _are_ built for each particular 440 chip separately, and
not all these defines are even available simultaneously.
So, frankly, I don't understand your complain here. We don't support
single kernel image running on different 440s. Also, last time I
checked, 440 port wasn't using device tree as well.
--
Eugene
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2006-09-29 16:46 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-09-29 7:46 [PATCH] IBM GPIO driver for PowerPC 4xx is back from the dead Jean-Baptiste Maneyrol
2006-09-29 16:42 ` Eugene Surovegin
-- strict thread matches above, loose matches on Subject: below --
2006-09-29 8:29 Jean-Baptiste Maneyrol
2006-09-29 9:06 ` Arnd Bergmann
2006-09-29 16:46 ` Eugene Surovegin
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).