1 /* 2 * Copyright (c) 2010 3 * Ben Gray <ben.r.gray@gmail.com>. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Ben Gray. 17 * 4. The name of the company nor the name of the author may be used to 18 * endorse or promote products derived from this software without specific 19 * prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 30 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /** 34 * Exposes pinmux module to pinctrl-compatible interface 35 */ 36 #include <sys/cdefs.h> 37 __FBSDID("$FreeBSD$"); 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/kernel.h> 42 #include <sys/module.h> 43 #include <sys/bus.h> 44 #include <sys/resource.h> 45 #include <sys/rman.h> 46 #include <sys/lock.h> 47 #include <sys/mutex.h> 48 49 #include <machine/bus.h> 50 #include <machine/resource.h> 51 52 #include <dev/ofw/openfirm.h> 53 #include <dev/ofw/ofw_bus.h> 54 #include <dev/ofw/ofw_bus_subr.h> 55 #include <dev/fdt/fdt_pinctrl.h> 56 57 #include "ti_pinmux.h" 58 59 struct pincfg { 60 uint32_t reg; 61 uint32_t conf; 62 }; 63 64 static struct resource_spec ti_pinmux_res_spec[] = { 65 { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Control memory window */ 66 { -1, 0 } 67 }; 68 69 static struct ti_pinmux_softc *ti_pinmux_sc; 70 71 #define ti_pinmux_read_2(sc, reg) \ 72 bus_space_read_2((sc)->sc_bst, (sc)->sc_bsh, (reg)) 73 #define ti_pinmux_write_2(sc, reg, val) \ 74 bus_space_write_2((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 75 #define ti_pinmux_read_4(sc, reg) \ 76 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 77 #define ti_pinmux_write_4(sc, reg, val) \ 78 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 79 80 81 /** 82 * ti_padconf_devmap - Array of pins, should be defined one per SoC 83 * 84 * This array is typically defined in one of the targeted *_scm_pinumx.c 85 * files and is specific to the given SoC platform. Each entry in the array 86 * corresponds to an individual pin. 87 */ 88 extern const struct ti_pinmux_device ti_pinmux_dev; 89 90 91 /** 92 * ti_pinmux_padconf_from_name - searches the list of pads and returns entry 93 * with matching ball name. 94 * @ballname: the name of the ball 95 * 96 * RETURNS: 97 * A pointer to the matching padconf or NULL if the ball wasn't found. 98 */ 99 static const struct ti_pinmux_padconf* 100 ti_pinmux_padconf_from_name(const char *ballname) 101 { 102 const struct ti_pinmux_padconf *padconf; 103 104 padconf = ti_pinmux_dev.padconf; 105 while (padconf->ballname != NULL) { 106 if (strcmp(ballname, padconf->ballname) == 0) 107 return(padconf); 108 padconf++; 109 } 110 111 return (NULL); 112 } 113 114 /** 115 * ti_pinmux_padconf_set_internal - sets the muxmode and state for a pad/pin 116 * @padconf: pointer to the pad structure 117 * @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx" 118 * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_??? 119 * 120 * 121 * LOCKING: 122 * Internally locks it's own context. 123 * 124 * RETURNS: 125 * 0 on success. 126 * EINVAL if pin requested is outside valid range or already in use. 127 */ 128 static int 129 ti_pinmux_padconf_set_internal(struct ti_pinmux_softc *sc, 130 const struct ti_pinmux_padconf *padconf, 131 const char *muxmode, unsigned int state) 132 { 133 unsigned int mode; 134 uint16_t reg_val; 135 136 /* populate the new value for the PADCONF register */ 137 reg_val = (uint16_t)(state & ti_pinmux_dev.padconf_sate_mask); 138 139 /* find the new mode requested */ 140 for (mode = 0; mode < 8; mode++) { 141 if ((padconf->muxmodes[mode] != NULL) && 142 (strcmp(padconf->muxmodes[mode], muxmode) == 0)) { 143 break; 144 } 145 } 146 147 /* couldn't find the mux mode */ 148 if (mode >= 8) { 149 printf("Invalid mode \"%s\"\n", muxmode); 150 return (EINVAL); 151 } 152 153 /* set the mux mode */ 154 reg_val |= (uint16_t)(mode & ti_pinmux_dev.padconf_muxmode_mask); 155 156 if (bootverbose) 157 device_printf(sc->sc_dev, "setting internal %x for %s\n", 158 reg_val, muxmode); 159 /* write the register value (16-bit writes) */ 160 ti_pinmux_write_2(sc, padconf->reg_off, reg_val); 161 162 return (0); 163 } 164 165 /** 166 * ti_pinmux_padconf_set - sets the muxmode and state for a pad/pin 167 * @padname: the name of the pad, i.e. "c12" 168 * @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx" 169 * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_??? 170 * 171 * 172 * LOCKING: 173 * Internally locks it's own context. 174 * 175 * RETURNS: 176 * 0 on success. 177 * EINVAL if pin requested is outside valid range or already in use. 178 */ 179 int 180 ti_pinmux_padconf_set(const char *padname, const char *muxmode, unsigned int state) 181 { 182 const struct ti_pinmux_padconf *padconf; 183 184 if (!ti_pinmux_sc) 185 return (ENXIO); 186 187 /* find the pin in the devmap */ 188 padconf = ti_pinmux_padconf_from_name(padname); 189 if (padconf == NULL) 190 return (EINVAL); 191 192 return (ti_pinmux_padconf_set_internal(ti_pinmux_sc, padconf, muxmode, state)); 193 } 194 195 /** 196 * ti_pinmux_padconf_get - gets the muxmode and state for a pad/pin 197 * @padname: the name of the pad, i.e. "c12" 198 * @muxmode: upon return will contain the name of the muxmode of the pin 199 * @state: upon return will contain the state of the pad/pin 200 * 201 * 202 * LOCKING: 203 * Internally locks it's own context. 204 * 205 * RETURNS: 206 * 0 on success. 207 * EINVAL if pin requested is outside valid range or already in use. 208 */ 209 int 210 ti_pinmux_padconf_get(const char *padname, const char **muxmode, 211 unsigned int *state) 212 { 213 const struct ti_pinmux_padconf *padconf; 214 uint16_t reg_val; 215 216 if (!ti_pinmux_sc) 217 return (ENXIO); 218 219 /* find the pin in the devmap */ 220 padconf = ti_pinmux_padconf_from_name(padname); 221 if (padconf == NULL) 222 return (EINVAL); 223 224 /* read the register value (16-bit reads) */ 225 reg_val = ti_pinmux_read_2(ti_pinmux_sc, padconf->reg_off); 226 227 /* save the state */ 228 if (state) 229 *state = (reg_val & ti_pinmux_dev.padconf_sate_mask); 230 231 /* save the mode */ 232 if (muxmode) 233 *muxmode = padconf->muxmodes[(reg_val & ti_pinmux_dev.padconf_muxmode_mask)]; 234 235 return (0); 236 } 237 238 /** 239 * ti_pinmux_padconf_set_gpiomode - converts a pad to GPIO mode. 240 * @gpio: the GPIO pin number (0-195) 241 * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_??? 242 * 243 * 244 * 245 * LOCKING: 246 * Internally locks it's own context. 247 * 248 * RETURNS: 249 * 0 on success. 250 * EINVAL if pin requested is outside valid range or already in use. 251 */ 252 int 253 ti_pinmux_padconf_set_gpiomode(uint32_t gpio, unsigned int state) 254 { 255 const struct ti_pinmux_padconf *padconf; 256 uint16_t reg_val; 257 258 if (!ti_pinmux_sc) 259 return (ENXIO); 260 261 /* find the gpio pin in the padconf array */ 262 padconf = ti_pinmux_dev.padconf; 263 while (padconf->ballname != NULL) { 264 if (padconf->gpio_pin == gpio) 265 break; 266 padconf++; 267 } 268 if (padconf->ballname == NULL) 269 return (EINVAL); 270 271 /* populate the new value for the PADCONF register */ 272 reg_val = (uint16_t)(state & ti_pinmux_dev.padconf_sate_mask); 273 274 /* set the mux mode */ 275 reg_val |= (uint16_t)(padconf->gpio_mode & ti_pinmux_dev.padconf_muxmode_mask); 276 277 /* write the register value (16-bit writes) */ 278 ti_pinmux_write_2(ti_pinmux_sc, padconf->reg_off, reg_val); 279 280 return (0); 281 } 282 283 /** 284 * ti_pinmux_padconf_get_gpiomode - gets the current GPIO mode of the pin 285 * @gpio: the GPIO pin number (0-195) 286 * @state: upon return will contain the state 287 * 288 * 289 * 290 * LOCKING: 291 * Internally locks it's own context. 292 * 293 * RETURNS: 294 * 0 on success. 295 * EINVAL if pin requested is outside valid range or not configured as GPIO. 296 */ 297 int 298 ti_pinmux_padconf_get_gpiomode(uint32_t gpio, unsigned int *state) 299 { 300 const struct ti_pinmux_padconf *padconf; 301 uint16_t reg_val; 302 303 if (!ti_pinmux_sc) 304 return (ENXIO); 305 306 /* find the gpio pin in the padconf array */ 307 padconf = ti_pinmux_dev.padconf; 308 while (padconf->ballname != NULL) { 309 if (padconf->gpio_pin == gpio) 310 break; 311 padconf++; 312 } 313 if (padconf->ballname == NULL) 314 return (EINVAL); 315 316 /* read the current register settings */ 317 reg_val = ti_pinmux_read_2(ti_pinmux_sc, padconf->reg_off); 318 319 /* check to make sure the pins is configured as GPIO in the first state */ 320 if ((reg_val & ti_pinmux_dev.padconf_muxmode_mask) != padconf->gpio_mode) 321 return (EINVAL); 322 323 /* read and store the reset of the state, i.e. pull-up, pull-down, etc */ 324 if (state) 325 *state = (reg_val & ti_pinmux_dev.padconf_sate_mask); 326 327 return (0); 328 } 329 330 static int 331 ti_pinmux_configure_pins(device_t dev, phandle_t cfgxref) 332 { 333 struct pincfg *cfgtuples, *cfg; 334 phandle_t cfgnode; 335 int i, ntuples; 336 static struct ti_pinmux_softc *sc; 337 338 sc = device_get_softc(dev); 339 cfgnode = OF_node_from_xref(cfgxref); 340 ntuples = OF_getencprop_alloc(cfgnode, "pinctrl-single,pins", sizeof(*cfgtuples), 341 (void **)&cfgtuples); 342 343 if (ntuples < 0) 344 return (ENOENT); 345 346 if (ntuples == 0) 347 return (0); /* Empty property is not an error. */ 348 349 for (i = 0, cfg = cfgtuples; i < ntuples; i++, cfg++) { 350 if (bootverbose) { 351 char name[32]; 352 OF_getprop(cfgnode, "name", &name, sizeof(name)); 353 printf("%16s: muxreg 0x%04x muxval 0x%02x\n", 354 name, cfg->reg, cfg->conf); 355 } 356 357 /* write the register value (16-bit writes) */ 358 ti_pinmux_write_2(sc, cfg->reg, cfg->conf); 359 } 360 361 OF_prop_free(cfgtuples); 362 363 return (0); 364 } 365 366 /* 367 * Device part of OMAP SCM driver 368 */ 369 370 static int 371 ti_pinmux_probe(device_t dev) 372 { 373 if (!ofw_bus_status_okay(dev)) 374 return (ENXIO); 375 376 if (!ofw_bus_is_compatible(dev, "pinctrl-single")) 377 return (ENXIO); 378 379 if (ti_pinmux_sc) { 380 printf("%s: multiple pinctrl modules in device tree data, ignoring\n", 381 __func__); 382 return (EEXIST); 383 } 384 385 device_set_desc(dev, "TI Pinmux Module"); 386 return (BUS_PROBE_DEFAULT); 387 } 388 389 /** 390 * ti_pinmux_attach - attaches the pinmux to the simplebus 391 * @dev: new device 392 * 393 * RETURNS 394 * Zero on success or ENXIO if an error occuried. 395 */ 396 static int 397 ti_pinmux_attach(device_t dev) 398 { 399 struct ti_pinmux_softc *sc = device_get_softc(dev); 400 401 #if 0 402 if (ti_pinmux_sc) 403 return (ENXIO); 404 #endif 405 406 sc->sc_dev = dev; 407 408 if (bus_alloc_resources(dev, ti_pinmux_res_spec, sc->sc_res)) { 409 device_printf(dev, "could not allocate resources\n"); 410 return (ENXIO); 411 } 412 413 sc->sc_bst = rman_get_bustag(sc->sc_res[0]); 414 sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]); 415 416 if (ti_pinmux_sc == NULL) 417 ti_pinmux_sc = sc; 418 419 fdt_pinctrl_register(dev, "pinctrl-single,pins"); 420 fdt_pinctrl_configure_tree(dev); 421 422 return (0); 423 } 424 425 static device_method_t ti_pinmux_methods[] = { 426 DEVMETHOD(device_probe, ti_pinmux_probe), 427 DEVMETHOD(device_attach, ti_pinmux_attach), 428 429 /* fdt_pinctrl interface */ 430 DEVMETHOD(fdt_pinctrl_configure, ti_pinmux_configure_pins), 431 { 0, 0 } 432 }; 433 434 static driver_t ti_pinmux_driver = { 435 "ti_pinmux", 436 ti_pinmux_methods, 437 sizeof(struct ti_pinmux_softc), 438 }; 439 440 static devclass_t ti_pinmux_devclass; 441 442 DRIVER_MODULE(ti_pinmux, simplebus, ti_pinmux_driver, ti_pinmux_devclass, 0, 0); 443