xref: /openbsd/sys/arch/octeon/dev/octgpio.c (revision d415bd75)
1 /*	$OpenBSD: octgpio.c,v 1.2 2019/09/29 04:28:52 visa Exp $	*/
2 
3 /*
4  * Copyright (c) 2019 Visa Hankala
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * Driver for OCTEON GPIO controller.
21  */
22 
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/device.h>
26 #include <sys/malloc.h>
27 
28 #include <dev/ofw/fdt.h>
29 #include <dev/ofw/ofw_gpio.h>
30 #include <dev/ofw/openfirm.h>
31 
32 #include <machine/fdt.h>
33 #include <machine/octeonvar.h>
34 #include <machine/octeon_model.h>
35 
36 #define GPIO_BIT_CFG(x)		(0x0000u + (x) * 8)
37 #define   GPIO_BIT_CFG_OUTPUT_SEL_M	0x00000000001f0000ull
38 #define   GPIO_BIT_CFG_OUTPUT_SEL_S	16
39 #define   GPIO_BIT_CFG_INT_EN		0x0000000000000004ull
40 #define   GPIO_BIT_CFG_RX_XOR		0x0000000000000002ull
41 #define   GPIO_BIT_CFG_TX_OE		0x0000000000000001ull
42 #define GPIO_XBIT_CFG(x)	(0x0100u + (x) * 8)
43 #define GPIO_RX_DAT		0x0080u
44 #define GPIO_TX_SET		0x0088u
45 #define GPIO_TX_CLR		0x0090u
46 
47 #define GPIO_RD_8(sc, reg) \
48 	bus_space_read_8((sc)->sc_iot, (sc)->sc_ioh, (reg))
49 #define GPIO_WR_8(sc, reg, val) \
50 	bus_space_write_8((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
51 
52 struct octgpio_softc {
53 	struct device		 sc_dev;
54 	bus_space_tag_t		 sc_iot;
55 	bus_space_handle_t	 sc_ioh;
56 	struct gpio_controller	 sc_gc;
57 	uint32_t		 sc_npins;
58 	uint32_t		 sc_xbit;
59 };
60 
61 int	octgpio_match(struct device *, void *, void *);
62 void	octgpio_attach(struct device *, struct device *, void *);
63 
64 void	octgpio_config_pin(void *, uint32_t *, int);
65 int	octgpio_get_pin(void *, uint32_t *);
66 void	octgpio_set_pin(void *, uint32_t *, int);
67 
68 const struct cfattach octgpio_ca = {
69 	sizeof(struct octgpio_softc), octgpio_match, octgpio_attach
70 };
71 
72 struct cfdriver octgpio_cd = {
73 	NULL, "octgpio", DV_DULL
74 };
75 
76 int
77 octgpio_match(struct device *parent, void *match, void *aux)
78 {
79 	struct fdt_attach_args *faa = aux;
80 
81 	return OF_is_compatible(faa->fa_node, "cavium,octeon-3860-gpio") ||
82 	    OF_is_compatible(faa->fa_node, "cavium,octeon-7890-gpio");
83 }
84 
85 void
86 octgpio_attach(struct device *parent, struct device *self, void *aux)
87 {
88 	struct fdt_attach_args *faa = aux;
89 	struct octgpio_softc *sc = (struct octgpio_softc *)self;
90 	uint32_t chipid;
91 
92 	if (faa->fa_nreg != 1) {
93 		printf(": no registers\n");
94 		return;
95 	}
96 
97 	sc->sc_iot = faa->fa_iot;
98 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, faa->fa_reg[0].size,
99 	    0, &sc->sc_ioh)) {
100 		printf(": can't map registers\n");
101 		return;
102 	}
103 
104 	chipid = octeon_get_chipid();
105 	switch (octeon_model_family(chipid)) {
106 	case OCTEON_MODEL_FAMILY_CN61XX:
107 	case OCTEON_MODEL_FAMILY_CN63XX:
108 	case OCTEON_MODEL_FAMILY_CN66XX:
109 	case OCTEON_MODEL_FAMILY_CN68XX:
110 	case OCTEON_MODEL_FAMILY_CN71XX:
111 		sc->sc_npins = 20;
112 		sc->sc_xbit = 16;
113 		break;
114 	case OCTEON_MODEL_FAMILY_CN73XX:
115 		sc->sc_npins = 32;
116 		sc->sc_xbit = 0;
117 		break;
118 	case OCTEON_MODEL_FAMILY_CN78XX:
119 		sc->sc_npins = 20;
120 		sc->sc_xbit = 0;
121 		break;
122 	default:
123 		sc->sc_npins = 24;
124 		sc->sc_xbit = 16;
125 		break;
126 	}
127 
128 	sc->sc_gc.gc_node = faa->fa_node;
129 	sc->sc_gc.gc_cookie = sc;
130 	sc->sc_gc.gc_config_pin = octgpio_config_pin;
131 	sc->sc_gc.gc_get_pin = octgpio_get_pin;
132 	sc->sc_gc.gc_set_pin = octgpio_set_pin;
133 	gpio_controller_register(&sc->sc_gc);
134 
135 	printf(": %u pins, xbit %u\n", sc->sc_npins, sc->sc_xbit);
136 }
137 
138 void
139 octgpio_config_pin(void *cookie, uint32_t *cells, int config)
140 {
141 	struct octgpio_softc *sc = cookie;
142 	uint64_t output_sel, reg, value;
143 	uint32_t pin = cells[0];
144 
145 	if (pin >= sc->sc_npins)
146 		return;
147 	if (pin >= sc->sc_xbit)
148 		reg = GPIO_XBIT_CFG(pin - sc->sc_xbit);
149 	else
150 		reg = GPIO_BIT_CFG(pin);
151 
152 	value = GPIO_RD_8(sc, reg);
153 	if (config & GPIO_CONFIG_OUTPUT) {
154 		value |= GPIO_BIT_CFG_TX_OE;
155 
156 		switch (config & GPIO_CONFIG_MD_OUTPUT_SEL_MASK) {
157 		case GPIO_CONFIG_MD_USB0_VBUS_CTRL:
158 			output_sel = 0x14;
159 			break;
160 		case GPIO_CONFIG_MD_USB1_VBUS_CTRL:
161 			output_sel = 0x19;
162 			break;
163 		default:
164 			output_sel = 0;
165 			break;
166 		}
167 		value &= ~GPIO_BIT_CFG_OUTPUT_SEL_M;
168 		value |= output_sel << GPIO_BIT_CFG_OUTPUT_SEL_S;
169 	} else
170 		value &= ~(GPIO_BIT_CFG_TX_OE | GPIO_BIT_CFG_RX_XOR);
171 	/* There is no INT_EN bit on true XBIT pins. */
172 	value &= ~GPIO_BIT_CFG_INT_EN;
173 	GPIO_WR_8(sc, reg, value);
174 }
175 
176 int
177 octgpio_get_pin(void *cookie, uint32_t *cells)
178 {
179 	struct octgpio_softc *sc = cookie;
180 	uint32_t pin = cells[0];
181 	uint32_t flags = cells[1];
182 	int value;
183 
184 	if (pin >= sc->sc_npins)
185 		return 0;
186 
187 	value = (GPIO_RD_8(sc, GPIO_RX_DAT) >> pin) & 1;
188 	if (flags & GPIO_ACTIVE_LOW)
189 		value = !value;
190 	return value;
191 }
192 
193 void
194 octgpio_set_pin(void *cookie, uint32_t *cells, int value)
195 {
196 	struct octgpio_softc *sc = cookie;
197 	uint32_t pin = cells[0];
198 	uint32_t flags = cells[1];
199 
200 	if (pin >= sc->sc_npins)
201 		return;
202 
203 	if (flags & GPIO_ACTIVE_LOW)
204 		value = !value;
205 	if (value)
206 		GPIO_WR_8(sc, GPIO_TX_SET, 1ul << pin);
207 	else
208 		GPIO_WR_8(sc, GPIO_TX_CLR, 1ul << pin);
209 }
210