blob: bb85acf8ccb1401fcd99bba50668248ab31e5cf8 [file] [log] [blame]
Shunqian Zheng015ae112016-04-20 20:35:09 +08001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2014 Rockchip Inc.
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.
9 *
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.
14 */
15
Kyösti Mälkki13f66502019-03-03 08:01:05 +020016#include <device/mmio.h>
Lin Huang589474f2017-08-02 16:59:06 +080017#include <assert.h>
Shunqian Zheng015ae112016-04-20 20:35:09 +080018#include <gpio.h>
19#include <soc/gpio.h>
20#include <soc/grf.h>
21#include <soc/soc.h>
22#include <stdlib.h>
23
Julius Werner2768a112016-09-01 22:55:58 -070024static void gpio_set_dir(gpio_t gpio, enum gpio_dir dir)
25{
26 clrsetbits_le32(&gpio_port[gpio.port]->swporta_ddr,
27 1 << gpio.num, dir << gpio.num);
28}
29
30static void gpio_set_pull(gpio_t gpio, enum gpio_pull pull)
Shunqian Zheng015ae112016-04-20 20:35:09 +080031{
Shunqian Zheng74bb4122016-05-17 14:00:04 +080032 u32 pull_val = gpio_get_pull_val(gpio, pull);
Lin Huang7c5eb072017-08-03 14:51:41 +080033 if (is_pmu_gpio(gpio) && IS_ENABLED(CONFIG_SOC_ROCKCHIP_RK3288))
Shunqian Zheng015ae112016-04-20 20:35:09 +080034 clrsetbits_le32(gpio_grf_reg(gpio), 3 << (gpio.idx * 2),
Shunqian Zheng74bb4122016-05-17 14:00:04 +080035 pull_val << (gpio.idx * 2));
Shunqian Zheng015ae112016-04-20 20:35:09 +080036 else
37 write32(gpio_grf_reg(gpio), RK_CLRSETBITS(3 << (gpio.idx * 2),
Shunqian Zheng74bb4122016-05-17 14:00:04 +080038 pull_val << (gpio.idx * 2)));
Shunqian Zheng015ae112016-04-20 20:35:09 +080039}
40
41void gpio_input(gpio_t gpio)
42{
Julius Werner2768a112016-09-01 22:55:58 -070043 gpio_set_pull(gpio, GPIO_PULLNONE);
44 gpio_set_dir(gpio, GPIO_INPUT);
Shunqian Zheng015ae112016-04-20 20:35:09 +080045}
46
47void gpio_input_pulldown(gpio_t gpio)
48{
Julius Werner2768a112016-09-01 22:55:58 -070049 gpio_set_pull(gpio, GPIO_PULLDOWN);
50 gpio_set_dir(gpio, GPIO_INPUT);
Shunqian Zheng015ae112016-04-20 20:35:09 +080051}
52
53void gpio_input_pullup(gpio_t gpio)
54{
Julius Werner2768a112016-09-01 22:55:58 -070055 gpio_set_pull(gpio, GPIO_PULLUP);
56 gpio_set_dir(gpio, GPIO_INPUT);
Shunqian Zheng015ae112016-04-20 20:35:09 +080057}
58
Lin Huang589474f2017-08-02 16:59:06 +080059void gpio_input_irq(gpio_t gpio, enum gpio_irq_type type, enum gpio_pull pull)
Jeffy Chenb0b59872017-03-03 18:24:02 +080060{
61 uint32_t int_polarity, inttype_level;
62 uint32_t mask = BIT(gpio.num);
63
Lin Huang589474f2017-08-02 16:59:06 +080064 /* gpio pull only PULLNONE, PULLUP, PULLDOWN status */
65 assert(pull <= GPIO_PULLDOWN);
66
67 gpio_set_dir(gpio, GPIO_INPUT);
68 gpio_set_pull(gpio, pull);
Jeffy Chenb0b59872017-03-03 18:24:02 +080069
70 int_polarity = inttype_level = 0;
71 switch (type) {
72 case IRQ_TYPE_EDGE_RISING:
73 int_polarity = mask;
74 inttype_level = mask;
75 break;
76 case IRQ_TYPE_EDGE_FALLING:
77 inttype_level = mask;
78 break;
79 case IRQ_TYPE_LEVEL_HIGH:
80 int_polarity = mask;
81 break;
82 case IRQ_TYPE_LEVEL_LOW:
83 break;
84 }
85 clrsetbits_le32(&gpio_port[gpio.port]->int_polarity,
86 mask, int_polarity);
87 clrsetbits_le32(&gpio_port[gpio.port]->inttype_level,
88 mask, inttype_level);
89
90 setbits_le32(&gpio_port[gpio.port]->inten, mask);
91 clrbits_le32(&gpio_port[gpio.port]->intmask, mask);
92}
93
94int gpio_irq_status(gpio_t gpio)
95{
96 uint32_t mask = BIT(gpio.num);
97 uint32_t int_status = read32(&gpio_port[gpio.port]->int_status);
98
99 if (!(int_status & mask))
100 return 0;
101
102 setbits_le32(&gpio_port[gpio.port]->porta_eoi, mask);
103 return 1;
104}
105
Shunqian Zheng015ae112016-04-20 20:35:09 +0800106int gpio_get(gpio_t gpio)
107{
108 return (read32(&gpio_port[gpio.port]->ext_porta) >> gpio.num) & 0x1;
109}
110
Julius Wernerffeee422018-03-27 16:22:00 -0700111void gpio_set(gpio_t gpio, int value)
Shunqian Zheng015ae112016-04-20 20:35:09 +0800112{
Shunqian Zheng015ae112016-04-20 20:35:09 +0800113 clrsetbits_le32(&gpio_port[gpio.port]->swporta_dr, 1 << gpio.num,
114 !!value << gpio.num);
Julius Wernerffeee422018-03-27 16:22:00 -0700115}
116
117void gpio_output(gpio_t gpio, int value)
118{
119 gpio_set(gpio, value);
Julius Werner2768a112016-09-01 22:55:58 -0700120 gpio_set_dir(gpio, GPIO_OUTPUT);
121 gpio_set_pull(gpio, GPIO_PULLNONE);
Shunqian Zheng015ae112016-04-20 20:35:09 +0800122}