diff options
Diffstat (limited to 'packages/linux/linux-rp-2.6.24/tosa/0048-tc6393xb-GPIO-support.patch')
-rw-r--r-- | packages/linux/linux-rp-2.6.24/tosa/0048-tc6393xb-GPIO-support.patch | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/packages/linux/linux-rp-2.6.24/tosa/0048-tc6393xb-GPIO-support.patch b/packages/linux/linux-rp-2.6.24/tosa/0048-tc6393xb-GPIO-support.patch new file mode 100644 index 0000000000..ef47d6cc21 --- /dev/null +++ b/packages/linux/linux-rp-2.6.24/tosa/0048-tc6393xb-GPIO-support.patch @@ -0,0 +1,225 @@ +From 4fb4d83c7090ea21619bb652f2ea9b5c8c0c453e Mon Sep 17 00:00:00 2001 +From: Dmitry Baryshkov <dbaryshkov@gmail.com> +Date: Wed, 9 Jan 2008 01:42:58 +0300 +Subject: [PATCH 48/64] tc6393xb GPIO support + +Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com> +--- + drivers/mfd/tc6393xb.c | 124 ++++++++++++++++++++++++++++++++++++++++-- + include/linux/mfd/tc6393xb.h | 2 +- + 2 files changed, 119 insertions(+), 7 deletions(-) + +diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c +index 1a394e4..9001687 100644 +--- a/drivers/mfd/tc6393xb.c ++++ b/drivers/mfd/tc6393xb.c +@@ -49,6 +49,8 @@ enum pincontrol { + #define TC6393XB_MCR_INT_EN BIT(7) + /* bits 8 - 16 are unknown */ + ++#include <asm/gpio.h> ++ + struct tc6393xb_scr { + u8 x00[8]; + u8 revid; /* 0x08 Revision ID */ +@@ -96,6 +98,8 @@ struct tc6393xb_scr { + struct tc6393xb { + struct tc6393xb_scr __iomem *scr; + ++ struct gpio_chip gpio; ++ + spinlock_t lock; /* protects RMW cycles */ + + struct { +@@ -513,6 +517,96 @@ static struct mfd_cell tc6393xb_cells[] = { + + /*--------------------------------------------------------------------------*/ + ++static int tc6393xb_gpio_get(struct gpio_chip *chip, ++ unsigned offset) ++{ ++ struct tc6393xb *tc6393xb = container_of(chip, ++ struct tc6393xb, gpio); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ u32 mask = 1 << offset; ++ ++ return tmio_ioread32(scr->gpo_dsr) & mask; ++} ++ ++static void __tc6393xb_gpio_set(struct gpio_chip *chip, ++ unsigned offset, int value) ++{ ++ struct tc6393xb *tc6393xb = container_of(chip, ++ struct tc6393xb, gpio); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ u32 dsr; ++ ++ dsr = tmio_ioread32(scr->gpo_dsr); ++ if (value) ++ dsr |= (1L << offset); ++ else ++ dsr &= ~(1L << offset); ++ ++ tmio_iowrite32(dsr, scr->gpo_dsr); ++} ++ ++static void tc6393xb_gpio_set(struct gpio_chip *chip, ++ unsigned offset, int value) ++{ ++ struct tc6393xb *tc6393xb = container_of(chip, ++ struct tc6393xb, gpio); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tc6393xb->lock, flags); ++ ++ __tc6393xb_gpio_set(chip, offset, value); ++ ++ spin_unlock_irqrestore(&tc6393xb->lock, flags); ++} ++ ++static int tc6393xb_gpio_direction_input(struct gpio_chip *chip, ++ unsigned offset) ++{ ++ struct tc6393xb *tc6393xb = container_of(chip, ++ struct tc6393xb, gpio); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ unsigned long flags; ++ u32 doecr; ++ ++ spin_lock_irqsave(&tc6393xb->lock, flags); ++ ++ doecr = tmio_ioread32(scr->gpo_doecr); ++ ++ doecr &= ~(1 << offset); ++ ++ tmio_iowrite32(doecr, scr->gpo_doecr); ++ ++ spin_unlock_irqrestore(&tc6393xb->lock, flags); ++ ++ return 0; ++} ++ ++static int tc6393xb_gpio_direction_output(struct gpio_chip *chip, ++ unsigned offset, int value) ++{ ++ struct tc6393xb *tc6393xb = container_of(chip, ++ struct tc6393xb, gpio); ++ struct tc6393xb_scr __iomem *scr = tc6393xb->scr; ++ unsigned long flags; ++ u32 doecr; ++ ++ spin_lock_irqsave(&tc6393xb->lock, flags); ++ ++ doecr = tmio_ioread32(scr->gpo_doecr); ++ ++ doecr |= (1 << offset); ++ ++ tmio_iowrite32(doecr, scr->gpo_doecr); ++ ++ __tc6393xb_gpio_set(chip, offset, value); ++ ++ spin_unlock_irqrestore(&tc6393xb->lock, flags); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++ + static void + tc6393xb_irq(unsigned int irq, struct irq_desc *desc) + { +@@ -631,10 +725,8 @@ static int tc6393xb_hw_init(struct platform_device *dev, int resume) + iowrite16(tcpd->scr_gper, &scr->gper); + iowrite8(0, &scr->irr); + iowrite8(0xbf, &scr->imr); +- iowrite16(tcpd->scr_gpo_dsr, scr->gpo_dsr + 0); +- iowrite16(tcpd->scr_gpo_dsr >> 16, scr->gpo_dsr + 1); +- iowrite16(tcpd->scr_gpo_doecr, scr->gpo_doecr + 0); +- iowrite16(tcpd->scr_gpo_doecr >> 16, scr->gpo_doecr + 1); ++ tmio_iowrite32(tcpd->scr_gpo_dsr, &scr->gpo_dsr); ++ tmio_iowrite32(tcpd->scr_gpo_doecr, &scr->gpo_doecr); + + if (resume) + for (i = 0; i < 4; i++) +@@ -650,7 +742,7 @@ static int __devinit tc6393xb_probe(struct platform_device *dev) + struct tc6393xb *tc6393xb; + struct resource *iomem; + struct resource *rscr; +- int retval; ++ int retval, temp; + + iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!iomem) +@@ -696,6 +788,18 @@ static int __devinit tc6393xb_probe(struct platform_device *dev) + ioread8(&tc6393xb->scr->revid), + (unsigned long) iomem->start, tc6393xb->irq); + ++ tc6393xb->gpio.label = "tc6393xb"; ++ tc6393xb->gpio.base = tcpd->gpio_base; ++ tc6393xb->gpio.ngpio = 16; /* FIXME: actually 32, but I'm not sure */ ++ tc6393xb->gpio.set = tc6393xb_gpio_set; ++ tc6393xb->gpio.get = tc6393xb_gpio_get; ++ tc6393xb->gpio.direction_input = tc6393xb_gpio_direction_input; ++ tc6393xb->gpio.direction_output = tc6393xb_gpio_direction_output; ++ ++ retval = gpiochip_add(&tc6393xb->gpio); ++ if (retval) ++ goto err_gpio_add; ++ + if (tc6393xb->irq) + tc6393xb_attach_irq(dev); + +@@ -713,6 +817,8 @@ static int __devinit tc6393xb_probe(struct platform_device *dev) + if (tc6393xb->irq) + tc6393xb_detach_irq(dev); + ++err_gpio_add: ++ temp = gpiochip_remove(&tc6393xb->gpio); + err_hw_init: + tcpd->disable(dev); + err_enable: +@@ -734,6 +840,12 @@ static int __devexit tc6393xb_remove(struct platform_device *dev) { + if (tc6393xb->irq) + tc6393xb_detach_irq(dev); + ++ ret = gpiochip_remove(&tc6393xb->gpio); ++ if (ret) { ++ dev_err(&dev->dev, "Can't remove gpio chip: %d\n", ret); ++ return ret; ++ } ++ + ret = tcpd->disable(dev); + + iounmap(tc6393xb->scr); +@@ -804,7 +916,7 @@ static void __exit tc6393xb_exit(void) + platform_driver_unregister(&tc6393xb_driver); + } + +-module_init(tc6393xb_init); ++subsys_initcall(tc6393xb_init); + module_exit(tc6393xb_exit); + + MODULE_LICENSE("GPL"); +diff --git a/include/linux/mfd/tc6393xb.h b/include/linux/mfd/tc6393xb.h +index 2c69f63..97c4c7c 100644 +--- a/include/linux/mfd/tc6393xb.h ++++ b/include/linux/mfd/tc6393xb.h +@@ -45,6 +45,7 @@ struct tc6393xb_platform_data { + int (*resume)(struct platform_device *dev); + + int irq_base; /* a base for cascaded irq */ ++ int gpio_base; + + struct tmio_nand_data *nand_data; + struct tmio_fb_data *fb_data; +@@ -54,7 +55,6 @@ extern int tc6393xb_lcd_set_power(struct platform_device *fb_dev, bool on); + extern int tc6393xb_lcd_mode(struct platform_device *fb_dev, + struct fb_videomode *mode); + +- + /* + * Relative to irq_base + */ +-- +1.5.3.8 + |