blob: 9c4ef24079b4f4c12eba1121f2962126a2c42d2a [file] [log] [blame]
Icarus Chau98558952015-03-03 19:36:03 -08001/*
2* Copyright (C) 2015 Broadcom Corporation
3*
4* This program is free software; you can redistribute it and/or
5* modify it under the terms of the GNU General Public License as
6* published by the Free Software Foundation version 2.
7*
8* This program is distributed "as is" WITHOUT ANY WARRANTY of any
9* kind, whether express or implied; without even the implied warranty
10* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*/
13
14#include <arch/io.h>
15#include <console/console.h>
16#include <gpio.h>
17#include <stdlib.h>
18#include <delay.h>
19
20#define dev_dbg(chip, fmt, args...) printk(BIOS_DEBUG, "[%s] " fmt, \
21 chip->label, args)
22
23#define CYGNUS_GPIO_DATA_IN_OFFSET 0x00
24#define CYGNUS_GPIO_DATA_OUT_OFFSET 0x04
25#define CYGNUS_GPIO_OUT_EN_OFFSET 0x08
26#define CYGNUS_GPIO_IN_TYPE_OFFSET 0x0c
27#define CYGNUS_GPIO_INT_DE_OFFSET 0x10
28#define CYGNUS_GPIO_INT_EDGE_OFFSET 0x14
29#define CYGNUS_GPIO_INT_MSK_OFFSET 0x18
30#define CYGNUS_GPIO_INT_STAT_OFFSET 0x1c
31#define CYGNUS_GPIO_INT_MSTAT_OFFSET 0x20
32#define CYGNUS_GPIO_INT_CLR_OFFSET 0x24
33#define CYGNUS_GPIO_PAD_RES_OFFSET 0x34
34#define CYGNUS_GPIO_RES_EN_OFFSET 0x38
35
36/* drive strength control for ASIU GPIO */
37#define CYGNUS_GPIO_ASIU_DRV0_CTRL_OFFSET 0x58
38
39/* drive strength control for CCM/CRMU (AON) GPIO */
40#define CYGNUS_GPIO_DRV0_CTRL_OFFSET 0x00
41
42#define GPIO_BANK_SIZE 0x200
43#define NGPIOS_PER_BANK 32
44#define GPIO_BANK(pin) ((pin) / NGPIOS_PER_BANK)
45
46#define CYGNUS_GPIO_REG(pin, reg) (GPIO_BANK(pin) * GPIO_BANK_SIZE + (reg))
47#define CYGNUS_GPIO_SHIFT(pin) ((pin) % NGPIOS_PER_BANK)
48
49#define GPIO_DRV_STRENGTH_BIT_SHIFT 20
50#define GPIO_DRV_STRENGTH_BITS 3
51#define GPIO_DRV_STRENGTH_BIT_MASK ((1 << GPIO_DRV_STRENGTH_BITS) - 1)
52
53/*
54 * Cygnus GPIO core
55 *
56 * @base: I/O register base for Cygnus GPIO controller
57 * @io_ctrl: I/O register base for certain type of Cygnus GPIO controller that
58 * has the PINCONF support implemented outside of the GPIO block
59 * @num_banks: number of GPIO banks, each bank supports up to 32 GPIOs
60 * @pinmux_is_supported: flag to indicate this GPIO controller contains pins
61 * that can be individually muxed to GPIO
62 * @pctl_priv: pointer to pinctrl handle
63 */
64struct cygnus_gpio {
65 void *base;
66 void *io_ctrl;
67 const char *label;
68 int gpio_base;
69 u16 ngpio;
70 unsigned num_banks;
71 int pinmux_is_supported;
72 void *pctl_priv;
73};
74
75/*
76 * GPIO cores table
77 *
78 * Cygnus has 3 gpio cores. The tables contains descriptors of those cores.
79 */
80struct cygnus_gpio cygnus_gpio_table[] = {
81 {
82 .base = (void *)0x03024800,
83 .io_ctrl = (void *)0x03024008,
84 .label = "gpio_crmu",
85 .gpio_base = 170,
86 .ngpio = 6,
87 },
88 {
89 .base = (void *)0x1800a000,
90 .io_ctrl = (void *)0x0301d164,
91 .label = "gpio_ccm",
92 .gpio_base = 0,
93 .ngpio = 24,
94 },
95 {
96 .base = (void *)0x180a5000,
97 .label = "gpio_asiu",
98 .gpio_base = 24,
99 .ngpio = 146,
100 .pinmux_is_supported = 1
101 }
102};
103
104/*
105 * Map a GPIO in the local gpio_chip pin space to a pin in the Cygnus IOMUX
106 * pinctrl pin space
107 */
108struct cygnus_gpio_pin_range {
109 unsigned offset;
110 unsigned pin_base;
111 unsigned num_pins;
112};
113
114#define CYGNUS_PINRANGE(o, p, n) { .offset = o, .pin_base = p, .num_pins = n }
115
116/*
117 * Pin mapping table for mapping local GPIO pins to Cygnus IOMUX pinctrl pins.
118 * This is for ASIU gpio. The offset is based on ASIU gpios.
119 */
120static const struct cygnus_gpio_pin_range cygnus_gpio_pintable[] = {
121 CYGNUS_PINRANGE(0, 42, 1),
122 CYGNUS_PINRANGE(1, 44, 3),
123 CYGNUS_PINRANGE(4, 48, 1),
124 CYGNUS_PINRANGE(5, 50, 3),
125 CYGNUS_PINRANGE(8, 126, 1),
126 CYGNUS_PINRANGE(9, 155, 1),
127 CYGNUS_PINRANGE(10, 152, 1),
128 CYGNUS_PINRANGE(11, 154, 1),
129 CYGNUS_PINRANGE(12, 153, 1),
130 CYGNUS_PINRANGE(13, 127, 3),
131 CYGNUS_PINRANGE(16, 140, 1),
132 CYGNUS_PINRANGE(17, 145, 7),
133 CYGNUS_PINRANGE(24, 130, 10),
134 CYGNUS_PINRANGE(34, 141, 4),
135 CYGNUS_PINRANGE(38, 54, 1),
136 CYGNUS_PINRANGE(39, 56, 3),
137 CYGNUS_PINRANGE(42, 60, 3),
138 CYGNUS_PINRANGE(45, 64, 3),
139 CYGNUS_PINRANGE(48, 68, 2),
140 CYGNUS_PINRANGE(50, 84, 6),
141 CYGNUS_PINRANGE(56, 94, 6),
142 CYGNUS_PINRANGE(62, 72, 1),
143 CYGNUS_PINRANGE(63, 70, 1),
144 CYGNUS_PINRANGE(64, 80, 1),
145 CYGNUS_PINRANGE(65, 74, 3),
146 CYGNUS_PINRANGE(68, 78, 1),
147 CYGNUS_PINRANGE(69, 82, 1),
148 CYGNUS_PINRANGE(70, 156, 17),
149 CYGNUS_PINRANGE(87, 104, 12),
150 CYGNUS_PINRANGE(99, 102, 2),
151 CYGNUS_PINRANGE(101, 90, 4),
152 CYGNUS_PINRANGE(105, 116, 10),
153 CYGNUS_PINRANGE(123, 11, 1),
154 CYGNUS_PINRANGE(124, 38, 4),
155 CYGNUS_PINRANGE(128, 43, 1),
156 CYGNUS_PINRANGE(129, 47, 1),
157 CYGNUS_PINRANGE(130, 49, 1),
158 CYGNUS_PINRANGE(131, 53, 1),
159 CYGNUS_PINRANGE(132, 55, 1),
160 CYGNUS_PINRANGE(133, 59, 1),
161 CYGNUS_PINRANGE(134, 63, 1),
162 CYGNUS_PINRANGE(135, 67, 1),
163 CYGNUS_PINRANGE(136, 71, 1),
164 CYGNUS_PINRANGE(137, 73, 1),
165 CYGNUS_PINRANGE(138, 77, 1),
166 CYGNUS_PINRANGE(139, 79, 1),
167 CYGNUS_PINRANGE(140, 81, 1),
168 CYGNUS_PINRANGE(141, 83, 1),
169 CYGNUS_PINRANGE(142, 10, 1)
170};
171
172static unsigned cygnus_gpio_to_pin(unsigned gpio)
173{
174 int i;
175
176 for (i = 0; i < ARRAY_SIZE(cygnus_gpio_pintable); i++) {
177 const struct cygnus_gpio_pin_range *range = cygnus_gpio_pintable
178 + i;
179
180 if ((gpio < range->offset) ||
181 (gpio >= (range->offset + range->num_pins)))
182 continue;
183
184 return range->pin_base + (gpio - range->offset);
185 }
186 return -1;
187}
188
189static struct cygnus_gpio *cygnus_get_gpio_core(unsigned gpio,
190 unsigned *gpio_offset)
191{
192 int i;
193
194 for (i = 0; i < ARRAY_SIZE(cygnus_gpio_table); i++) {
195 struct cygnus_gpio *chip = cygnus_gpio_table + i;
196
197 if ((gpio < chip->gpio_base) ||
198 (gpio >= (chip->gpio_base + chip->ngpio)))
199 continue;
200
201 *gpio_offset = gpio - chip->gpio_base;
202 return chip;
203 }
204
205 return NULL;
206}
207
208static u32 cygnus_readl(struct cygnus_gpio *chip, unsigned int offset)
209{
210 return read32(chip->base + offset);
211}
212
213static void cygnus_writel(struct cygnus_gpio *chip, unsigned int offset,
214 u32 val)
215{
216 write32(chip->base + offset, val);
217}
218
219/**
220 * cygnus_set_bit - set or clear one bit (corresponding to the GPIO pin) in a
221 * Cygnus GPIO register
222 *
223 * @cygnus_gpio: Cygnus GPIO device
224 * @reg: register offset
225 * @gpio: GPIO pin
226 * @set: set or clear. 1 - set; 0 -clear
227 */
228static void cygnus_set_bit(struct cygnus_gpio *chip, unsigned int reg,
229 unsigned gpio, int set)
230{
231 unsigned int offset = CYGNUS_GPIO_REG(gpio, reg);
232 unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
233 u32 val;
234
235 val = cygnus_readl(chip, offset);
236 if (set)
237 val |= BIT(shift);
238 else
239 val &= ~BIT(shift);
240 cygnus_writel(chip, offset, val);
241}
242
243static int cygnus_get_bit(struct cygnus_gpio *chip, unsigned int reg,
244 unsigned gpio)
245{
246 unsigned int offset = CYGNUS_GPIO_REG(gpio, reg);
247 unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
248 u32 val;
249
250 val = cygnus_readl(chip, offset) & BIT(shift);
251 if (val)
252 return 1;
253 else
254 return 0;
255}
256
257/*
258 * Request the Cygnus IOMUX pinmux controller to mux individual pins to GPIO
259 */
260static int cygnus_gpio_request(struct cygnus_gpio *chip, unsigned offset)
261{
262 /* not all Cygnus GPIO pins can be muxed individually */
263 if (!chip->pinmux_is_supported || (chip->pctl_priv == NULL))
264 return 0;
265
266 return cygnus_gpio_request_enable(chip->pctl_priv,
267 cygnus_gpio_to_pin(offset));
268}
269
270static void cygnus_gpio_free(struct cygnus_gpio *chip, unsigned offset)
271{
272 if (!chip->pinmux_is_supported || (chip->pctl_priv == NULL))
273 return;
274
275 cygnus_gpio_disable_free(chip->pctl_priv, cygnus_gpio_to_pin(offset));
276}
277
278static int cygnus_gpio_direction_input(struct cygnus_gpio *chip, unsigned gpio)
279{
280 cygnus_set_bit(chip, CYGNUS_GPIO_OUT_EN_OFFSET, gpio, 0);
281
282 dev_dbg(chip, "gpio:%u set input\n", gpio);
283
284 return 0;
285}
286
287static int cygnus_gpio_direction_output(struct cygnus_gpio *chip, unsigned gpio,
288 int value)
289{
290 cygnus_set_bit(chip, CYGNUS_GPIO_OUT_EN_OFFSET, gpio, 1);
291 cygnus_set_bit(chip, CYGNUS_GPIO_DATA_OUT_OFFSET, gpio, value);
292
293 dev_dbg(chip, "gpio:%u set output, value:%d\n", gpio, value);
294
295 return 0;
296}
297
298static void cygnus_gpio_set(struct cygnus_gpio *chip, unsigned gpio, int value)
299{
300 cygnus_set_bit(chip, CYGNUS_GPIO_DATA_OUT_OFFSET, gpio, value);
301
302 dev_dbg(chip, "gpio:%u set, value:%d\n", gpio, value);
303}
304
305static int cygnus_gpio_get(struct cygnus_gpio *chip, unsigned gpio)
306{
307 return cygnus_get_bit(chip, CYGNUS_GPIO_DATA_IN_OFFSET, gpio);
308}
309
310static int cygnus_gpio_set_pull(struct cygnus_gpio *chip, unsigned gpio,
311 int disable, int pull_up)
312{
313 if (disable) {
314 cygnus_set_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio, 0);
315 } else {
316 cygnus_set_bit(chip, CYGNUS_GPIO_PAD_RES_OFFSET, gpio, pull_up);
317 cygnus_set_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio, 1);
318 }
319
320 dev_dbg(chip, "gpio:%u set pullup:%d\n", gpio, pull_up);
321
322 return 0;
323}
324
325#define CYGNUS_GPIO_TEST_AON_GPIO0 170
326#define CYGNUS_GPIO_TEST_SPI2_MISO 69
327#define CYGNUS_GPIO_TEST_DELAY_S 3
328
329static void cygnus_gpio_test(void)
330{
331 gpio_t gpio_in;
332 gpio_t gpio_out;
333 unsigned val;
334
335 printk(BIOS_INFO, "Start gpio test...\n");
336
337 gpio_in = CYGNUS_GPIO_TEST_AON_GPIO0; /* AON_GPIO0 */
338 gpio_input(gpio_in);
339 gpio_input_pulldown(gpio_in);
340 printk(BIOS_INFO, "GPIO get %d=%d\n", gpio_in, gpio_get(gpio_in));
341
342 gpio_in = CYGNUS_GPIO_TEST_SPI2_MISO; /* SPI2_MISO */
343 gpio_input(gpio_in);
344 gpio_input_pullup(gpio_in);
345 printk(BIOS_INFO, "GPIO get %d=%d\n", gpio_in, gpio_get(gpio_in));
346 val = 0;
347 gpio_out = CYGNUS_GPIO_TEST_SPI2_MISO;
348
349 gpio_output(gpio_out, val);
350 printk(BIOS_INFO, "GPIO set %d=%d\n", gpio_out, val);
351 delay(CYGNUS_GPIO_TEST_DELAY_S);
352
353 val = 1;
354 gpio_set(gpio_out, val);
355 printk(BIOS_INFO, "GPIO set %d=%d\n", gpio_out, val);
356 delay(CYGNUS_GPIO_TEST_DELAY_S);
357
358 val = 0;
359 gpio_set(gpio_out, val);
360 printk(BIOS_INFO, "GPIO set %d=%d\n", gpio_out, val);
361 delay(CYGNUS_GPIO_TEST_DELAY_S);
362
363 val = 1;
364 gpio_set(gpio_out, val);
365 printk(BIOS_INFO, "GPIO set %d=%d\n", gpio_out, val);
366 delay(CYGNUS_GPIO_TEST_DELAY_S);
367
368 val = 0;
369 gpio_set(gpio_out, val);
370 printk(BIOS_INFO, "GPIO set %d=%d\n", gpio_out, val);
371 delay(CYGNUS_GPIO_TEST_DELAY_S);
372
373 gpio_free(CYGNUS_GPIO_TEST_AON_GPIO0);
374 gpio_free(CYGNUS_GPIO_TEST_SPI2_MISO);
375 printk(BIOS_INFO, "Gpio test completed...\n");
376}
377
378void gpio_init(void)
379{
380 int i;
381
382 printk(BIOS_INFO, "Setting up the gpio...\n");
383
384 for (i = 0; i < ARRAY_SIZE(cygnus_gpio_table); i++) {
385 struct cygnus_gpio *chip = cygnus_gpio_table + i;
386
387 chip->num_banks = (chip->ngpio+NGPIOS_PER_BANK - 1)
388 / NGPIOS_PER_BANK;
389 if (chip->pinmux_is_supported)
390 chip->pctl_priv = cygnus_pinmux_init();
391 }
392
393 if (IS_ENABLED(CONFIG_CYGNUS_GPIO_TEST))
394 cygnus_gpio_test();
395}
396
397void gpio_free(gpio_t gpio)
398{
399 struct cygnus_gpio *chip;
400 unsigned gpio_num;
401
402 chip = cygnus_get_gpio_core(gpio, &gpio_num);
403 if (chip == NULL) {
404 dev_dbg(chip, "unable to find chip for gpio %d", gpio);
405 return;
406 }
407
408 cygnus_gpio_free(chip, gpio_num);
409}
410
411void gpio_input(gpio_t gpio)
412{
413 struct cygnus_gpio *chip;
414 unsigned gpio_num;
415
416 chip = cygnus_get_gpio_core(gpio, &gpio_num);
417 if (chip == NULL) {
418 dev_dbg(chip, "unable to find chip for gpio %d", gpio);
419 return;
420 }
421
422 if (cygnus_gpio_request(chip, gpio_num) != 0) {
423 printk(BIOS_ERR, "Cannot mux GPIO %d\n", gpio);
424 return;
425 }
426 cygnus_gpio_direction_input(chip, gpio_num);
427}
428
429void gpio_input_pulldown(gpio_t gpio)
430{
431 struct cygnus_gpio *chip;
432 unsigned gpio_num;
433
434 chip = cygnus_get_gpio_core(gpio, &gpio_num);
435 if (chip == NULL) {
436 dev_dbg(chip, "unable to find chip for gpio %d", gpio);
437 return;
438 }
439
440 cygnus_gpio_set_pull(chip, gpio_num, 0, 0);
441}
442
443void gpio_input_pullup(gpio_t gpio)
444{
445 struct cygnus_gpio *chip;
446 unsigned gpio_num;
447
448 chip = cygnus_get_gpio_core(gpio, &gpio_num);
449 if (chip == NULL) {
450 dev_dbg(chip, "unable to find chip for gpio %d", gpio);
451 return;
452 }
453
454 cygnus_gpio_set_pull(chip, gpio_num, 0, 1);
455}
456
457int gpio_get(gpio_t gpio)
458{
459 struct cygnus_gpio *chip;
460 unsigned gpio_num;
461
462 chip = cygnus_get_gpio_core(gpio, &gpio_num);
463 if (chip == NULL) {
464 dev_dbg(chip, "unable to find chip for gpio %d", gpio);
465 return -1;
466 }
467
468 return cygnus_gpio_get(chip, gpio_num);
469}
470
471void gpio_set(gpio_t gpio, int value)
472{
473 struct cygnus_gpio *chip;
474 unsigned gpio_num;
475
476 chip = cygnus_get_gpio_core(gpio, &gpio_num);
477 if (chip == NULL) {
478 dev_dbg(chip, "unable to find chip for gpio %d", gpio);
479 return;
480 }
481
482 cygnus_gpio_set(chip, gpio_num, value);
483}
484
485void gpio_output(gpio_t gpio, int value)
486{
487 struct cygnus_gpio *chip;
488 unsigned gpio_num;
489
490 chip = cygnus_get_gpio_core(gpio, &gpio_num);
491 if (chip == NULL) {
492 dev_dbg(chip, "unable to find chip for gpio %d", gpio);
493 return;
494 }
495
496 if (cygnus_gpio_request(chip, gpio_num) != 0) {
497 printk(BIOS_ERR, "Cannot mux GPIO %d\n", gpio);
498 return;
499 }
500 cygnus_gpio_direction_output(chip, gpio_num, value);
501}