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/cpu.h> 51 #include <machine/cpufunc.h> 52 #include <machine/resource.h> 53 54 #include <dev/fdt/fdt_common.h> 55 #include <dev/fdt/fdt_pinctrl.h> 56 #include <dev/ofw/openfirm.h> 57 #include <dev/ofw/ofw_bus.h> 58 #include <dev/ofw/ofw_bus_subr.h> 59 60 #include "ti_pinmux.h" 61 62 struct pincfg { 63 uint32_t reg; 64 uint32_t conf; 65 }; 66 67 static struct resource_spec ti_pinmux_res_spec[] = { 68 { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Control memory window */ 69 { -1, 0 } 70 }; 71 72 static struct ti_pinmux_softc *ti_pinmux_sc; 73 74 #define ti_pinmux_read_2(sc, reg) \ 75 bus_space_read_2((sc)->sc_bst, (sc)->sc_bsh, (reg)) 76 #define ti_pinmux_write_2(sc, reg, val) \ 77 bus_space_write_2((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 78 #define ti_pinmux_read_4(sc, reg) \ 79 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 80 #define ti_pinmux_write_4(sc, reg, val) \ 81 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 82 83 84 /** 85 * ti_padconf_devmap - Array of pins, should be defined one per SoC 86 * 87 * This array is typically defined in one of the targeted *_scm_pinumx.c 88 * files and is specific to the given SoC platform. Each entry in the array 89 * corresponds to an individual pin. 90 */ 91 extern const struct ti_pinmux_device ti_pinmux_dev; 92 93 94 /** 95 * ti_pinmux_padconf_from_name - searches the list of pads and returns entry 96 * with matching ball name. 97 * @ballname: the name of the ball 98 * 99 * RETURNS: 100 * A pointer to the matching padconf or NULL if the ball wasn't found. 101 */ 102 static const struct ti_pinmux_padconf* 103 ti_pinmux_padconf_from_name(const char *ballname) 104 { 105 const struct ti_pinmux_padconf *padconf; 106 107 padconf = ti_pinmux_dev.padconf; 108 while (padconf->ballname != NULL) { 109 if (strcmp(ballname, padconf->ballname) == 0) 110 return(padconf); 111 padconf++; 112 } 113 114 return (NULL); 115 } 116 117 /** 118 * ti_pinmux_padconf_set_internal - sets the muxmode and state for a pad/pin 119 * @padconf: pointer to the pad structure 120 * @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx" 121 * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_??? 122 * 123 * 124 * LOCKING: 125 * Internally locks it's own context. 126 * 127 * RETURNS: 128 * 0 on success. 129 * EINVAL if pin requested is outside valid range or already in use. 130 */ 131 static int 132 ti_pinmux_padconf_set_internal(struct ti_pinmux_softc *sc, 133 const struct ti_pinmux_padconf *padconf, 134 const char *muxmode, unsigned int state) 135 { 136 unsigned int mode; 137 uint16_t reg_val; 138 139 /* populate the new value for the PADCONF register */ 140 reg_val = (uint16_t)(state & ti_pinmux_dev.padconf_sate_mask); 141 142 /* find the new mode requested */ 143 for (mode = 0; mode < 8; mode++) { 144 if ((padconf->muxmodes[mode] != NULL) && 145 (strcmp(padconf->muxmodes[mode], muxmode) == 0)) { 146 break; 147 } 148 } 149 150 /* couldn't find the mux mode */ 151 if (mode >= 8) { 152 printf("Invalid mode \"%s\"\n", muxmode); 153 return (EINVAL); 154 } 155 156 /* set the mux mode */ 157 reg_val |= (uint16_t)(mode & ti_pinmux_dev.padconf_muxmode_mask); 158 159 if (bootverbose) 160 device_printf(sc->sc_dev, "setting internal %x for %s\n", 161 reg_val, muxmode); 162 /* write the register value (16-bit writes) */ 163 ti_pinmux_write_2(sc, padconf->reg_off, reg_val); 164 165 return (0); 166 } 167 168 /** 169 * ti_pinmux_padconf_set - sets the muxmode and state for a pad/pin 170 * @padname: the name of the pad, i.e. "c12" 171 * @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx" 172 * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_??? 173 * 174 * 175 * LOCKING: 176 * Internally locks it's own context. 177 * 178 * RETURNS: 179 * 0 on success. 180 * EINVAL if pin requested is outside valid range or already in use. 181 */ 182 int 183 ti_pinmux_padconf_set(const char *padname, const char *muxmode, unsigned int state) 184 { 185 const struct ti_pinmux_padconf *padconf; 186 187 if (!ti_pinmux_sc) 188 return (ENXIO); 189 190 /* find the pin in the devmap */ 191 padconf = ti_pinmux_padconf_from_name(padname); 192 if (padconf == NULL) 193 return (EINVAL); 194 195 return (ti_pinmux_padconf_set_internal(ti_pinmux_sc, padconf, muxmode, state)); 196 } 197 198 /** 199 * ti_pinmux_padconf_get - gets the muxmode and state for a pad/pin 200 * @padname: the name of the pad, i.e. "c12" 201 * @muxmode: upon return will contain the name of the muxmode of the pin 202 * @state: upon return will contain the state of the pad/pin 203 * 204 * 205 * LOCKING: 206 * Internally locks it's own context. 207 * 208 * RETURNS: 209 * 0 on success. 210 * EINVAL if pin requested is outside valid range or already in use. 211 */ 212 int 213 ti_pinmux_padconf_get(const char *padname, const char **muxmode, 214 unsigned int *state) 215 { 216 const struct ti_pinmux_padconf *padconf; 217 uint16_t reg_val; 218 219 if (!ti_pinmux_sc) 220 return (ENXIO); 221 222 /* find the pin in the devmap */ 223 padconf = ti_pinmux_padconf_from_name(padname); 224 if (padconf == NULL) 225 return (EINVAL); 226 227 /* read the register value (16-bit reads) */ 228 reg_val = ti_pinmux_read_2(ti_pinmux_sc, padconf->reg_off); 229 230 /* save the state */ 231 if (state) 232 *state = (reg_val & ti_pinmux_dev.padconf_sate_mask); 233 234 /* save the mode */ 235 if (muxmode) 236 *muxmode = padconf->muxmodes[(reg_val & ti_pinmux_dev.padconf_muxmode_mask)]; 237 238 return (0); 239 } 240 241 /** 242 * ti_pinmux_padconf_set_gpiomode - converts a pad to GPIO mode. 243 * @gpio: the GPIO pin number (0-195) 244 * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_??? 245 * 246 * 247 * 248 * LOCKING: 249 * Internally locks it's own context. 250 * 251 * RETURNS: 252 * 0 on success. 253 * EINVAL if pin requested is outside valid range or already in use. 254 */ 255 int 256 ti_pinmux_padconf_set_gpiomode(uint32_t gpio, unsigned int state) 257 { 258 const struct ti_pinmux_padconf *padconf; 259 uint16_t reg_val; 260 261 if (!ti_pinmux_sc) 262 return (ENXIO); 263 264 /* find the gpio pin in the padconf array */ 265 padconf = ti_pinmux_dev.padconf; 266 while (padconf->ballname != NULL) { 267 if (padconf->gpio_pin == gpio) 268 break; 269 padconf++; 270 } 271 if (padconf->ballname == NULL) 272 return (EINVAL); 273 274 /* populate the new value for the PADCONF register */ 275 reg_val = (uint16_t)(state & ti_pinmux_dev.padconf_sate_mask); 276 277 /* set the mux mode */ 278 reg_val |= (uint16_t)(padconf->gpio_mode & ti_pinmux_dev.padconf_muxmode_mask); 279 280 /* write the register value (16-bit writes) */ 281 ti_pinmux_write_2(ti_pinmux_sc, padconf->reg_off, reg_val); 282 283 return (0); 284 } 285 286 /** 287 * ti_pinmux_padconf_get_gpiomode - gets the current GPIO mode of the pin 288 * @gpio: the GPIO pin number (0-195) 289 * @state: upon return will contain the state 290 * 291 * 292 * 293 * LOCKING: 294 * Internally locks it's own context. 295 * 296 * RETURNS: 297 * 0 on success. 298 * EINVAL if pin requested is outside valid range or not configured as GPIO. 299 */ 300 int 301 ti_pinmux_padconf_get_gpiomode(uint32_t gpio, unsigned int *state) 302 { 303 const struct ti_pinmux_padconf *padconf; 304 uint16_t reg_val; 305 306 if (!ti_pinmux_sc) 307 return (ENXIO); 308 309 /* find the gpio pin in the padconf array */ 310 padconf = ti_pinmux_dev.padconf; 311 while (padconf->ballname != NULL) { 312 if (padconf->gpio_pin == gpio) 313 break; 314 padconf++; 315 } 316 if (padconf->ballname == NULL) 317 return (EINVAL); 318 319 /* read the current register settings */ 320 reg_val = ti_pinmux_read_2(ti_pinmux_sc, padconf->reg_off); 321 322 /* check to make sure the pins is configured as GPIO in the first state */ 323 if ((reg_val & ti_pinmux_dev.padconf_muxmode_mask) != padconf->gpio_mode) 324 return (EINVAL); 325 326 /* read and store the reset of the state, i.e. pull-up, pull-down, etc */ 327 if (state) 328 *state = (reg_val & ti_pinmux_dev.padconf_sate_mask); 329 330 return (0); 331 } 332 333 static int 334 ti_pinmux_configure_pins(device_t dev, phandle_t cfgxref) 335 { 336 struct pincfg *cfgtuples, *cfg; 337 phandle_t cfgnode; 338 int i, ntuples; 339 static struct ti_pinmux_softc *sc; 340 341 sc = device_get_softc(dev); 342 cfgnode = OF_node_from_xref(cfgxref); 343 ntuples = OF_getencprop_alloc(cfgnode, "pinctrl-single,pins", sizeof(*cfgtuples), 344 (void **)&cfgtuples); 345 346 if (ntuples < 0) 347 return (ENOENT); 348 349 if (ntuples == 0) 350 return (0); /* Empty property is not an error. */ 351 352 for (i = 0, cfg = cfgtuples; i < ntuples; i++, cfg++) { 353 if (bootverbose) { 354 char name[32]; 355 OF_getprop(cfgnode, "name", &name, sizeof(name)); 356 printf("%16s: muxreg 0x%04x muxval 0x%02x\n", 357 name, cfg->reg, cfg->conf); 358 } 359 360 /* write the register value (16-bit writes) */ 361 ti_pinmux_write_2(sc, cfg->reg, cfg->conf); 362 } 363 364 OF_prop_free(cfgtuples); 365 366 return (0); 367 } 368 369 /* 370 * Device part of OMAP SCM driver 371 */ 372 373 static int 374 ti_pinmux_probe(device_t dev) 375 { 376 if (!ofw_bus_status_okay(dev)) 377 return (ENXIO); 378 379 if (!ofw_bus_is_compatible(dev, "pinctrl-single")) 380 return (ENXIO); 381 382 if (ti_pinmux_sc) { 383 printf("%s: multiple pinctrl modules in device tree data, ignoring\n", 384 __func__); 385 return (EEXIST); 386 } 387 388 device_set_desc(dev, "TI Pinmux Module"); 389 return (BUS_PROBE_DEFAULT); 390 } 391 392 /** 393 * ti_pinmux_attach - attaches the pinmux to the simplebus 394 * @dev: new device 395 * 396 * RETURNS 397 * Zero on success or ENXIO if an error occuried. 398 */ 399 static int 400 ti_pinmux_attach(device_t dev) 401 { 402 struct ti_pinmux_softc *sc = device_get_softc(dev); 403 404 #if 0 405 if (ti_pinmux_sc) 406 return (ENXIO); 407 #endif 408 409 sc->sc_dev = dev; 410 411 if (bus_alloc_resources(dev, ti_pinmux_res_spec, sc->sc_res)) { 412 device_printf(dev, "could not allocate resources\n"); 413 return (ENXIO); 414 } 415 416 sc->sc_bst = rman_get_bustag(sc->sc_res[0]); 417 sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]); 418 419 if (ti_pinmux_sc == NULL) 420 ti_pinmux_sc = sc; 421 422 fdt_pinctrl_register(dev, "pinctrl-single,pins"); 423 fdt_pinctrl_configure_tree(dev); 424 425 return (0); 426 } 427 428 static device_method_t ti_pinmux_methods[] = { 429 DEVMETHOD(device_probe, ti_pinmux_probe), 430 DEVMETHOD(device_attach, ti_pinmux_attach), 431 432 /* fdt_pinctrl interface */ 433 DEVMETHOD(fdt_pinctrl_configure, ti_pinmux_configure_pins), 434 { 0, 0 } 435 }; 436 437 static driver_t ti_pinmux_driver = { 438 "ti_pinmux", 439 ti_pinmux_methods, 440 sizeof(struct ti_pinmux_softc), 441 }; 442 443 static devclass_t ti_pinmux_devclass; 444 445 DRIVER_MODULE(ti_pinmux, simplebus, ti_pinmux_driver, ti_pinmux_devclass, 0, 0); 446