1 /* $OpenBSD: mvpinctrl.c,v 1.1 2017/08/25 20:00:35 patrick Exp $ */ 2 /* 3 * Copyright (c) 2013,2016 Patrick Wildt <patrick@blueri.se> 4 * Copyright (c) 2016 Mark Kettenis <kettenis@openbsd.org> 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 #include <sys/param.h> 20 #include <sys/systm.h> 21 #include <sys/device.h> 22 #include <sys/malloc.h> 23 24 #include <machine/intr.h> 25 #include <machine/bus.h> 26 #include <machine/fdt.h> 27 28 #include <dev/ofw/openfirm.h> 29 #include <dev/ofw/ofw_pinctrl.h> 30 #include <dev/ofw/fdt.h> 31 32 #define HREAD4(sc, reg) \ 33 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 34 #define HWRITE4(sc, reg, val) \ 35 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 36 #define HSET4(sc, reg, bits) \ 37 HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits)) 38 #define HCLR4(sc, reg, bits) \ 39 HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits)) 40 41 struct mvpinctrl_pin { 42 char *pin; 43 char *function; 44 int value; 45 int pid; 46 }; 47 48 struct mvpinctrl_softc { 49 struct device sc_dev; 50 bus_space_tag_t sc_iot; 51 bus_space_handle_t sc_ioh; 52 struct mvpinctrl_pin *sc_pins; 53 int sc_npins; 54 }; 55 56 int mvpinctrl_match(struct device *, void *, void *); 57 void mvpinctrl_attach(struct device *, struct device *, void *); 58 int mvpinctrl_pinctrl(uint32_t, void *); 59 60 struct cfattach mvpinctrl_ca = { 61 sizeof (struct mvpinctrl_softc), mvpinctrl_match, mvpinctrl_attach 62 }; 63 64 struct cfdriver mvpinctrl_cd = { 65 NULL, "mvpinctrl", DV_DULL 66 }; 67 68 #define STR_HELPER(x) #x 69 #define STR(x) STR_HELPER(x) 70 #define MPP(id, func, val) { STR(mpp ## id), func, val, id } 71 72 struct mvpinctrl_pin mv88f6828_pins[] = { 73 MPP(4, "ge", 1), 74 MPP(5, "ge", 1), 75 MPP(6, "ge0", 1), 76 MPP(7, "ge0", 1), 77 MPP(8, "ge0", 1), 78 MPP(9, "ge0", 1), 79 MPP(10, "ge0", 1), 80 MPP(11, "ge0", 1), 81 MPP(12, "ge0", 1), 82 MPP(13, "ge0", 1), 83 MPP(14, "ge0", 1), 84 MPP(15, "ge0", 1), 85 MPP(16, "ge0", 1), 86 MPP(17, "ge0", 1), 87 MPP(20, "gpio", 0), 88 MPP(21, "sd0", 4), 89 MPP(23, "gpio", 0), 90 MPP(28, "sd0", 4), 91 MPP(37, "sd0", 4), 92 MPP(38, "sd0", 4), 93 MPP(39, "sd0", 4), 94 MPP(40, "sd0", 4), 95 MPP(41, "gpio", 0), 96 MPP(45, "ref", 1), 97 MPP(46, "ref", 1), 98 }; 99 100 int 101 mvpinctrl_match(struct device *parent, void *match, void *aux) 102 { 103 struct fdt_attach_args *faa = aux; 104 105 return OF_is_compatible(faa->fa_node, "marvell,mv88f6828-pinctrl"); 106 } 107 108 void 109 mvpinctrl_attach(struct device *parent, struct device *self, void *aux) 110 { 111 struct fdt_attach_args *faa = aux; 112 struct mvpinctrl_softc *sc = (struct mvpinctrl_softc *) self; 113 114 sc->sc_iot = faa->fa_iot; 115 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 116 faa->fa_reg[0].size, 0, &sc->sc_ioh)) 117 panic("mvpinctrl_attach: bus_space_map failed!"); 118 119 sc->sc_pins = mv88f6828_pins; 120 sc->sc_npins = sizeof(mv88f6828_pins) / sizeof(struct mvpinctrl_pin); 121 pinctrl_register(faa->fa_node, mvpinctrl_pinctrl, sc); 122 123 printf("\n"); 124 } 125 126 int 127 mvpinctrl_pinctrl(uint32_t phandle, void *cookie) 128 { 129 struct mvpinctrl_softc *sc = cookie; 130 char *pins, *pin, *func; 131 int i, flen, plen, node; 132 133 node = OF_getnodebyphandle(phandle); 134 if (node == 0) 135 return -1; 136 137 flen = OF_getproplen(node, "marvell,function"); 138 if (flen <= 0) 139 return -1; 140 141 func = malloc(flen, M_TEMP, M_WAITOK); 142 OF_getprop(node, "marvell,function", func, flen); 143 144 plen = OF_getproplen(node, "marvell,pins"); 145 if (plen <= 0) 146 return -1; 147 148 pin = pins = malloc(plen, M_TEMP, M_WAITOK); 149 OF_getprop(node, "marvell,pins", pins, plen); 150 151 while (plen > 0) { 152 int found = 0; 153 154 for (i = 0; i < sc->sc_npins; i++) { 155 uint32_t off, shift; 156 157 if (strcmp(sc->sc_pins[i].pin, pin)) 158 continue; 159 if (strcmp(sc->sc_pins[i].function, func)) 160 continue; 161 162 found++; 163 164 off = (sc->sc_pins[i].pid / 8) * sizeof(uint32_t); 165 shift = (sc->sc_pins[i].pid % 8) * 4; 166 167 HWRITE4(sc, off, (HREAD4(sc, off) & ~(0xf << shift)) | 168 (sc->sc_pins[i].value << shift)); 169 } 170 171 if (found == 0) 172 printf("%s: unsupported pin %s function %s\n", 173 sc->sc_dev.dv_xname, pin, func); 174 175 plen -= strlen(pin) + 1; 176 pin += strlen(pin) + 1; 177 } 178 179 free(func, M_TEMP, flen); 180 free(pins, M_TEMP, plen); 181 return 0; 182 } 183