xref: /aosp_15_r20/external/coreboot/src/soc/cavium/cn81xx/gpio.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <soc/gpio.h>
5 #include <device/mmio.h>
6 #include <endian.h>
7 #include <soc/addressmap.h>
8 
9 union gpio_const {
10 	u64 u;
11 	struct {
12 		u64 gpios:8; /** Number of GPIOs implemented */
13 		u64 pp:8; /** Number of PP vectors */
14 		u64:48; /* Reserved */
15 	} s;
16 };
17 union bit_cfg {
18 	u64 u;
19 	struct {
20 		u64 tx_oe	: 1; /* Output Enable */
21 		u64 xor		: 1; /* Invert */
22 		u64 int_en	: 1; /* Interrupt Enable */
23 		u64 int_type	: 1; /* Type of Interrupt */
24 		u64 filt_cnt	: 4; /* Glitch filter counter */
25 		u64 filt_sel	: 4; /* Glitch filter select */
26 		u64 tx_od	: 1; /* Set Output to Open Drain */
27 		u64		: 3;
28 		u64 pin_sel	: 10; /* Select type of pin */
29 		u64		: 38;
30 	} s;
31 };
32 
33 struct cavium_gpio {
34 	u64 rx_dat;
35 	u64 tx_set;
36 	u64 tx_clr;
37 	u64 multicast;
38 	u64 ocla_exten_trg;
39 	u64 strap;
40 	u64 reserved[12];
41 	union gpio_const gpio_const; /* Offset 90 */
42 	u64 reserved2[109];
43 	union bit_cfg bit_cfg[48]; /* Offset 400 */
44 };
45 
46 /* Base address of GPIO BAR */
gpio_get_baseaddr(void)47 static const void *gpio_get_baseaddr(void)
48 {
49 	return (const void *)GPIO_PF_BAR0;
50 }
51 
52 /* Number of GPIO pins. Usually 48. */
gpio_pin_count(void)53 gpio_t gpio_pin_count(void)
54 {
55 	struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
56 	union gpio_const gpio_const;
57 
58 	gpio_const.u = read64(&regs->gpio_const.u);
59 
60 	if (gpio_const.s.gpios > 64)
61 		return 64; // FIXME: Add support for more than 64 GPIOs
62 	return gpio_const.s.gpios;
63 }
64 
65 /* Set GPIO to software control and direction INPUT */
gpio_input(gpio_t gpio)66 void gpio_input(gpio_t gpio)
67 {
68 	struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
69 	union bit_cfg bit_cfg;
70 
71 	if (gpio >= gpio_pin_count())
72 		return;
73 
74 	printk(BIOS_SPEW, "GPIO(%u): direction input\n", gpio);
75 
76 	bit_cfg.u = read64(&regs->bit_cfg[gpio]);
77 	bit_cfg.s.pin_sel = 0;
78 	bit_cfg.s.tx_oe = 0;
79 	write64(&regs->bit_cfg[gpio], bit_cfg.u);
80 }
81 
82 /* Set GPIO of direction OUTPUT to level */
gpio_set(gpio_t gpio,int value)83 void gpio_set(gpio_t gpio, int value)
84 {
85 	struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
86 
87 	if (gpio >= gpio_pin_count())
88 		return;
89 
90 	printk(BIOS_SPEW, "GPIO(%u): level: %u\n", gpio, !!value);
91 
92 	if (value)
93 		write64(&regs->tx_set, 1ULL << gpio);
94 	else
95 		write64(&regs->tx_clr, 1ULL << gpio);
96 }
97 
98 /* Set GPIO direction to OUTPUT with level */
gpio_output(gpio_t gpio,int value)99 void gpio_output(gpio_t gpio, int value)
100 {
101 	struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
102 	union bit_cfg bit_cfg;
103 
104 	if (gpio >= gpio_pin_count())
105 		return;
106 
107 	gpio_set(gpio, value);
108 
109 	printk(BIOS_SPEW, "GPIO(%u): direction output with level: %u\n", gpio,
110 	       !!value);
111 
112 	bit_cfg.u = read64(&regs->bit_cfg[gpio]);
113 	bit_cfg.s.pin_sel = 0;
114 	bit_cfg.s.tx_oe = 1;
115 	write64(&regs->bit_cfg[gpio], bit_cfg.u);
116 }
117 
118 /* Set GPIO invert flag, that affects INPUT and OUTPUT */
gpio_invert(gpio_t gpio,int value)119 void gpio_invert(gpio_t gpio, int value)
120 {
121 	struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
122 	union bit_cfg bit_cfg;
123 
124 	if (gpio >= gpio_pin_count())
125 		return;
126 
127 	bit_cfg.u = read64(&regs->bit_cfg[gpio]);
128 	bit_cfg.s.xor = !!value;
129 	write64(&regs->bit_cfg[gpio], bit_cfg.u);
130 
131 	printk(BIOS_SPEW, "GPIO(%u): invert: %s\n", gpio, value ? "ON" : "OFF");
132 }
133 
134 /* Read GPIO level with direction set to INPUT */
gpio_get(gpio_t gpio)135 int gpio_get(gpio_t gpio)
136 {
137 	struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
138 
139 	if (gpio >= gpio_pin_count())
140 		return 0;
141 
142 	const u64 reg = read64(&regs->rx_dat);
143 	printk(BIOS_SPEW, "GPIO(%u): input: %u\n", gpio,
144 	       !!(reg & (1ULL << gpio)));
145 
146 	return !!(reg & (1ULL << gpio));
147 }
148 
149 /* Read GPIO STRAP level sampled at cold boot */
gpio_strap_value(gpio_t gpio)150 int gpio_strap_value(gpio_t gpio)
151 {
152 	struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
153 
154 	if (gpio >= gpio_pin_count())
155 		return 0;
156 
157 	const u64 reg = read64(&regs->strap);
158 	printk(BIOS_SPEW, "GPIO(%u): strap: %u\n", gpio,
159 	       !!(reg & (1ULL << gpio)));
160 
161 	return !!(reg & (1ULL << gpio));
162 }
163 
164 /* FIXME: Parse devicetree ? */
gpio_init(void)165 void gpio_init(void)
166 {
167 	const size_t pin_count = gpio_pin_count();
168 
169 	printk(BIOS_DEBUG, "GPIO: base address: %p, pin count: %zd\n",
170 	       gpio_get_baseaddr(), pin_count);
171 
172 	if (!pin_count)
173 		return;
174 }
175 
gpio_input_pulldown(gpio_t gpio)176 void gpio_input_pulldown(gpio_t gpio)
177 {
178 }
179 
gpio_input_pullup(gpio_t gpio)180 void gpio_input_pullup(gpio_t gpio)
181 {
182 }
183