123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- /*
- * Atheros AR71XX/AR724X/AR913X GPIO API support
- *
- * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
- * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- *
- * 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.
- */
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/spinlock.h>
- #include <linux/io.h>
- #include <linux/ioport.h>
- #include <linux/gpio.h>
- #include <asm/mach-ath79/ar71xx_regs.h>
- #include <asm/mach-ath79/ath79.h>
- #include "common.h"
- static void __iomem *ath79_gpio_base;
- static unsigned long ath79_gpio_count;
- static DEFINE_SPINLOCK(ath79_gpio_lock);
- static void __ath79_gpio_set_value(unsigned gpio, int value)
- {
- void __iomem *base = ath79_gpio_base;
- if (value)
- __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET);
- else
- __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR);
- }
- static int __ath79_gpio_get_value(unsigned gpio)
- {
- return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
- }
- static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset)
- {
- return __ath79_gpio_get_value(offset);
- }
- static void ath79_gpio_set_value(struct gpio_chip *chip,
- unsigned offset, int value)
- {
- __ath79_gpio_set_value(offset, value);
- }
- static int ath79_gpio_direction_input(struct gpio_chip *chip,
- unsigned offset)
- {
- void __iomem *base = ath79_gpio_base;
- unsigned long flags;
- spin_lock_irqsave(&ath79_gpio_lock, flags);
- __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
- base + AR71XX_GPIO_REG_OE);
- spin_unlock_irqrestore(&ath79_gpio_lock, flags);
- return 0;
- }
- static int ath79_gpio_direction_output(struct gpio_chip *chip,
- unsigned offset, int value)
- {
- void __iomem *base = ath79_gpio_base;
- unsigned long flags;
- spin_lock_irqsave(&ath79_gpio_lock, flags);
- if (value)
- __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
- else
- __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
- __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
- base + AR71XX_GPIO_REG_OE);
- spin_unlock_irqrestore(&ath79_gpio_lock, flags);
- return 0;
- }
- static struct gpio_chip ath79_gpio_chip = {
- .label = "ath79",
- .get = ath79_gpio_get_value,
- .set = ath79_gpio_set_value,
- .direction_input = ath79_gpio_direction_input,
- .direction_output = ath79_gpio_direction_output,
- .base = 0,
- };
- void ath79_gpio_function_enable(u32 mask)
- {
- void __iomem *base = ath79_gpio_base;
- unsigned long flags;
- spin_lock_irqsave(&ath79_gpio_lock, flags);
- __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) | mask,
- base + AR71XX_GPIO_REG_FUNC);
- /* flush write */
- __raw_readl(base + AR71XX_GPIO_REG_FUNC);
- spin_unlock_irqrestore(&ath79_gpio_lock, flags);
- }
- void ath79_gpio_function_disable(u32 mask)
- {
- void __iomem *base = ath79_gpio_base;
- unsigned long flags;
- spin_lock_irqsave(&ath79_gpio_lock, flags);
- __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~mask,
- base + AR71XX_GPIO_REG_FUNC);
- /* flush write */
- __raw_readl(base + AR71XX_GPIO_REG_FUNC);
- spin_unlock_irqrestore(&ath79_gpio_lock, flags);
- }
- void ath79_gpio_function_setup(u32 set, u32 clear)
- {
- void __iomem *base = ath79_gpio_base;
- unsigned long flags;
- spin_lock_irqsave(&ath79_gpio_lock, flags);
- __raw_writel((__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~clear) | set,
- base + AR71XX_GPIO_REG_FUNC);
- /* flush write */
- __raw_readl(base + AR71XX_GPIO_REG_FUNC);
- spin_unlock_irqrestore(&ath79_gpio_lock, flags);
- }
- void __init ath79_gpio_init(void)
- {
- int err;
- if (soc_is_ar71xx())
- ath79_gpio_count = AR71XX_GPIO_COUNT;
- else if (soc_is_ar724x())
- ath79_gpio_count = AR724X_GPIO_COUNT;
- else if (soc_is_ar913x())
- ath79_gpio_count = AR913X_GPIO_COUNT;
- else if (soc_is_ar933x())
- ath79_gpio_count = AR933X_GPIO_COUNT;
- else
- BUG();
- ath79_gpio_base = ioremap_nocache(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE);
- ath79_gpio_chip.ngpio = ath79_gpio_count;
- err = gpiochip_add(&ath79_gpio_chip);
- if (err)
- panic("cannot add AR71xx GPIO chip, error=%d", err);
- }
- int gpio_get_value(unsigned gpio)
- {
- if (gpio < ath79_gpio_count)
- return __ath79_gpio_get_value(gpio);
- return __gpio_get_value(gpio);
- }
- EXPORT_SYMBOL(gpio_get_value);
- void gpio_set_value(unsigned gpio, int value)
- {
- if (gpio < ath79_gpio_count)
- __ath79_gpio_set_value(gpio, value);
- else
- __gpio_set_value(gpio, value);
- }
- EXPORT_SYMBOL(gpio_set_value);
- int gpio_to_irq(unsigned gpio)
- {
- /* FIXME */
- return -EINVAL;
- }
- EXPORT_SYMBOL(gpio_to_irq);
- int irq_to_gpio(unsigned irq)
- {
- /* FIXME */
- return -EINVAL;
- }
- EXPORT_SYMBOL(irq_to_gpio);
|