Commit 6eae43c57ee92de91f6cc7c391cea97c43295da0

Authored by Gabor Juhos
Committed by Ralf Baechle
1 parent d4a67d9dc8

MIPS: ath79: add GPIOLIB support

This patch implements generic GPIO routines for the built-in
GPIO controllers of the Atheros AR71XX/AR724X/AR913X SoCs.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: linux-mips@linux-mips.org
Cc: Luis R. Rodriguez <lrodriguez@atheros.com>
Cc: Cliff Holden <Cliff.Holden@Atheros.com>
Cc: Kathy Giori <Kathy.Giori@Atheros.com>
Patchwork: https://patchwork.linux-mips.org/patch/1948/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

Showing 7 changed files with 252 additions and 2 deletions Side-by-side Diff

... ... @@ -68,6 +68,7 @@
68 68  
69 69 config ATH79
70 70 bool "Atheros AR71XX/AR724X/AR913X based boards"
  71 + select ARCH_REQUIRE_GPIOLIB
71 72 select BOOT_RAW
72 73 select CEVT_R4K
73 74 select CSRC_R4K
arch/mips/ath79/Makefile
... ... @@ -8,7 +8,7 @@
8 8 # under the terms of the GNU General Public License version 2 as published
9 9 # by the Free Software Foundation.
10 10  
11   -obj-y := prom.o setup.o irq.o common.o clock.o
  11 +obj-y := prom.o setup.o irq.o common.o clock.o gpio.o
12 12  
13 13 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
14 14  
arch/mips/ath79/common.h
... ... @@ -23,5 +23,10 @@
23 23 void ath79_clocks_init(void);
24 24 void ath79_ddr_wb_flush(unsigned int reg);
25 25  
  26 +void ath79_gpio_function_enable(u32 mask);
  27 +void ath79_gpio_function_disable(u32 mask);
  28 +void ath79_gpio_function_setup(u32 set, u32 clear);
  29 +void ath79_gpio_init(void);
  30 +
26 31 #endif /* __ATH79_COMMON_H */
arch/mips/ath79/gpio.c
  1 +/*
  2 + * Atheros AR71XX/AR724X/AR913X GPIO API support
  3 + *
  4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
  5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify it
  8 + * under the terms of the GNU General Public License version 2 as published
  9 + * by the Free Software Foundation.
  10 + */
  11 +
  12 +#include <linux/kernel.h>
  13 +#include <linux/init.h>
  14 +#include <linux/module.h>
  15 +#include <linux/types.h>
  16 +#include <linux/spinlock.h>
  17 +#include <linux/io.h>
  18 +#include <linux/ioport.h>
  19 +#include <linux/gpio.h>
  20 +
  21 +#include <asm/mach-ath79/ar71xx_regs.h>
  22 +#include <asm/mach-ath79/ath79.h>
  23 +#include "common.h"
  24 +
  25 +static void __iomem *ath79_gpio_base;
  26 +static unsigned long ath79_gpio_count;
  27 +static DEFINE_SPINLOCK(ath79_gpio_lock);
  28 +
  29 +static void __ath79_gpio_set_value(unsigned gpio, int value)
  30 +{
  31 + void __iomem *base = ath79_gpio_base;
  32 +
  33 + if (value)
  34 + __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET);
  35 + else
  36 + __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR);
  37 +}
  38 +
  39 +static int __ath79_gpio_get_value(unsigned gpio)
  40 +{
  41 + return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
  42 +}
  43 +
  44 +static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset)
  45 +{
  46 + return __ath79_gpio_get_value(offset);
  47 +}
  48 +
  49 +static void ath79_gpio_set_value(struct gpio_chip *chip,
  50 + unsigned offset, int value)
  51 +{
  52 + __ath79_gpio_set_value(offset, value);
  53 +}
  54 +
  55 +static int ath79_gpio_direction_input(struct gpio_chip *chip,
  56 + unsigned offset)
  57 +{
  58 + void __iomem *base = ath79_gpio_base;
  59 + unsigned long flags;
  60 +
  61 + spin_lock_irqsave(&ath79_gpio_lock, flags);
  62 +
  63 + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
  64 + base + AR71XX_GPIO_REG_OE);
  65 +
  66 + spin_unlock_irqrestore(&ath79_gpio_lock, flags);
  67 +
  68 + return 0;
  69 +}
  70 +
  71 +static int ath79_gpio_direction_output(struct gpio_chip *chip,
  72 + unsigned offset, int value)
  73 +{
  74 + void __iomem *base = ath79_gpio_base;
  75 + unsigned long flags;
  76 +
  77 + spin_lock_irqsave(&ath79_gpio_lock, flags);
  78 +
  79 + if (value)
  80 + __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
  81 + else
  82 + __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
  83 +
  84 + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
  85 + base + AR71XX_GPIO_REG_OE);
  86 +
  87 + spin_unlock_irqrestore(&ath79_gpio_lock, flags);
  88 +
  89 + return 0;
  90 +}
  91 +
  92 +static struct gpio_chip ath79_gpio_chip = {
  93 + .label = "ath79",
  94 + .get = ath79_gpio_get_value,
  95 + .set = ath79_gpio_set_value,
  96 + .direction_input = ath79_gpio_direction_input,
  97 + .direction_output = ath79_gpio_direction_output,
  98 + .base = 0,
  99 +};
  100 +
  101 +void ath79_gpio_function_enable(u32 mask)
  102 +{
  103 + void __iomem *base = ath79_gpio_base;
  104 + unsigned long flags;
  105 +
  106 + spin_lock_irqsave(&ath79_gpio_lock, flags);
  107 +
  108 + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) | mask,
  109 + base + AR71XX_GPIO_REG_FUNC);
  110 + /* flush write */
  111 + __raw_readl(base + AR71XX_GPIO_REG_FUNC);
  112 +
  113 + spin_unlock_irqrestore(&ath79_gpio_lock, flags);
  114 +}
  115 +
  116 +void ath79_gpio_function_disable(u32 mask)
  117 +{
  118 + void __iomem *base = ath79_gpio_base;
  119 + unsigned long flags;
  120 +
  121 + spin_lock_irqsave(&ath79_gpio_lock, flags);
  122 +
  123 + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~mask,
  124 + base + AR71XX_GPIO_REG_FUNC);
  125 + /* flush write */
  126 + __raw_readl(base + AR71XX_GPIO_REG_FUNC);
  127 +
  128 + spin_unlock_irqrestore(&ath79_gpio_lock, flags);
  129 +}
  130 +
  131 +void ath79_gpio_function_setup(u32 set, u32 clear)
  132 +{
  133 + void __iomem *base = ath79_gpio_base;
  134 + unsigned long flags;
  135 +
  136 + spin_lock_irqsave(&ath79_gpio_lock, flags);
  137 +
  138 + __raw_writel((__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~clear) | set,
  139 + base + AR71XX_GPIO_REG_FUNC);
  140 + /* flush write */
  141 + __raw_readl(base + AR71XX_GPIO_REG_FUNC);
  142 +
  143 + spin_unlock_irqrestore(&ath79_gpio_lock, flags);
  144 +}
  145 +
  146 +void __init ath79_gpio_init(void)
  147 +{
  148 + int err;
  149 +
  150 + if (soc_is_ar71xx())
  151 + ath79_gpio_count = AR71XX_GPIO_COUNT;
  152 + else if (soc_is_ar724x())
  153 + ath79_gpio_count = AR724X_GPIO_COUNT;
  154 + else if (soc_is_ar913x())
  155 + ath79_gpio_count = AR913X_GPIO_COUNT;
  156 + else
  157 + BUG();
  158 +
  159 + ath79_gpio_base = ioremap_nocache(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE);
  160 + ath79_gpio_chip.ngpio = ath79_gpio_count;
  161 +
  162 + err = gpiochip_add(&ath79_gpio_chip);
  163 + if (err)
  164 + panic("cannot add AR71xx GPIO chip, error=%d", err);
  165 +}
  166 +
  167 +int gpio_get_value(unsigned gpio)
  168 +{
  169 + if (gpio < ath79_gpio_count)
  170 + return __ath79_gpio_get_value(gpio);
  171 +
  172 + return __gpio_get_value(gpio);
  173 +}
  174 +EXPORT_SYMBOL(gpio_get_value);
  175 +
  176 +void gpio_set_value(unsigned gpio, int value)
  177 +{
  178 + if (gpio < ath79_gpio_count)
  179 + __ath79_gpio_set_value(gpio, value);
  180 + else
  181 + __gpio_set_value(gpio, value);
  182 +}
  183 +EXPORT_SYMBOL(gpio_set_value);
  184 +
  185 +int gpio_to_irq(unsigned gpio)
  186 +{
  187 + /* FIXME */
  188 + return -EINVAL;
  189 +}
  190 +EXPORT_SYMBOL(gpio_to_irq);
  191 +
  192 +int irq_to_gpio(unsigned irq)
  193 +{
  194 + /* FIXME */
  195 + return -EINVAL;
  196 +}
  197 +EXPORT_SYMBOL(irq_to_gpio);
arch/mips/ath79/setup.c
... ... @@ -157,7 +157,6 @@
157 157 AR71XX_RESET_SIZE);
158 158 ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE,
159 159 AR71XX_PLL_SIZE);
160   -
161 160 ath79_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE,
162 161 AR71XX_DDR_CTRL_SIZE);
163 162  
... ... @@ -183,6 +182,7 @@
183 182  
184 183 static int __init ath79_setup(void)
185 184 {
  185 + ath79_gpio_init();
186 186 ath79_register_uart();
187 187 return 0;
188 188 }
arch/mips/include/asm/mach-ath79/ar71xx_regs.h
... ... @@ -25,6 +25,8 @@
25 25 #define AR71XX_DDR_CTRL_SIZE 0x100
26 26 #define AR71XX_UART_BASE (AR71XX_APB_BASE + 0x00020000)
27 27 #define AR71XX_UART_SIZE 0x100
  28 +#define AR71XX_GPIO_BASE (AR71XX_APB_BASE + 0x00040000)
  29 +#define AR71XX_GPIO_SIZE 0x100
28 30 #define AR71XX_PLL_BASE (AR71XX_APB_BASE + 0x00050000)
29 31 #define AR71XX_PLL_SIZE 0x100
30 32 #define AR71XX_RESET_BASE (AR71XX_APB_BASE + 0x00060000)
... ... @@ -203,6 +205,25 @@
203 205 #define AR71XX_SPI_IOC_CS2 AR71XX_SPI_IOC_CS(2)
204 206 #define AR71XX_SPI_IOC_CS_ALL (AR71XX_SPI_IOC_CS0 | AR71XX_SPI_IOC_CS1 | \
205 207 AR71XX_SPI_IOC_CS2)
  208 +
  209 +/*
  210 + * GPIO block
  211 + */
  212 +#define AR71XX_GPIO_REG_OE 0x00
  213 +#define AR71XX_GPIO_REG_IN 0x04
  214 +#define AR71XX_GPIO_REG_OUT 0x08
  215 +#define AR71XX_GPIO_REG_SET 0x0c
  216 +#define AR71XX_GPIO_REG_CLEAR 0x10
  217 +#define AR71XX_GPIO_REG_INT_MODE 0x14
  218 +#define AR71XX_GPIO_REG_INT_TYPE 0x18
  219 +#define AR71XX_GPIO_REG_INT_POLARITY 0x1c
  220 +#define AR71XX_GPIO_REG_INT_PENDING 0x20
  221 +#define AR71XX_GPIO_REG_INT_ENABLE 0x24
  222 +#define AR71XX_GPIO_REG_FUNC 0x28
  223 +
  224 +#define AR71XX_GPIO_COUNT 16
  225 +#define AR724X_GPIO_COUNT 18
  226 +#define AR913X_GPIO_COUNT 22
206 227  
207 228 #endif /* __ASM_MACH_AR71XX_REGS_H */
arch/mips/include/asm/mach-ath79/gpio.h
  1 +/*
  2 + * Atheros AR71XX/AR724X/AR913X GPIO API definitions
  3 + *
  4 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
  5 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify it
  8 + * under the terms of the GNU General Public License version 2 as published
  9 + * by the Free Software Foundation.
  10 + *
  11 + */
  12 +
  13 +#ifndef __ASM_MACH_ATH79_GPIO_H
  14 +#define __ASM_MACH_ATH79_GPIO_H
  15 +
  16 +#define ARCH_NR_GPIOS 64
  17 +#include <asm-generic/gpio.h>
  18 +
  19 +int gpio_to_irq(unsigned gpio);
  20 +int irq_to_gpio(unsigned irq);
  21 +int gpio_get_value(unsigned gpio);
  22 +void gpio_set_value(unsigned gpio, int value);
  23 +
  24 +#define gpio_cansleep __gpio_cansleep
  25 +
  26 +#endif /* __ASM_MACH_ATH79_GPIO_H */