12cb06a4fSStefan Roese /*
22cb06a4fSStefan Roese * Copyright (C) 2012 Stefan Roese <sr@denx.de>
32cb06a4fSStefan Roese *
41a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+
52cb06a4fSStefan Roese */
62cb06a4fSStefan Roese
72cb06a4fSStefan Roese /*
82cb06a4fSStefan Roese * Driver for SPEAr600 GPIO controller
92cb06a4fSStefan Roese */
102cb06a4fSStefan Roese
112cb06a4fSStefan Roese #include <common.h>
122cb06a4fSStefan Roese #include <asm/arch/hardware.h>
132cb06a4fSStefan Roese #include <asm/gpio.h>
142cb06a4fSStefan Roese #include <asm/io.h>
152cb06a4fSStefan Roese #include <errno.h>
162cb06a4fSStefan Roese
gpio_direction(unsigned gpio,enum gpio_direction direction)172cb06a4fSStefan Roese static int gpio_direction(unsigned gpio,
182cb06a4fSStefan Roese enum gpio_direction direction)
192cb06a4fSStefan Roese {
202cb06a4fSStefan Roese struct gpio_regs *regs = (struct gpio_regs *)CONFIG_GPIO_BASE;
212cb06a4fSStefan Roese u32 val;
222cb06a4fSStefan Roese
232cb06a4fSStefan Roese val = readl(®s->gpiodir);
242cb06a4fSStefan Roese
252cb06a4fSStefan Roese if (direction == GPIO_DIRECTION_OUT)
262cb06a4fSStefan Roese val |= 1 << gpio;
272cb06a4fSStefan Roese else
282cb06a4fSStefan Roese val &= ~(1 << gpio);
292cb06a4fSStefan Roese
302cb06a4fSStefan Roese writel(val, ®s->gpiodir);
312cb06a4fSStefan Roese
322cb06a4fSStefan Roese return 0;
332cb06a4fSStefan Roese }
342cb06a4fSStefan Roese
gpio_set_value(unsigned gpio,int value)352cb06a4fSStefan Roese int gpio_set_value(unsigned gpio, int value)
362cb06a4fSStefan Roese {
372cb06a4fSStefan Roese struct gpio_regs *regs = (struct gpio_regs *)CONFIG_GPIO_BASE;
382cb06a4fSStefan Roese
39*c0c37402SAxel Lin if (value)
402cb06a4fSStefan Roese writel(1 << gpio, ®s->gpiodata[DATA_REG_ADDR(gpio)]);
41*c0c37402SAxel Lin else
42*c0c37402SAxel Lin writel(0, ®s->gpiodata[DATA_REG_ADDR(gpio)]);
432cb06a4fSStefan Roese
442cb06a4fSStefan Roese return 0;
452cb06a4fSStefan Roese }
462cb06a4fSStefan Roese
gpio_get_value(unsigned gpio)472cb06a4fSStefan Roese int gpio_get_value(unsigned gpio)
482cb06a4fSStefan Roese {
492cb06a4fSStefan Roese struct gpio_regs *regs = (struct gpio_regs *)CONFIG_GPIO_BASE;
502cb06a4fSStefan Roese u32 val;
512cb06a4fSStefan Roese
522cb06a4fSStefan Roese val = readl(®s->gpiodata[DATA_REG_ADDR(gpio)]);
532cb06a4fSStefan Roese
542cb06a4fSStefan Roese return !!val;
552cb06a4fSStefan Roese }
562cb06a4fSStefan Roese
gpio_request(unsigned gpio,const char * label)572cb06a4fSStefan Roese int gpio_request(unsigned gpio, const char *label)
582cb06a4fSStefan Roese {
592cb06a4fSStefan Roese if (gpio >= SPEAR_GPIO_COUNT)
602cb06a4fSStefan Roese return -EINVAL;
612cb06a4fSStefan Roese
622cb06a4fSStefan Roese return 0;
632cb06a4fSStefan Roese }
642cb06a4fSStefan Roese
gpio_free(unsigned gpio)652cb06a4fSStefan Roese int gpio_free(unsigned gpio)
662cb06a4fSStefan Roese {
672cb06a4fSStefan Roese return 0;
682cb06a4fSStefan Roese }
692cb06a4fSStefan Roese
gpio_toggle_value(unsigned gpio)702cb06a4fSStefan Roese void gpio_toggle_value(unsigned gpio)
712cb06a4fSStefan Roese {
722cb06a4fSStefan Roese gpio_set_value(gpio, !gpio_get_value(gpio));
732cb06a4fSStefan Roese }
742cb06a4fSStefan Roese
gpio_direction_input(unsigned gpio)752cb06a4fSStefan Roese int gpio_direction_input(unsigned gpio)
762cb06a4fSStefan Roese {
772cb06a4fSStefan Roese return gpio_direction(gpio, GPIO_DIRECTION_IN);
782cb06a4fSStefan Roese }
792cb06a4fSStefan Roese
gpio_direction_output(unsigned gpio,int value)802cb06a4fSStefan Roese int gpio_direction_output(unsigned gpio, int value)
812cb06a4fSStefan Roese {
822cb06a4fSStefan Roese int ret = gpio_direction(gpio, GPIO_DIRECTION_OUT);
832cb06a4fSStefan Roese
842cb06a4fSStefan Roese if (ret < 0)
852cb06a4fSStefan Roese return ret;
862cb06a4fSStefan Roese
872cb06a4fSStefan Roese gpio_set_value(gpio, value);
882cb06a4fSStefan Roese return 0;
892cb06a4fSStefan Roese }
90