Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  *  Miscellaneous functions for IDT EB434 board
0003  *
0004  *  Copyright 2004 IDT Inc. (rischelp@idt.com)
0005  *  Copyright 2006 Phil Sutter <n0-1@freewrt.org>
0006  *  Copyright 2007 Florian Fainelli <florian@openwrt.org>
0007  *
0008  *  This program is free software; you can redistribute  it and/or modify it
0009  *  under  the terms of  the GNU General  Public License as published by the
0010  *  Free Software Foundation;  either version 2 of the  License, or (at your
0011  *  option) any later version.
0012  *
0013  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
0014  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
0015  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
0016  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
0017  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0018  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
0019  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
0020  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
0021  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0022  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0023  *
0024  *  You should have received a copy of the  GNU General Public License along
0025  *  with this program; if not, write  to the Free Software Foundation, Inc.,
0026  *  675 Mass Ave, Cambridge, MA 02139, USA.
0027  */
0028 
0029 #include <linux/kernel.h>
0030 #include <linux/init.h>
0031 #include <linux/types.h>
0032 #include <linux/export.h>
0033 #include <linux/spinlock.h>
0034 #include <linux/platform_device.h>
0035 #include <linux/gpio/driver.h>
0036 
0037 #include <asm/mach-rc32434/rb.h>
0038 #include <asm/mach-rc32434/gpio.h>
0039 
0040 #define GPIOBASE    0x050000
0041 /* Offsets relative to GPIOBASE */
0042 #define GPIOFUNC    0x00
0043 #define GPIOCFG     0x04
0044 #define GPIOD       0x08
0045 #define GPIOILEVEL  0x0C
0046 #define GPIOISTAT   0x10
0047 #define GPIONMIEN   0x14
0048 #define IMASK6      0x38
0049 
0050 struct rb532_gpio_chip {
0051     struct gpio_chip chip;
0052     void __iomem     *regbase;
0053 };
0054 
0055 static struct resource rb532_gpio_reg0_res[] = {
0056     {
0057         .name   = "gpio_reg0",
0058         .start  = REGBASE + GPIOBASE,
0059         .end    = REGBASE + GPIOBASE + sizeof(struct rb532_gpio_reg) - 1,
0060         .flags  = IORESOURCE_MEM,
0061     }
0062 };
0063 
0064 /* rb532_set_bit - sanely set a bit
0065  *
0066  * bitval: new value for the bit
0067  * offset: bit index in the 4 byte address range
0068  * ioaddr: 4 byte aligned address being altered
0069  */
0070 static inline void rb532_set_bit(unsigned bitval,
0071         unsigned offset, void __iomem *ioaddr)
0072 {
0073     unsigned long flags;
0074     u32 val;
0075 
0076     local_irq_save(flags);
0077 
0078     val = readl(ioaddr);
0079     val &= ~(!bitval << offset);   /* unset bit if bitval == 0 */
0080     val |= (!!bitval << offset);   /* set bit if bitval == 1 */
0081     writel(val, ioaddr);
0082 
0083     local_irq_restore(flags);
0084 }
0085 
0086 /* rb532_get_bit - read a bit
0087  *
0088  * returns the boolean state of the bit, which may be > 1
0089  */
0090 static inline int rb532_get_bit(unsigned offset, void __iomem *ioaddr)
0091 {
0092     return readl(ioaddr) & (1 << offset);
0093 }
0094 
0095 /*
0096  * Return GPIO level */
0097 static int rb532_gpio_get(struct gpio_chip *chip, unsigned offset)
0098 {
0099     struct rb532_gpio_chip  *gpch;
0100 
0101     gpch = gpiochip_get_data(chip);
0102     return !!rb532_get_bit(offset, gpch->regbase + GPIOD);
0103 }
0104 
0105 /*
0106  * Set output GPIO level
0107  */
0108 static void rb532_gpio_set(struct gpio_chip *chip,
0109                 unsigned offset, int value)
0110 {
0111     struct rb532_gpio_chip  *gpch;
0112 
0113     gpch = gpiochip_get_data(chip);
0114     rb532_set_bit(value, offset, gpch->regbase + GPIOD);
0115 }
0116 
0117 /*
0118  * Set GPIO direction to input
0119  */
0120 static int rb532_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
0121 {
0122     struct rb532_gpio_chip  *gpch;
0123 
0124     gpch = gpiochip_get_data(chip);
0125 
0126     /* disable alternate function in case it's set */
0127     rb532_set_bit(0, offset, gpch->regbase + GPIOFUNC);
0128 
0129     rb532_set_bit(0, offset, gpch->regbase + GPIOCFG);
0130     return 0;
0131 }
0132 
0133 /*
0134  * Set GPIO direction to output
0135  */
0136 static int rb532_gpio_direction_output(struct gpio_chip *chip,
0137                     unsigned offset, int value)
0138 {
0139     struct rb532_gpio_chip  *gpch;
0140 
0141     gpch = gpiochip_get_data(chip);
0142 
0143     /* disable alternate function in case it's set */
0144     rb532_set_bit(0, offset, gpch->regbase + GPIOFUNC);
0145 
0146     /* set the initial output value */
0147     rb532_set_bit(value, offset, gpch->regbase + GPIOD);
0148 
0149     rb532_set_bit(1, offset, gpch->regbase + GPIOCFG);
0150     return 0;
0151 }
0152 
0153 static int rb532_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
0154 {
0155     return 8 + 4 * 32 + gpio;
0156 }
0157 
0158 static struct rb532_gpio_chip rb532_gpio_chip[] = {
0159     [0] = {
0160         .chip = {
0161             .label          = "gpio0",
0162             .direction_input    = rb532_gpio_direction_input,
0163             .direction_output   = rb532_gpio_direction_output,
0164             .get            = rb532_gpio_get,
0165             .set            = rb532_gpio_set,
0166             .to_irq         = rb532_gpio_to_irq,
0167             .base           = 0,
0168             .ngpio          = 32,
0169         },
0170     },
0171 };
0172 
0173 /*
0174  * Set GPIO interrupt level
0175  */
0176 void rb532_gpio_set_ilevel(int bit, unsigned gpio)
0177 {
0178     rb532_set_bit(bit, gpio, rb532_gpio_chip->regbase + GPIOILEVEL);
0179 }
0180 EXPORT_SYMBOL(rb532_gpio_set_ilevel);
0181 
0182 /*
0183  * Set GPIO interrupt status
0184  */
0185 void rb532_gpio_set_istat(int bit, unsigned gpio)
0186 {
0187     rb532_set_bit(bit, gpio, rb532_gpio_chip->regbase + GPIOISTAT);
0188 }
0189 EXPORT_SYMBOL(rb532_gpio_set_istat);
0190 
0191 /*
0192  * Configure GPIO alternate function
0193  */
0194 void rb532_gpio_set_func(unsigned gpio)
0195 {
0196        rb532_set_bit(1, gpio, rb532_gpio_chip->regbase + GPIOFUNC);
0197 }
0198 EXPORT_SYMBOL(rb532_gpio_set_func);
0199 
0200 int __init rb532_gpio_init(void)
0201 {
0202     struct resource *r;
0203 
0204     r = rb532_gpio_reg0_res;
0205     rb532_gpio_chip->regbase = ioremap(r->start, resource_size(r));
0206 
0207     if (!rb532_gpio_chip->regbase) {
0208         printk(KERN_ERR "rb532: cannot remap GPIO register 0\n");
0209         return -ENXIO;
0210     }
0211 
0212     /* Register our GPIO chip */
0213     gpiochip_add_data(&rb532_gpio_chip->chip, rb532_gpio_chip);
0214 
0215     return 0;
0216 }
0217 arch_initcall(rb532_gpio_init);