1 /* $OpenBSD: octgpio.c,v 1.1 2019/01/12 16:59:38 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/octeon_model.h> 34 35 #define GPIO_BIT_CFG(x) (0x0000u + (x) * 8) 36 #define GPIO_BIT_CFG_INT_EN 0x0000000000000004ull 37 #define GPIO_BIT_CFG_RX_XOR 0x0000000000000002ull 38 #define GPIO_BIT_CFG_TX_OE 0x0000000000000001ull 39 #define GPIO_XBIT_CFG(x) (0x0100u + (x) * 8) 40 #define GPIO_RX_DAT 0x0080u 41 #define GPIO_TX_SET 0x0088u 42 #define GPIO_TX_CLR 0x0090u 43 44 #define GPIO_RD_8(sc, reg) \ 45 bus_space_read_8((sc)->sc_iot, (sc)->sc_ioh, (reg)) 46 #define GPIO_WR_8(sc, reg, val) \ 47 bus_space_write_8((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 48 49 struct octgpio_softc { 50 struct device sc_dev; 51 bus_space_tag_t sc_iot; 52 bus_space_handle_t sc_ioh; 53 struct gpio_controller sc_gc; 54 uint32_t sc_npins; 55 uint32_t sc_xbit; 56 }; 57 58 int octgpio_match(struct device *, void *, void *); 59 void octgpio_attach(struct device *, struct device *, void *); 60 61 void octgpio_config_pin(void *, uint32_t *, int); 62 int octgpio_get_pin(void *, uint32_t *); 63 void octgpio_set_pin(void *, uint32_t *, int); 64 65 const struct cfattach octgpio_ca = { 66 sizeof(struct octgpio_softc), octgpio_match, octgpio_attach 67 }; 68 69 struct cfdriver octgpio_cd = { 70 NULL, "octgpio", DV_DULL 71 }; 72 73 int 74 octgpio_match(struct device *parent, void *match, void *aux) 75 { 76 struct fdt_attach_args *faa = aux; 77 78 return OF_is_compatible(faa->fa_node, "cavium,octeon-3860-gpio") || 79 OF_is_compatible(faa->fa_node, "cavium,octeon-7890-gpio"); 80 } 81 82 void 83 octgpio_attach(struct device *parent, struct device *self, void *aux) 84 { 85 struct fdt_attach_args *faa = aux; 86 struct octgpio_softc *sc = (struct octgpio_softc *)self; 87 uint32_t chipid; 88 89 if (faa->fa_nreg != 1) { 90 printf(": no registers\n"); 91 return; 92 } 93 94 sc->sc_iot = faa->fa_iot; 95 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, faa->fa_reg[0].size, 96 0, &sc->sc_ioh)) { 97 printf(": can't map registers\n"); 98 return; 99 } 100 101 chipid = octeon_get_chipid(); 102 switch (octeon_model_family(chipid)) { 103 case OCTEON_MODEL_FAMILY_CN61XX: 104 case OCTEON_MODEL_FAMILY_CN63XX: 105 case OCTEON_MODEL_FAMILY_CN66XX: 106 case OCTEON_MODEL_FAMILY_CN68XX: 107 case OCTEON_MODEL_FAMILY_CN71XX: 108 sc->sc_npins = 20; 109 sc->sc_xbit = 16; 110 break; 111 case OCTEON_MODEL_FAMILY_CN73XX: 112 sc->sc_npins = 32; 113 sc->sc_xbit = 0; 114 break; 115 case OCTEON_MODEL_FAMILY_CN78XX: 116 sc->sc_npins = 20; 117 sc->sc_xbit = 0; 118 break; 119 default: 120 sc->sc_npins = 24; 121 sc->sc_xbit = 16; 122 break; 123 } 124 125 sc->sc_gc.gc_node = faa->fa_node; 126 sc->sc_gc.gc_cookie = sc; 127 sc->sc_gc.gc_config_pin = octgpio_config_pin; 128 sc->sc_gc.gc_get_pin = octgpio_get_pin; 129 sc->sc_gc.gc_set_pin = octgpio_set_pin; 130 gpio_controller_register(&sc->sc_gc); 131 132 printf(": %u pins, xbit %u\n", sc->sc_npins, sc->sc_xbit); 133 } 134 135 void 136 octgpio_config_pin(void *cookie, uint32_t *cells, int config) 137 { 138 struct octgpio_softc *sc = cookie; 139 uint64_t reg, value; 140 uint32_t pin = cells[0]; 141 142 if (pin >= sc->sc_npins) 143 return; 144 if (pin >= sc->sc_xbit) 145 reg = GPIO_XBIT_CFG(pin - sc->sc_xbit); 146 else 147 reg = GPIO_BIT_CFG(pin); 148 149 value = GPIO_RD_8(sc, reg); 150 if (config & GPIO_CONFIG_OUTPUT) 151 value |= GPIO_BIT_CFG_TX_OE; 152 else 153 value &= ~(GPIO_BIT_CFG_TX_OE | GPIO_BIT_CFG_RX_XOR); 154 /* There is no INT_EN bit on true XBIT pins. */ 155 value &= ~GPIO_BIT_CFG_INT_EN; 156 GPIO_WR_8(sc, reg, value); 157 } 158 159 int 160 octgpio_get_pin(void *cookie, uint32_t *cells) 161 { 162 struct octgpio_softc *sc = cookie; 163 uint32_t pin = cells[0]; 164 uint32_t flags = cells[1]; 165 int value; 166 167 if (pin >= sc->sc_npins) 168 return 0; 169 170 value = (GPIO_RD_8(sc, GPIO_RX_DAT) >> pin) & 1; 171 if (flags & GPIO_ACTIVE_LOW) 172 value = !value; 173 return value; 174 } 175 176 void 177 octgpio_set_pin(void *cookie, uint32_t *cells, int value) 178 { 179 struct octgpio_softc *sc = cookie; 180 uint32_t pin = cells[0]; 181 uint32_t flags = cells[1]; 182 183 if (pin >= sc->sc_npins) 184 return; 185 186 if (flags & GPIO_ACTIVE_LOW) 187 value = !value; 188 if (value) 189 GPIO_WR_8(sc, GPIO_TX_SET, 1ul << pin); 190 else 191 GPIO_WR_8(sc, GPIO_TX_CLR, 1ul << pin); 192 } 193