Home | History | Annotate | Download | only in gpio
      1 /*
      2  * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
      3  * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
      4  *
      5  * GPIO driver for PL061
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions are met:
      9  *
     10  * Redistributions of source code must retain the above copyright notice, this
     11  * list of conditions and the following disclaimer.
     12  *
     13  * Redistributions in binary form must reproduce the above copyright notice,
     14  * this list of conditions and the following disclaimer in the documentation
     15  * and/or other materials provided with the distribution.
     16  *
     17  * Neither the name of ARM nor the names of its contributors may be used
     18  * to endorse or promote products derived from this software without specific
     19  * prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
     25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31  * POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 #include <console.h>
     35 #include <debug.h>
     36 #include <errno.h>
     37 #include <gpio.h>
     38 #include <mmio.h>
     39 
     40 #define MAX_GPIO_DEVICES	32
     41 #define GPIOS_PER_DEV		8
     42 #define GPIO_DIR		0x400
     43 
     44 #define BIT(nr)			(1UL << (nr))
     45 
     46 struct gpio_device_t {
     47 	unsigned int	base[MAX_GPIO_DEVICES];
     48 	unsigned int	count;
     49 };
     50 
     51 static struct gpio_device_t gpio_dev;
     52 
     53 /* return 0 for failure */
     54 static unsigned int find_gc_base(unsigned int gpio)
     55 {
     56 	int gc;
     57 
     58 	gc = gpio / GPIOS_PER_DEV;
     59 	if (gc >= gpio_dev.count)
     60 		return 0;
     61 	return gpio_dev.base[gc];
     62 }
     63 
     64 int gpio_direction_input(unsigned int gpio)
     65 {
     66 	unsigned int gc_base, offset, data;
     67 
     68 	gc_base = find_gc_base(gpio);
     69 	if (!gc_base)
     70 		return -EINVAL;
     71 	offset = gpio % GPIOS_PER_DEV;
     72 
     73 	data = mmio_read_8(gc_base + GPIO_DIR);
     74 	data &= ~(1 << offset);
     75 	mmio_write_8(gc_base + GPIO_DIR, data);
     76 	return 0;
     77 }
     78 
     79 int gpio_direction_output(unsigned int gpio)
     80 {
     81 	unsigned int gc_base, offset, data;
     82 
     83 	gc_base = find_gc_base(gpio);
     84 	if (!gc_base)
     85 		return -EINVAL;
     86 	offset = gpio % 8;
     87 
     88 	data = mmio_read_8(gc_base + GPIO_DIR);
     89 	data |= 1 << offset;
     90 	mmio_write_8(gc_base + GPIO_DIR, data);
     91 	return 0;
     92 }
     93 
     94 int gpio_get_value(unsigned int gpio)
     95 {
     96 	unsigned int gc_base, offset;
     97 
     98 	gc_base = find_gc_base(gpio);
     99 	if (!gc_base)
    100 		return -EINVAL;
    101 	offset = gpio % 8;
    102 
    103 	return !!mmio_read_8(gc_base + (BIT(offset + 2)));
    104 }
    105 
    106 int gpio_set_value(unsigned int gpio, unsigned int value)
    107 {
    108 	unsigned int gc_base, offset;
    109 
    110 	gc_base = find_gc_base(gpio);
    111 	if (!gc_base)
    112 		return -EINVAL;
    113 	offset = gpio % 8;
    114 	mmio_write_8(gc_base + (BIT(offset + 2)), !!value << offset);
    115 	return 0;
    116 }
    117 
    118 int gpio_register_device(unsigned int base)
    119 {
    120 	int i;
    121 	if (gpio_dev.count > MAX_GPIO_DEVICES)
    122 		return -EINVAL;
    123 	for (i = 0; i < gpio_dev.count; i++) {
    124 		if (gpio_dev.base[i] == base) {
    125 			WARN("%s: duplicated gpio base\n", __func__);
    126 			return -EINVAL;
    127 		}
    128 	}
    129 	gpio_dev.base[gpio_dev.count] = base;
    130 	gpio_dev.count++;
    131 	return 0;
    132 }
    133