]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/gpio/am33xx_gpio.c
karo: merge with Ka-Ro specific tree for secure boot support
[karo-tx-uboot.git] / drivers / gpio / am33xx_gpio.c
1 /*
2  * Copyright (C) 2012 Lothar Waßmann <LW@KARO-electronics.de>
3  *
4  * See file CREDITS for list of people who contributed to this
5  * project.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  */
17
18 #include <common.h>
19 #include <errno.h>
20 #include <asm/io.h>
21 #include <asm/bitops.h>
22 #include <linux/sizes.h>
23 #include <asm/arch/hardware.h>
24 #include <asm/arch/gpio.h>
25
26 struct gpio_regs {
27         unsigned int res1[0x134 / 4];
28         unsigned int oe;                /* 0x134 */
29         unsigned int datain;            /* 0x138 */
30         unsigned int res2[0x54 / 4];
31         unsigned int cleardataout;      /* 0x190 */
32         unsigned int setdataout;        /* 0x194 */
33 };
34
35 static const struct gpio_regs *gpio_base[] = {
36         (struct gpio_regs *)AM33XX_GPIO0_BASE,
37         (struct gpio_regs *)AM33XX_GPIO1_BASE,
38         (struct gpio_regs *)AM33XX_GPIO2_BASE,
39         (struct gpio_regs *)AM33XX_GPIO3_BASE,
40 };
41
42 static unsigned long gpio_map[ARRAY_SIZE(gpio_base)] __attribute__((section("data")));
43
44 #define MAX_GPIO        (ARRAY_SIZE(gpio_base) * 32)
45
46 int gpio_request(unsigned gpio, const char *name)
47 {
48         if (gpio >= MAX_GPIO) {
49                 printf("ERROR: Invalid GPIO: %u (GPIO%u_%u)\n", gpio,
50                         gpio / 32, gpio % 32);
51                 return -EINVAL;
52         }
53         if (test_and_set_bit(gpio, gpio_map))
54                 return -EBUSY;
55         return 0;
56 }
57
58 int gpio_free(unsigned gpio)
59 {
60         if (gpio >= MAX_GPIO) {
61                 printf("ERROR: Invalid GPIO: %u (GPIO%u_%u)\n", gpio,
62                         gpio / 32, gpio % 32);
63                 return -EINVAL;
64         }
65         if (test_bit(gpio, gpio_map))
66                 __clear_bit(gpio, gpio_map);
67         else
68                 printf("ERROR: trying to free unclaimed GPIO %u\n", gpio);
69
70         return 0;
71 }
72
73 int gpio_set_value(unsigned gpio, int val)
74 {
75         int bank = gpio / 32;
76         int mask = 1 << (gpio % 32);
77
78         if (bank >= ARRAY_SIZE(gpio_base)) {
79                 printf("ERROR: Invalid GPIO: %u (GPIO%u_%u)\n", gpio,
80                         gpio / 32, gpio % 32);
81                 return -EINVAL;
82         }
83         if (val)
84                 writel(mask, &gpio_base[bank]->setdataout);
85         else
86                 writel(mask, &gpio_base[bank]->cleardataout);
87         return 0;
88 }
89
90 int gpio_get_value(unsigned gpio)
91 {
92         int bank = gpio / 32;
93         int mask = 1 << (gpio % 32);
94
95         if (bank >= ARRAY_SIZE(gpio_base)) {
96                 printf("ERROR: Invalid GPIO: %u (GPIO%u_%u)\n", gpio,
97                         gpio / 32, gpio % 32);
98                 return -EINVAL;
99         }
100         return (readl(&gpio_base[bank]->datain) & mask) != 0;
101 }
102
103 int gpio_direction_input(unsigned gpio)
104 {
105         int bank = gpio / 32;
106         int mask = 1 << (gpio % 32);
107
108         if (bank >= ARRAY_SIZE(gpio_base)) {
109                 printf("ERROR: Invalid GPIO: %u (GPIO%u_%u)\n", gpio,
110                         gpio / 32, gpio % 32);
111                 return -EINVAL;
112         }
113         writel(readl(&gpio_base[bank]->oe) | mask, &gpio_base[bank]->oe);
114         return 0;
115 }
116
117 int gpio_direction_output(unsigned gpio, int val)
118 {
119         int bank = gpio / 32;
120         int mask = 1 << (gpio % 32);
121
122         if (bank >= ARRAY_SIZE(gpio_base)) {
123                 printf("ERROR: Invalid GPIO: %u (GPIO%u_%u)\n", gpio,
124                         gpio / 32, gpio % 32);
125                 return -EINVAL;
126         }
127         gpio_set_value(gpio, val);
128         writel(readl(&gpio_base[bank]->oe) & ~mask, &gpio_base[bank]->oe);
129         return 0;
130 }