1 /* $OpenBSD: mvgpio.c,v 1.2 2021/05/07 01:54:17 jsg Exp $ */ 2 /* 3 * Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/device.h> 21 22 #include <machine/intr.h> 23 #include <machine/bus.h> 24 #include <machine/fdt.h> 25 26 #include <dev/ofw/openfirm.h> 27 #include <dev/ofw/ofw_gpio.h> 28 #include <dev/ofw/ofw_misc.h> 29 #include <dev/ofw/fdt.h> 30 31 /* Registers. */ 32 #define GPIO_DOUT 0x0000 33 #define GPIO_DOUTEN 0x0004 34 #define GPIO_DINACTLOW 0x000c 35 #define GPIO_DIN 0x0010 36 37 #define HREAD4(sc, reg) \ 38 (regmap_read_4((sc)->sc_rm, (sc)->sc_offset + (reg))) 39 #define HWRITE4(sc, reg, val) \ 40 regmap_write_4((sc)->sc_rm, (sc)->sc_offset + (reg), (val)) 41 #define HSET4(sc, reg, bits) \ 42 HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits)) 43 #define HCLR4(sc, reg, bits) \ 44 HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits)) 45 46 struct mvgpio_softc { 47 struct device sc_dev; 48 struct regmap *sc_rm; 49 bus_size_t sc_offset; 50 51 struct gpio_controller sc_gc; 52 }; 53 54 int mvgpio_match(struct device *, void *, void *); 55 void mvgpio_attach(struct device *, struct device *, void *); 56 57 struct cfattach mvgpio_ca = { 58 sizeof (struct mvgpio_softc), mvgpio_match, mvgpio_attach 59 }; 60 61 struct cfdriver mvgpio_cd = { 62 NULL, "mvgpio", DV_DULL 63 }; 64 65 void mvgpio_config_pin(void *, uint32_t *, int); 66 int mvgpio_get_pin(void *, uint32_t *); 67 void mvgpio_set_pin(void *, uint32_t *, int); 68 69 int 70 mvgpio_match(struct device *parent, void *match, void *aux) 71 { 72 struct fdt_attach_args *faa = aux; 73 74 return OF_is_compatible(faa->fa_node, "marvell,armada-8k-gpio"); 75 } 76 77 void 78 mvgpio_attach(struct device *parent, struct device *self, void *aux) 79 { 80 struct mvgpio_softc *sc = (struct mvgpio_softc *)self; 81 struct fdt_attach_args *faa = aux; 82 83 sc->sc_rm = regmap_bynode(OF_parent(faa->fa_node)); 84 if (sc->sc_rm == NULL) { 85 printf(": no registers\n"); 86 return; 87 } 88 sc->sc_offset = OF_getpropint(faa->fa_node, "offset", 0); 89 90 sc->sc_gc.gc_node = faa->fa_node; 91 sc->sc_gc.gc_cookie = sc; 92 sc->sc_gc.gc_config_pin = mvgpio_config_pin; 93 sc->sc_gc.gc_get_pin = mvgpio_get_pin; 94 sc->sc_gc.gc_set_pin = mvgpio_set_pin; 95 gpio_controller_register(&sc->sc_gc); 96 97 printf("\n"); 98 } 99 100 void 101 mvgpio_config_pin(void *cookie, uint32_t *cells, int config) 102 { 103 struct mvgpio_softc *sc = cookie; 104 uint32_t pin = cells[0]; 105 106 if (pin >= 32) 107 return; 108 109 if (config & GPIO_CONFIG_OUTPUT) 110 HCLR4(sc, GPIO_DOUTEN, (1 << pin)); 111 else 112 HSET4(sc, GPIO_DOUTEN, (1 << pin)); 113 } 114 115 int 116 mvgpio_get_pin(void *cookie, uint32_t *cells) 117 { 118 struct mvgpio_softc *sc = cookie; 119 uint32_t pin = cells[0]; 120 uint32_t flags = cells[1]; 121 uint32_t reg; 122 int val; 123 124 if (pin >= 32) 125 return 0; 126 127 reg = HREAD4(sc, GPIO_DIN); 128 reg ^= HREAD4(sc, GPIO_DINACTLOW); 129 reg &= (1 << pin); 130 val = (reg >> pin) & 1; 131 if (flags & GPIO_ACTIVE_LOW) 132 val = !val; 133 return val; 134 } 135 136 void 137 mvgpio_set_pin(void *cookie, uint32_t *cells, int val) 138 { 139 struct mvgpio_softc *sc = cookie; 140 uint32_t pin = cells[0]; 141 uint32_t flags = cells[1]; 142 143 if (pin >= 32) 144 return; 145 146 if (flags & GPIO_ACTIVE_LOW) 147 val = !val; 148 if (val) 149 HSET4(sc, GPIO_DOUT, (1 << pin)); 150 else 151 HCLR4(sc, GPIO_DOUT, (1 << pin)); 152 } 153