blob: 13dcf798730f4313e6767dc8078b05a454e6adb2 [file] [log] [blame]
Tom Rixdd2d1cc2009-05-15 23:48:36 +02001/*
2 * Copyright (c) 2009 Wind River Systems, Inc.
3 * Tom Rix <Tom.Rix@windriver.com>
4 *
Wolfgang Denk5064ca42013-07-28 22:12:44 +02005 * SPDX-License-Identifier: GPL-2.0
Tom Rixdd2d1cc2009-05-15 23:48:36 +02006 *
7 * This work is derived from the linux 2.6.27 kernel source
8 * To fetch, use the kernel repository
9 * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
10 * Use the v2.6.27 tag.
11 *
12 * Below is the original's header including its copyright
13 *
14 * linux/arch/arm/plat-omap/gpio.c
15 *
16 * Support functions for OMAP GPIO
17 *
18 * Copyright (C) 2003-2005 Nokia Corporation
19 * Written by Juha Yrjölä <juha.yrjola@nokia.com>
Tom Rixdd2d1cc2009-05-15 23:48:36 +020020 */
21#include <common.h>
Joe Hershbergerf8928f12011-11-11 15:55:36 -060022#include <asm/gpio.h>
Tom Rixdd2d1cc2009-05-15 23:48:36 +020023#include <asm/io.h>
24#include <asm/errno.h>
25
Sanjeev Premiea2cf552011-09-08 10:47:25 -040026#define OMAP_GPIO_DIR_OUT 0
27#define OMAP_GPIO_DIR_IN 1
28
Aneesh V9a390882011-07-21 09:29:29 -040029static inline const struct gpio_bank *get_gpio_bank(int gpio)
Tom Rixdd2d1cc2009-05-15 23:48:36 +020030{
Aneesh V9a390882011-07-21 09:29:29 -040031 return &omap_gpio_bank[gpio >> 5];
Tom Rixdd2d1cc2009-05-15 23:48:36 +020032}
33
34static inline int get_gpio_index(int gpio)
35{
36 return gpio & 0x1f;
37}
38
Nikita Kiryanove3cb9c12012-11-27 22:40:57 +000039int gpio_is_valid(int gpio)
Tom Rixdd2d1cc2009-05-15 23:48:36 +020040{
Axel Lin01a461f2013-06-21 18:54:25 +080041 return (gpio >= 0) && (gpio < OMAP_MAX_GPIO);
Tom Rixdd2d1cc2009-05-15 23:48:36 +020042}
43
44static int check_gpio(int gpio)
45{
Nikita Kiryanove3cb9c12012-11-27 22:40:57 +000046 if (!gpio_is_valid(gpio)) {
Tom Rixdd2d1cc2009-05-15 23:48:36 +020047 printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
Joe Hershbergerf8928f12011-11-11 15:55:36 -060048 return -1;
Tom Rixdd2d1cc2009-05-15 23:48:36 +020049 }
50 return 0;
51}
52
Aneesh V9a390882011-07-21 09:29:29 -040053static void _set_gpio_direction(const struct gpio_bank *bank, int gpio,
54 int is_input)
Tom Rixdd2d1cc2009-05-15 23:48:36 +020055{
56 void *reg = bank->base;
57 u32 l;
58
59 switch (bank->method) {
60 case METHOD_GPIO_24XX:
Aneesh V9a390882011-07-21 09:29:29 -040061 reg += OMAP_GPIO_OE;
Tom Rixdd2d1cc2009-05-15 23:48:36 +020062 break;
63 default:
64 return;
65 }
66 l = __raw_readl(reg);
67 if (is_input)
68 l |= 1 << gpio;
69 else
70 l &= ~(1 << gpio);
71 __raw_writel(l, reg);
72}
73
Sanjeev Premiea2cf552011-09-08 10:47:25 -040074/**
75 * Get the direction of the GPIO by reading the GPIO_OE register
76 * corresponding to the specified bank.
77 */
78static int _get_gpio_direction(const struct gpio_bank *bank, int gpio)
Tom Rixdd2d1cc2009-05-15 23:48:36 +020079{
Sanjeev Premiea2cf552011-09-08 10:47:25 -040080 void *reg = bank->base;
81 u32 v;
Tom Rixdd2d1cc2009-05-15 23:48:36 +020082
Sanjeev Premiea2cf552011-09-08 10:47:25 -040083 switch (bank->method) {
84 case METHOD_GPIO_24XX:
85 reg += OMAP_GPIO_OE;
86 break;
87 default:
Joe Hershbergerf8928f12011-11-11 15:55:36 -060088 return -1;
Sanjeev Premiea2cf552011-09-08 10:47:25 -040089 }
90
91 v = __raw_readl(reg);
92
93 if (v & (1 << gpio))
94 return OMAP_GPIO_DIR_IN;
95 else
96 return OMAP_GPIO_DIR_OUT;
Tom Rixdd2d1cc2009-05-15 23:48:36 +020097}
98
Aneesh V9a390882011-07-21 09:29:29 -040099static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio,
100 int enable)
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200101{
102 void *reg = bank->base;
103 u32 l = 0;
104
105 switch (bank->method) {
106 case METHOD_GPIO_24XX:
107 if (enable)
Aneesh V9a390882011-07-21 09:29:29 -0400108 reg += OMAP_GPIO_SETDATAOUT;
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200109 else
Aneesh V9a390882011-07-21 09:29:29 -0400110 reg += OMAP_GPIO_CLEARDATAOUT;
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200111 l = 1 << gpio;
112 break;
113 default:
114 printf("omap3-gpio unknown bank method %s %d\n",
115 __FILE__, __LINE__);
116 return;
117 }
118 __raw_writel(l, reg);
119}
120
Sanjeev Premiea2cf552011-09-08 10:47:25 -0400121/**
122 * Set value of the specified gpio
123 */
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600124int gpio_set_value(unsigned gpio, int value)
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200125{
Aneesh V9a390882011-07-21 09:29:29 -0400126 const struct gpio_bank *bank;
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200127
128 if (check_gpio(gpio) < 0)
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600129 return -1;
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200130 bank = get_gpio_bank(gpio);
Sanjeev Premiea2cf552011-09-08 10:47:25 -0400131 _set_gpio_dataout(bank, get_gpio_index(gpio), value);
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600132
133 return 0;
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200134}
135
Sanjeev Premiea2cf552011-09-08 10:47:25 -0400136/**
137 * Get value of the specified gpio
138 */
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600139int gpio_get_value(unsigned gpio)
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200140{
Aneesh V9a390882011-07-21 09:29:29 -0400141 const struct gpio_bank *bank;
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200142 void *reg;
Sanjeev Premiea2cf552011-09-08 10:47:25 -0400143 int input;
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200144
145 if (check_gpio(gpio) < 0)
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600146 return -1;
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200147 bank = get_gpio_bank(gpio);
148 reg = bank->base;
149 switch (bank->method) {
150 case METHOD_GPIO_24XX:
Sanjeev Premiea2cf552011-09-08 10:47:25 -0400151 input = _get_gpio_direction(bank, get_gpio_index(gpio));
152 switch (input) {
153 case OMAP_GPIO_DIR_IN:
154 reg += OMAP_GPIO_DATAIN;
155 break;
156 case OMAP_GPIO_DIR_OUT:
157 reg += OMAP_GPIO_DATAOUT;
158 break;
159 default:
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600160 return -1;
Sanjeev Premiea2cf552011-09-08 10:47:25 -0400161 }
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200162 break;
163 default:
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600164 return -1;
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200165 }
166 return (__raw_readl(reg)
167 & (1 << get_gpio_index(gpio))) != 0;
168}
169
Sanjeev Premiea2cf552011-09-08 10:47:25 -0400170/**
171 * Set gpio direction as input
172 */
173int gpio_direction_input(unsigned gpio)
Joel A Fernandes46b9c202011-09-04 11:10:03 -0500174{
Sanjeev Premiea2cf552011-09-08 10:47:25 -0400175 const struct gpio_bank *bank;
Joel A Fernandes46b9c202011-09-04 11:10:03 -0500176
177 if (check_gpio(gpio) < 0)
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600178 return -1;
Sanjeev Premiea2cf552011-09-08 10:47:25 -0400179
Joel A Fernandes46b9c202011-09-04 11:10:03 -0500180 bank = get_gpio_bank(gpio);
Sanjeev Premiea2cf552011-09-08 10:47:25 -0400181 _set_gpio_direction(bank, get_gpio_index(gpio), 1);
182
183 return 0;
Joel A Fernandes46b9c202011-09-04 11:10:03 -0500184}
185
Sanjeev Premiea2cf552011-09-08 10:47:25 -0400186/**
187 * Set gpio direction as output
188 */
189int gpio_direction_output(unsigned gpio, int value)
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200190{
Sanjeev Premiea2cf552011-09-08 10:47:25 -0400191 const struct gpio_bank *bank;
192
193 if (check_gpio(gpio) < 0)
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600194 return -1;
Sanjeev Premiea2cf552011-09-08 10:47:25 -0400195
196 bank = get_gpio_bank(gpio);
197 _set_gpio_dataout(bank, get_gpio_index(gpio), value);
198 _set_gpio_direction(bank, get_gpio_index(gpio), 0);
199
200 return 0;
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200201}
202
Sanjeev Premiea2cf552011-09-08 10:47:25 -0400203/**
204 * Request a gpio before using it.
205 *
206 * NOTE: Argument 'label' is unused.
207 */
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600208int gpio_request(unsigned gpio, const char *label)
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200209{
210 if (check_gpio(gpio) < 0)
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600211 return -1;
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200212
213 return 0;
214}
215
Sanjeev Premiea2cf552011-09-08 10:47:25 -0400216/**
217 * Reset and free the gpio after using it.
218 */
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600219int gpio_free(unsigned gpio)
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200220{
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600221 return 0;
Tom Rixdd2d1cc2009-05-15 23:48:36 +0200222}