Linux Audio

Check our new training course

Linux kernel drivers training

May 6-19, 2025
Register
Loading...
Note: File does not exist in v4.10.11.
  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
 25static void __iomem *ath79_gpio_base;
 26static unsigned long ath79_gpio_count;
 27static DEFINE_SPINLOCK(ath79_gpio_lock);
 28
 29static 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
 39static int __ath79_gpio_get_value(unsigned gpio)
 40{
 41	return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
 42}
 43
 44static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset)
 45{
 46	return __ath79_gpio_get_value(offset);
 47}
 48
 49static void ath79_gpio_set_value(struct gpio_chip *chip,
 50				  unsigned offset, int value)
 51{
 52	__ath79_gpio_set_value(offset, value);
 53}
 54
 55static 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
 71static 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
 92static 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
101void 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
116void 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
131void 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
146void __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
167int 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}
174EXPORT_SYMBOL(gpio_get_value);
175
176void 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}
183EXPORT_SYMBOL(gpio_set_value);
184
185int gpio_to_irq(unsigned gpio)
186{
187	/* FIXME */
188	return -EINVAL;
189}
190EXPORT_SYMBOL(gpio_to_irq);
191
192int irq_to_gpio(unsigned irq)
193{
194	/* FIXME */
195	return -EINVAL;
196}
197EXPORT_SYMBOL(irq_to_gpio);