diff options
| author | Anton Vorontsov <avorontsov@ru.mvista.com> | 2008-05-19 13:47:05 -0400 |
|---|---|---|
| committer | Kumar Gala <galak@kernel.crashing.org> | 2008-06-10 12:11:10 -0400 |
| commit | 32def337aafee0bc65eb58d5b1b3617525eb7fb7 (patch) | |
| tree | 22173ef1c86e1dd6de2eadee2600dbad1e029249 | |
| parent | 9572653ee01a2134ae3a1d7aa29ce9d026a6afe9 (diff) | |
powerpc/QE: implement support for the GPIO LIB API
This is needed to access QE GPIOs via Linux GPIO API.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Acked-By: Timur Tabi <timur@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
| -rw-r--r-- | Documentation/powerpc/booting-without-of.txt | 27 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/qe_lib/Kconfig | 9 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/qe_lib/Makefile | 1 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/qe_lib/gpio.c | 146 | ||||
| -rw-r--r-- | include/asm-powerpc/qe.h | 3 |
5 files changed, 186 insertions, 0 deletions
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index 8675ebca2cfd..b68684d39f96 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt | |||
| @@ -1736,6 +1736,33 @@ platforms are moved over to use the flattened-device-tree model. | |||
| 1736 | ...... | 1736 | ...... |
| 1737 | }; | 1737 | }; |
| 1738 | 1738 | ||
| 1739 | Note that "par_io" nodes are obsolete, and should not be used for | ||
| 1740 | the new device trees. Instead, each Par I/O bank should be represented | ||
| 1741 | via its own gpio-controller node: | ||
| 1742 | |||
| 1743 | Required properties: | ||
| 1744 | - #gpio-cells : should be "2". | ||
| 1745 | - compatible : should be "fsl,<chip>-qe-pario-bank", | ||
| 1746 | "fsl,mpc8323-qe-pario-bank". | ||
| 1747 | - reg : offset to the register set and its length. | ||
| 1748 | - gpio-controller : node to identify gpio controllers. | ||
| 1749 | |||
| 1750 | Example: | ||
| 1751 | qe_pio_a: gpio-controller@1400 { | ||
| 1752 | #gpio-cells = <2>; | ||
| 1753 | compatible = "fsl,mpc8360-qe-pario-bank", | ||
| 1754 | "fsl,mpc8323-qe-pario-bank"; | ||
| 1755 | reg = <0x1400 0x18>; | ||
| 1756 | gpio-controller; | ||
| 1757 | }; | ||
| 1758 | |||
| 1759 | qe_pio_e: gpio-controller@1460 { | ||
| 1760 | #gpio-cells = <2>; | ||
| 1761 | compatible = "fsl,mpc8360-qe-pario-bank", | ||
| 1762 | "fsl,mpc8323-qe-pario-bank"; | ||
| 1763 | reg = <0x1460 0x18>; | ||
| 1764 | gpio-controller; | ||
| 1765 | }; | ||
| 1739 | 1766 | ||
| 1740 | vi) Pin configuration nodes | 1767 | vi) Pin configuration nodes |
| 1741 | 1768 | ||
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig index 76ffbc48d4b9..4bb18f57901e 100644 --- a/arch/powerpc/sysdev/qe_lib/Kconfig +++ b/arch/powerpc/sysdev/qe_lib/Kconfig | |||
| @@ -24,3 +24,12 @@ config QE_USB | |||
| 24 | bool | 24 | bool |
| 25 | help | 25 | help |
| 26 | QE USB Host Controller support | 26 | QE USB Host Controller support |
| 27 | |||
| 28 | config QE_GPIO | ||
| 29 | bool "QE GPIO support" | ||
| 30 | depends on QUICC_ENGINE | ||
| 31 | select GENERIC_GPIO | ||
| 32 | select HAVE_GPIO_LIB | ||
| 33 | help | ||
| 34 | Say Y here if you're going to use hardware that connects to the | ||
| 35 | QE GPIOs. | ||
diff --git a/arch/powerpc/sysdev/qe_lib/Makefile b/arch/powerpc/sysdev/qe_lib/Makefile index e9ff8884f74a..f1855c185291 100644 --- a/arch/powerpc/sysdev/qe_lib/Makefile +++ b/arch/powerpc/sysdev/qe_lib/Makefile | |||
| @@ -7,3 +7,4 @@ obj-$(CONFIG_UCC) += ucc.o | |||
| 7 | obj-$(CONFIG_UCC_SLOW) += ucc_slow.o | 7 | obj-$(CONFIG_UCC_SLOW) += ucc_slow.o |
| 8 | obj-$(CONFIG_UCC_FAST) += ucc_fast.o | 8 | obj-$(CONFIG_UCC_FAST) += ucc_fast.o |
| 9 | obj-$(CONFIG_QE_USB) += usb.o | 9 | obj-$(CONFIG_QE_USB) += usb.o |
| 10 | obj-$(CONFIG_QE_GPIO) += gpio.o | ||
diff --git a/arch/powerpc/sysdev/qe_lib/gpio.c b/arch/powerpc/sysdev/qe_lib/gpio.c new file mode 100644 index 000000000000..c712e245dc4c --- /dev/null +++ b/arch/powerpc/sysdev/qe_lib/gpio.c | |||
| @@ -0,0 +1,146 @@ | |||
| 1 | /* | ||
| 2 | * QUICC Engine GPIOs | ||
| 3 | * | ||
| 4 | * Copyright (c) MontaVista Software, Inc. 2008. | ||
| 5 | * | ||
| 6 | * Author: Anton Vorontsov <avorontsov@ru.mvista.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the | ||
| 10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 11 | * option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/spinlock.h> | ||
| 16 | #include <linux/io.h> | ||
| 17 | #include <linux/of.h> | ||
| 18 | #include <linux/of_gpio.h> | ||
| 19 | #include <linux/gpio.h> | ||
| 20 | #include <asm/qe.h> | ||
| 21 | |||
| 22 | struct qe_gpio_chip { | ||
| 23 | struct of_mm_gpio_chip mm_gc; | ||
| 24 | spinlock_t lock; | ||
| 25 | |||
| 26 | /* shadowed data register to clear/set bits safely */ | ||
| 27 | u32 cpdata; | ||
| 28 | }; | ||
| 29 | |||
| 30 | static inline struct qe_gpio_chip * | ||
| 31 | to_qe_gpio_chip(struct of_mm_gpio_chip *mm_gc) | ||
| 32 | { | ||
| 33 | return container_of(mm_gc, struct qe_gpio_chip, mm_gc); | ||
| 34 | } | ||
| 35 | |||
| 36 | static void qe_gpio_save_regs(struct of_mm_gpio_chip *mm_gc) | ||
| 37 | { | ||
| 38 | struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc); | ||
| 39 | struct qe_pio_regs __iomem *regs = mm_gc->regs; | ||
| 40 | |||
| 41 | qe_gc->cpdata = in_be32(®s->cpdata); | ||
| 42 | } | ||
| 43 | |||
| 44 | static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio) | ||
| 45 | { | ||
| 46 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 47 | struct qe_pio_regs __iomem *regs = mm_gc->regs; | ||
| 48 | u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio); | ||
| 49 | |||
| 50 | return in_be32(®s->cpdata) & pin_mask; | ||
| 51 | } | ||
| 52 | |||
| 53 | static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | ||
| 54 | { | ||
| 55 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 56 | struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc); | ||
| 57 | struct qe_pio_regs __iomem *regs = mm_gc->regs; | ||
| 58 | unsigned long flags; | ||
| 59 | u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio); | ||
| 60 | |||
| 61 | spin_lock_irqsave(&qe_gc->lock, flags); | ||
| 62 | |||
| 63 | if (val) | ||
| 64 | qe_gc->cpdata |= pin_mask; | ||
| 65 | else | ||
| 66 | qe_gc->cpdata &= ~pin_mask; | ||
| 67 | |||
| 68 | out_be32(®s->cpdata, qe_gc->cpdata); | ||
| 69 | |||
| 70 | spin_unlock_irqrestore(&qe_gc->lock, flags); | ||
| 71 | } | ||
| 72 | |||
| 73 | static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) | ||
| 74 | { | ||
| 75 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 76 | struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc); | ||
| 77 | unsigned long flags; | ||
| 78 | |||
| 79 | spin_lock_irqsave(&qe_gc->lock, flags); | ||
| 80 | |||
| 81 | __par_io_config_pin(mm_gc->regs, gpio, QE_PIO_DIR_IN, 0, 0, 0); | ||
| 82 | |||
| 83 | spin_unlock_irqrestore(&qe_gc->lock, flags); | ||
| 84 | |||
| 85 | return 0; | ||
| 86 | } | ||
| 87 | |||
| 88 | static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | ||
| 89 | { | ||
| 90 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 91 | struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc); | ||
| 92 | unsigned long flags; | ||
| 93 | |||
| 94 | spin_lock_irqsave(&qe_gc->lock, flags); | ||
| 95 | |||
| 96 | __par_io_config_pin(mm_gc->regs, gpio, QE_PIO_DIR_OUT, 0, 0, 0); | ||
| 97 | |||
| 98 | spin_unlock_irqrestore(&qe_gc->lock, flags); | ||
| 99 | |||
| 100 | qe_gpio_set(gc, gpio, val); | ||
| 101 | |||
| 102 | return 0; | ||
| 103 | } | ||
| 104 | |||
| 105 | void __init qe_add_gpiochips(void) | ||
| 106 | { | ||
| 107 | struct device_node *np; | ||
| 108 | |||
| 109 | for_each_compatible_node(np, NULL, "fsl,mpc8323-qe-pario-bank") { | ||
| 110 | int ret; | ||
| 111 | struct qe_gpio_chip *qe_gc; | ||
| 112 | struct of_mm_gpio_chip *mm_gc; | ||
| 113 | struct of_gpio_chip *of_gc; | ||
| 114 | struct gpio_chip *gc; | ||
| 115 | |||
| 116 | qe_gc = kzalloc(sizeof(*qe_gc), GFP_KERNEL); | ||
| 117 | if (!qe_gc) { | ||
| 118 | ret = -ENOMEM; | ||
| 119 | goto err; | ||
| 120 | } | ||
| 121 | |||
| 122 | spin_lock_init(&qe_gc->lock); | ||
| 123 | |||
| 124 | mm_gc = &qe_gc->mm_gc; | ||
| 125 | of_gc = &mm_gc->of_gc; | ||
| 126 | gc = &of_gc->gc; | ||
| 127 | |||
| 128 | mm_gc->save_regs = qe_gpio_save_regs; | ||
| 129 | of_gc->gpio_cells = 2; | ||
| 130 | gc->ngpio = QE_PIO_PINS; | ||
| 131 | gc->direction_input = qe_gpio_dir_in; | ||
| 132 | gc->direction_output = qe_gpio_dir_out; | ||
| 133 | gc->get = qe_gpio_get; | ||
| 134 | gc->set = qe_gpio_set; | ||
| 135 | |||
| 136 | ret = of_mm_gpiochip_add(np, mm_gc); | ||
| 137 | if (ret) | ||
| 138 | goto err; | ||
| 139 | continue; | ||
| 140 | err: | ||
| 141 | pr_err("%s: registration failed with status %d\n", | ||
| 142 | np->full_name, ret); | ||
| 143 | kfree(qe_gc); | ||
| 144 | /* try others anyway */ | ||
| 145 | } | ||
| 146 | } | ||
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h index c4523acad48b..01e3c70b93ab 100644 --- a/include/asm-powerpc/qe.h +++ b/include/asm-powerpc/qe.h | |||
| @@ -100,8 +100,11 @@ struct qe_pio_regs { | |||
| 100 | #endif | 100 | #endif |
| 101 | }; | 101 | }; |
| 102 | 102 | ||
| 103 | extern void __init qe_add_gpiochips(void); | ||
| 103 | extern int par_io_init(struct device_node *np); | 104 | extern int par_io_init(struct device_node *np); |
| 104 | extern int par_io_of_config(struct device_node *np); | 105 | extern int par_io_of_config(struct device_node *np); |
| 106 | #define QE_PIO_DIR_IN 2 | ||
| 107 | #define QE_PIO_DIR_OUT 1 | ||
| 105 | extern void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin, | 108 | extern void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin, |
| 106 | int dir, int open_drain, int assignment, | 109 | int dir, int open_drain, int assignment, |
| 107 | int has_irq); | 110 | int has_irq); |
