blob: 1787878bc26a60966286ed37e02aa29ec8e089ea [file] [log] [blame]
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -08001/*
Stefan Reinauer08dc3572013-05-14 16:57:50 -07002 * This file is part of the coreboot project.
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -08003 *
Stefan Reinauer08dc3572013-05-14 16:57:50 -07004 * Copyright (C) 2009 Samsung Electronics
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -08009 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080014 */
15
Stefan Reinauer08dc3572013-05-14 16:57:50 -070016#include <assert.h>
Julius Werner1ed0c8c2014-10-20 13:16:29 -070017#include <console/console.h>
18#include <delay.h>
19#include <soc/cpu.h>
20#include <soc/gpio.h>
21#include <string.h>
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080022
23#define CON_MASK(x) (0xf << ((x) << 2))
24#define CON_SFR(x, v) ((v) << ((x) << 2))
25
26#define DAT_MASK(x) (0x1 << (x))
27#define DAT_SET(x) (0x1 << (x))
28
29#define PULL_MASK(x) (0x3 << ((x) << 1))
30#define PULL_MODE(x, v) ((v) << ((x) << 1))
31
32#define DRV_MASK(x) (0x3 << ((x) << 1))
33#define DRV_SET(x, m) ((m) << ((x) << 1))
34#define RATE_MASK(x) (0x1 << (x + 16))
35#define RATE_SET(x) (0x1 << (x + 16))
36
37struct gpio_info {
38 unsigned int reg_addr; /* Address of register for this part */
39 unsigned int max_gpio; /* Maximum GPIO in this part */
40};
41
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080042static const struct gpio_info gpio_data[EXYNOS_GPIO_NUM_PARTS] = {
43 { EXYNOS5_GPIO_PART1_BASE, GPIO_MAX_PORT_PART_1 },
44 { EXYNOS5_GPIO_PART2_BASE, GPIO_MAX_PORT_PART_2 },
45 { EXYNOS5_GPIO_PART3_BASE, GPIO_MAX_PORT_PART_3 },
46 { EXYNOS5_GPIO_PART4_BASE, GPIO_MAX_PORT_PART_4 },
47 { EXYNOS5_GPIO_PART5_BASE, GPIO_MAX_PORT_PART_5 },
48 { EXYNOS5_GPIO_PART6_BASE, GPIO_MAX_PORT },
49};
50
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080051/* This macro gets gpio pin offset from 0..7 */
52#define GPIO_BIT(x) ((x) & 0x7)
53
Stefan Reinauerdc006c12013-05-15 14:54:07 -070054static struct gpio_bank *gpio_get_bank(unsigned int gpio)
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080055{
56 const struct gpio_info *data;
57 unsigned int upto;
58 int i;
59
60 for (i = upto = 0, data = gpio_data; i < EXYNOS_GPIO_NUM_PARTS;
61 i++, upto = data->max_gpio, data++) {
62 if (gpio < data->max_gpio) {
Stefan Reinauerdc006c12013-05-15 14:54:07 -070063 struct gpio_bank *bank;
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080064
Stefan Reinauerdc006c12013-05-15 14:54:07 -070065 bank = (struct gpio_bank *)data->reg_addr;
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080066 bank += (gpio - upto) / GPIO_PER_BANK;
67 return bank;
68 }
69 }
70
Stefan Reinauer08dc3572013-05-14 16:57:50 -070071 ASSERT(gpio < GPIO_MAX_PORT); /* ...which it will not be */
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080072 return NULL;
73}
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080074
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080075/* Common GPIO API - only available on Exynos5 */
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080076void gpio_cfg_pin(int gpio, int cfg)
77{
78 unsigned int value;
Stefan Reinauerdc006c12013-05-15 14:54:07 -070079 struct gpio_bank *bank = gpio_get_bank(gpio);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080080
Julius Werner2f37bd62015-02-19 14:51:15 -080081 value = read32(&bank->con);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080082 value &= ~CON_MASK(GPIO_BIT(gpio));
83 value |= CON_SFR(GPIO_BIT(gpio), cfg);
Julius Werner2f37bd62015-02-19 14:51:15 -080084 write32(&bank->con, value);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080085}
86
87static int gpio_get_cfg(int gpio)
88{
Stefan Reinauerdc006c12013-05-15 14:54:07 -070089 struct gpio_bank *bank = gpio_get_bank(gpio);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080090 int shift = GPIO_BIT(gpio) << 2;
91
Julius Werner2f37bd62015-02-19 14:51:15 -080092 return (read32(&bank->con) & CON_MASK(GPIO_BIT(gpio))) >> shift;
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080093}
94
95void gpio_set_pull(int gpio, int mode)
96{
97 unsigned int value;
Stefan Reinauerdc006c12013-05-15 14:54:07 -070098 struct gpio_bank *bank = gpio_get_bank(gpio);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080099
Julius Werner2f37bd62015-02-19 14:51:15 -0800100 value = read32(&bank->pull);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800101 value &= ~PULL_MASK(GPIO_BIT(gpio));
102
103 switch (mode) {
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700104 case GPIO_PULL_DOWN:
105 case GPIO_PULL_UP:
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800106 value |= PULL_MODE(GPIO_BIT(gpio), mode);
107 break;
108 default:
109 break;
110 }
111
Julius Werner2f37bd62015-02-19 14:51:15 -0800112 write32(&bank->pull, value);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800113}
114
115void gpio_set_drv(int gpio, int mode)
116{
117 unsigned int value;
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700118 struct gpio_bank *bank = gpio_get_bank(gpio);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800119
Julius Werner2f37bd62015-02-19 14:51:15 -0800120 value = read32(&bank->drv);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800121 value &= ~DRV_MASK(GPIO_BIT(gpio));
122
123 switch (mode) {
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700124 case GPIO_DRV_1X:
125 case GPIO_DRV_2X:
126 case GPIO_DRV_3X:
127 case GPIO_DRV_4X:
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800128 value |= DRV_SET(GPIO_BIT(gpio), mode);
129 break;
130 default:
131 return;
132 }
133
Julius Werner2f37bd62015-02-19 14:51:15 -0800134 write32(&bank->drv, value);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800135}
136
137void gpio_set_rate(int gpio, int mode)
138{
139 unsigned int value;
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700140 struct gpio_bank *bank = gpio_get_bank(gpio);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800141
Julius Werner2f37bd62015-02-19 14:51:15 -0800142 value = read32(&bank->drv);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800143 value &= ~RATE_MASK(GPIO_BIT(gpio));
144
145 switch (mode) {
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700146 case GPIO_DRV_FAST:
147 case GPIO_DRV_SLOW:
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800148 value |= RATE_SET(GPIO_BIT(gpio));
149 break;
150 default:
151 return;
152 }
153
Julius Werner2f37bd62015-02-19 14:51:15 -0800154 write32(&bank->drv, value);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800155}
156
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800157int gpio_direction_input(unsigned gpio)
158{
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700159 gpio_cfg_pin(gpio, GPIO_INPUT);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800160
161 return 0;
162}
163
164int gpio_direction_output(unsigned gpio, int value)
165{
166 unsigned int val;
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700167 struct gpio_bank *bank = gpio_get_bank(gpio);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800168
Julius Werner2f37bd62015-02-19 14:51:15 -0800169 val = read32(&bank->dat);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800170 val &= ~DAT_MASK(GPIO_BIT(gpio));
171 if (value)
172 val |= DAT_SET(GPIO_BIT(gpio));
Julius Werner2f37bd62015-02-19 14:51:15 -0800173 write32(&bank->dat, val);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800174
Ronald G. Minnich32450562013-06-18 13:02:23 -0700175 gpio_cfg_pin(gpio, GPIO_OUTPUT);
176
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800177 return 0;
178}
179
180int gpio_get_value(unsigned gpio)
181{
182 unsigned int value;
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700183 struct gpio_bank *bank = gpio_get_bank(gpio);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800184
Julius Werner2f37bd62015-02-19 14:51:15 -0800185 value = read32(&bank->dat);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800186 return !!(value & DAT_MASK(GPIO_BIT(gpio)));
187}
188
189int gpio_set_value(unsigned gpio, int value)
190{
191 unsigned int val;
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700192 struct gpio_bank *bank = gpio_get_bank(gpio);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800193
Julius Werner2f37bd62015-02-19 14:51:15 -0800194 val = read32(&bank->dat);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800195 val &= ~DAT_MASK(GPIO_BIT(gpio));
196 if (value)
197 val |= DAT_SET(GPIO_BIT(gpio));
Julius Werner2f37bd62015-02-19 14:51:15 -0800198 write32(&bank->dat, val);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800199
200 return 0;
201}
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800202
203/*
204 * Add a delay here to give the lines time to settle
205 * TODO(sjg): 1us does not always work, 2 is stable, so use 5 to be safe
206 * Come back to this and sort out what the datasheet says
207 */
208#define GPIO_DELAY_US 5
209
David Hendricksad7f98cb2013-02-02 17:02:36 -0800210int gpio_read_mvl3(unsigned gpio)
211{
212 int high, low;
213 enum mvl3 value;
214
215 if (gpio >= GPIO_MAX_PORT)
216 return -1;
217
218 gpio_direction_input(gpio);
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700219 gpio_set_pull(gpio, GPIO_PULL_UP);
David Hendricksad7f98cb2013-02-02 17:02:36 -0800220 udelay(GPIO_DELAY_US);
221 high = gpio_get_value(gpio);
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700222 gpio_set_pull(gpio, GPIO_PULL_DOWN);
David Hendricksad7f98cb2013-02-02 17:02:36 -0800223 udelay(GPIO_DELAY_US);
224 low = gpio_get_value(gpio);
225
226 if (high && low) /* external pullup */
227 value = LOGIC_1;
228 else if (!high && !low) /* external pulldown */
229 value = LOGIC_0;
230 else /* floating */
231 value = LOGIC_Z;
232
233 /*
234 * Check if line is externally pulled high and
235 * configure the internal pullup to match. For
236 * floating and pulldowns, the GPIO is already
237 * configured with an internal pulldown from the
238 * above test.
239 */
240 if (value == LOGIC_1)
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700241 gpio_set_pull(gpio, GPIO_PULL_UP);
David Hendricksad7f98cb2013-02-02 17:02:36 -0800242
243 return value;
244}
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800245
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800246/*
247 * Display Exynos GPIO information
248 */
249void gpio_info(void)
250{
251 unsigned gpio;
252
253 for (gpio = 0; gpio < GPIO_MAX_PORT; gpio++) {
254 int cfg = gpio_get_cfg(gpio);
255
Stefan Reinauer08dc3572013-05-14 16:57:50 -0700256 printk(BIOS_INFO, "GPIO_%-3d: ", gpio);
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700257 if (cfg == GPIO_INPUT)
Stefan Reinauer08dc3572013-05-14 16:57:50 -0700258 printk(BIOS_INFO, "input");
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700259 else if (cfg == GPIO_OUTPUT)
Stefan Reinauer08dc3572013-05-14 16:57:50 -0700260 printk(BIOS_INFO, "output");
261 else
262 printk(BIOS_INFO, "func %d", cfg);
263
Stefan Reinauerdc006c12013-05-15 14:54:07 -0700264 if (cfg == GPIO_INPUT || cfg == GPIO_OUTPUT)
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800265 printk(BIOS_INFO, ", value = %d", gpio_get_value(gpio));
266 printk(BIOS_INFO, "\n");
267 }
268}