xref: /openbmc/linux/arch/mips/ar7/gpio.c (revision 3bc6968a)
17ca5dc14SFlorian Fainelli /*
27ca5dc14SFlorian Fainelli  * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
37ca5dc14SFlorian Fainelli  * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
45f3c9098SFlorian Fainelli  * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
57ca5dc14SFlorian Fainelli  *
67ca5dc14SFlorian Fainelli  * This program is free software; you can redistribute it and/or modify
77ca5dc14SFlorian Fainelli  * it under the terms of the GNU General Public License as published by
87ca5dc14SFlorian Fainelli  * the Free Software Foundation; either version 2 of the License, or
97ca5dc14SFlorian Fainelli  * (at your option) any later version.
107ca5dc14SFlorian Fainelli  *
117ca5dc14SFlorian Fainelli  * This program is distributed in the hope that it will be useful,
127ca5dc14SFlorian Fainelli  * but WITHOUT ANY WARRANTY; without even the implied warranty of
137ca5dc14SFlorian Fainelli  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
147ca5dc14SFlorian Fainelli  * GNU General Public License for more details.
157ca5dc14SFlorian Fainelli  *
167ca5dc14SFlorian Fainelli  * You should have received a copy of the GNU General Public License
177ca5dc14SFlorian Fainelli  * along with this program; if not, write to the Free Software
187ca5dc14SFlorian Fainelli  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
197ca5dc14SFlorian Fainelli  */
207ca5dc14SFlorian Fainelli 
217ca5dc14SFlorian Fainelli #include <linux/module.h>
225f3c9098SFlorian Fainelli #include <linux/gpio.h>
237ca5dc14SFlorian Fainelli 
247ca5dc14SFlorian Fainelli #include <asm/mach-ar7/gpio.h>
257ca5dc14SFlorian Fainelli 
265f3c9098SFlorian Fainelli struct ar7_gpio_chip {
275f3c9098SFlorian Fainelli 	void __iomem		*regs;
285f3c9098SFlorian Fainelli 	struct gpio_chip	chip;
295f3c9098SFlorian Fainelli };
307ca5dc14SFlorian Fainelli 
315f3c9098SFlorian Fainelli static int ar7_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
327ca5dc14SFlorian Fainelli {
335f3c9098SFlorian Fainelli 	struct ar7_gpio_chip *gpch =
345f3c9098SFlorian Fainelli 				container_of(chip, struct ar7_gpio_chip, chip);
355f3c9098SFlorian Fainelli 	void __iomem *gpio_in = gpch->regs + AR7_GPIO_INPUT;
367ca5dc14SFlorian Fainelli 
375f3c9098SFlorian Fainelli 	return readl(gpio_in) & (1 << gpio);
385f3c9098SFlorian Fainelli }
397ca5dc14SFlorian Fainelli 
405f3c9098SFlorian Fainelli static void ar7_gpio_set_value(struct gpio_chip *chip,
415f3c9098SFlorian Fainelli 				unsigned gpio, int value)
425f3c9098SFlorian Fainelli {
435f3c9098SFlorian Fainelli 	struct ar7_gpio_chip *gpch =
445f3c9098SFlorian Fainelli 				container_of(chip, struct ar7_gpio_chip, chip);
455f3c9098SFlorian Fainelli 	void __iomem *gpio_out = gpch->regs + AR7_GPIO_OUTPUT;
465f3c9098SFlorian Fainelli 	unsigned tmp;
475f3c9098SFlorian Fainelli 
485f3c9098SFlorian Fainelli 	tmp = readl(gpio_out) & ~(1 << gpio);
495f3c9098SFlorian Fainelli 	if (value)
505f3c9098SFlorian Fainelli 		tmp |= 1 << gpio;
515f3c9098SFlorian Fainelli 	writel(tmp, gpio_out);
525f3c9098SFlorian Fainelli }
535f3c9098SFlorian Fainelli 
545f3c9098SFlorian Fainelli static int ar7_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
555f3c9098SFlorian Fainelli {
565f3c9098SFlorian Fainelli 	struct ar7_gpio_chip *gpch =
575f3c9098SFlorian Fainelli 				container_of(chip, struct ar7_gpio_chip, chip);
585f3c9098SFlorian Fainelli 	void __iomem *gpio_dir = gpch->regs + AR7_GPIO_DIR;
595f3c9098SFlorian Fainelli 
605f3c9098SFlorian Fainelli 	writel(readl(gpio_dir) | (1 << gpio), gpio_dir);
617ca5dc14SFlorian Fainelli 
627ca5dc14SFlorian Fainelli 	return 0;
637ca5dc14SFlorian Fainelli }
647ca5dc14SFlorian Fainelli 
655f3c9098SFlorian Fainelli static int ar7_gpio_direction_output(struct gpio_chip *chip,
665f3c9098SFlorian Fainelli 					unsigned gpio, int value)
677ca5dc14SFlorian Fainelli {
685f3c9098SFlorian Fainelli 	struct ar7_gpio_chip *gpch =
695f3c9098SFlorian Fainelli 				container_of(chip, struct ar7_gpio_chip, chip);
705f3c9098SFlorian Fainelli 	void __iomem *gpio_dir = gpch->regs + AR7_GPIO_DIR;
715f3c9098SFlorian Fainelli 
725f3c9098SFlorian Fainelli 	ar7_gpio_set_value(chip, gpio, value);
735f3c9098SFlorian Fainelli 	writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir);
745f3c9098SFlorian Fainelli 
755f3c9098SFlorian Fainelli 	return 0;
767ca5dc14SFlorian Fainelli }
775f3c9098SFlorian Fainelli 
785f3c9098SFlorian Fainelli static struct ar7_gpio_chip ar7_gpio_chip = {
795f3c9098SFlorian Fainelli 	.chip = {
805f3c9098SFlorian Fainelli 		.label			= "ar7-gpio",
815f3c9098SFlorian Fainelli 		.direction_input	= ar7_gpio_direction_input,
825f3c9098SFlorian Fainelli 		.direction_output	= ar7_gpio_direction_output,
835f3c9098SFlorian Fainelli 		.set			= ar7_gpio_set_value,
845f3c9098SFlorian Fainelli 		.get			= ar7_gpio_get_value,
855f3c9098SFlorian Fainelli 		.base			= 0,
865f3c9098SFlorian Fainelli 		.ngpio			= AR7_GPIO_MAX,
875f3c9098SFlorian Fainelli 	}
885f3c9098SFlorian Fainelli };
895f3c9098SFlorian Fainelli 
905f3c9098SFlorian Fainelli int ar7_gpio_enable(unsigned gpio)
915f3c9098SFlorian Fainelli {
925f3c9098SFlorian Fainelli 	void __iomem *gpio_en = ar7_gpio_chip.regs + AR7_GPIO_ENABLE;
935f3c9098SFlorian Fainelli 
945f3c9098SFlorian Fainelli 	writel(readl(gpio_en) | (1 << gpio), gpio_en);
955f3c9098SFlorian Fainelli 
965f3c9098SFlorian Fainelli 	return 0;
975f3c9098SFlorian Fainelli }
985f3c9098SFlorian Fainelli EXPORT_SYMBOL(ar7_gpio_enable);
995f3c9098SFlorian Fainelli 
1005f3c9098SFlorian Fainelli int ar7_gpio_disable(unsigned gpio)
1015f3c9098SFlorian Fainelli {
1025f3c9098SFlorian Fainelli 	void __iomem *gpio_en = ar7_gpio_chip.regs + AR7_GPIO_ENABLE;
1035f3c9098SFlorian Fainelli 
1045f3c9098SFlorian Fainelli 	writel(readl(gpio_en) & ~(1 << gpio), gpio_en);
1055f3c9098SFlorian Fainelli 
1065f3c9098SFlorian Fainelli 	return 0;
1075f3c9098SFlorian Fainelli }
1085f3c9098SFlorian Fainelli EXPORT_SYMBOL(ar7_gpio_disable);
1095f3c9098SFlorian Fainelli 
1103bc6968aSFlorian Fainelli int __init ar7_gpio_init(void)
1115f3c9098SFlorian Fainelli {
1125f3c9098SFlorian Fainelli 	int ret;
1135f3c9098SFlorian Fainelli 
1145f3c9098SFlorian Fainelli 	ar7_gpio_chip.regs = ioremap_nocache(AR7_REGS_GPIO,
1155f3c9098SFlorian Fainelli 					AR7_REGS_GPIO + 0x10);
1165f3c9098SFlorian Fainelli 
1175f3c9098SFlorian Fainelli 	if (!ar7_gpio_chip.regs) {
1185f3c9098SFlorian Fainelli 		printk(KERN_ERR "ar7-gpio: failed to ioremap regs\n");
1195f3c9098SFlorian Fainelli 		return -ENOMEM;
1205f3c9098SFlorian Fainelli 	}
1215f3c9098SFlorian Fainelli 
1225f3c9098SFlorian Fainelli 	ret = gpiochip_add(&ar7_gpio_chip.chip);
1235f3c9098SFlorian Fainelli 	if (ret) {
1245f3c9098SFlorian Fainelli 		printk(KERN_ERR "ar7-gpio: failed to add gpiochip\n");
1255f3c9098SFlorian Fainelli 		return ret;
1265f3c9098SFlorian Fainelli 	}
1275f3c9098SFlorian Fainelli 	printk(KERN_INFO "ar7-gpio: registered %d GPIOs\n",
1285f3c9098SFlorian Fainelli 				ar7_gpio_chip.chip.ngpio);
1295f3c9098SFlorian Fainelli 	return ret;
1305f3c9098SFlorian Fainelli }
131