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 * SCM - System Control Module 35 * 36 * Hopefully in the end this module will contain a bunch of utility functions 37 * for configuring and querying the general system control registers, but for 38 * now it only does pin(pad) multiplexing. 39 * 40 * This is different from the GPIO module in that it is used to configure the 41 * pins between modules not just GPIO input/output. 42 * 43 * This file contains the generic top level driver, however it relies on chip 44 * specific settings and therefore expects an array of ti_scm_padconf structs 45 * call ti_padconf_devmap to be located somewhere in the kernel. 46 * 47 */ 48 #include <sys/cdefs.h> 49 __FBSDID("$FreeBSD$"); 50 51 #include <sys/param.h> 52 #include <sys/systm.h> 53 #include <sys/kernel.h> 54 #include <sys/module.h> 55 #include <sys/bus.h> 56 #include <sys/resource.h> 57 #include <sys/rman.h> 58 #include <sys/lock.h> 59 #include <sys/mutex.h> 60 61 #include <machine/bus.h> 62 #include <machine/cpu.h> 63 #include <machine/cpufunc.h> 64 #include <machine/frame.h> 65 #include <machine/resource.h> 66 67 #include <dev/fdt/fdt_common.h> 68 #include <dev/ofw/openfirm.h> 69 #include <dev/ofw/ofw_bus.h> 70 #include <dev/ofw/ofw_bus_subr.h> 71 72 #include "ti_scm.h" 73 74 static struct resource_spec ti_scm_res_spec[] = { 75 { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Control memory window */ 76 { -1, 0 } 77 }; 78 79 static struct ti_scm_softc *ti_scm_sc; 80 81 #define ti_scm_read_2(sc, reg) \ 82 bus_space_read_2((sc)->sc_bst, (sc)->sc_bsh, (reg)) 83 #define ti_scm_write_2(sc, reg, val) \ 84 bus_space_write_2((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 85 #define ti_scm_read_4(sc, reg) \ 86 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 87 #define ti_scm_write_4(sc, reg, val) \ 88 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 89 90 91 /** 92 * ti_padconf_devmap - Array of pins, should be defined one per SoC 93 * 94 * This array is typically defined in one of the targeted *_scm_pinumx.c 95 * files and is specific to the given SoC platform. Each entry in the array 96 * corresponds to an individual pin. 97 */ 98 extern const struct ti_scm_device ti_scm_dev; 99 100 101 /** 102 * ti_scm_padconf_from_name - searches the list of pads and returns entry 103 * with matching ball name. 104 * @ballname: the name of the ball 105 * 106 * RETURNS: 107 * A pointer to the matching padconf or NULL if the ball wasn't found. 108 */ 109 static const struct ti_scm_padconf* 110 ti_scm_padconf_from_name(const char *ballname) 111 { 112 const struct ti_scm_padconf *padconf; 113 114 padconf = ti_scm_dev.padconf; 115 while (padconf->ballname != NULL) { 116 if (strcmp(ballname, padconf->ballname) == 0) 117 return(padconf); 118 padconf++; 119 } 120 121 return (NULL); 122 } 123 124 /** 125 * ti_scm_padconf_set_internal - sets the muxmode and state for a pad/pin 126 * @padconf: pointer to the pad structure 127 * @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx" 128 * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_??? 129 * 130 * 131 * LOCKING: 132 * Internally locks it's own context. 133 * 134 * RETURNS: 135 * 0 on success. 136 * EINVAL if pin requested is outside valid range or already in use. 137 */ 138 static int 139 ti_scm_padconf_set_internal(struct ti_scm_softc *sc, 140 const struct ti_scm_padconf *padconf, 141 const char *muxmode, unsigned int state) 142 { 143 unsigned int mode; 144 uint16_t reg_val; 145 146 /* populate the new value for the PADCONF register */ 147 reg_val = (uint16_t)(state & ti_scm_dev.padconf_sate_mask); 148 149 /* find the new mode requested */ 150 for (mode = 0; mode < 8; mode++) { 151 if ((padconf->muxmodes[mode] != NULL) && 152 (strcmp(padconf->muxmodes[mode], muxmode) == 0)) { 153 break; 154 } 155 } 156 157 /* couldn't find the mux mode */ 158 if (mode >= 8) { 159 printf("Invalid mode \"%s\"\n", muxmode); 160 return (EINVAL); 161 } 162 163 /* set the mux mode */ 164 reg_val |= (uint16_t)(mode & ti_scm_dev.padconf_muxmode_mask); 165 166 if (bootverbose) 167 device_printf(sc->sc_dev, "setting internal %x for %s\n", 168 reg_val, muxmode); 169 /* write the register value (16-bit writes) */ 170 ti_scm_write_2(sc, padconf->reg_off, reg_val); 171 172 return (0); 173 } 174 175 /** 176 * ti_scm_padconf_set - sets the muxmode and state for a pad/pin 177 * @padname: the name of the pad, i.e. "c12" 178 * @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx" 179 * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_??? 180 * 181 * 182 * LOCKING: 183 * Internally locks it's own context. 184 * 185 * RETURNS: 186 * 0 on success. 187 * EINVAL if pin requested is outside valid range or already in use. 188 */ 189 int 190 ti_scm_padconf_set(const char *padname, const char *muxmode, unsigned int state) 191 { 192 const struct ti_scm_padconf *padconf; 193 194 if (!ti_scm_sc) 195 return (ENXIO); 196 197 /* find the pin in the devmap */ 198 padconf = ti_scm_padconf_from_name(padname); 199 if (padconf == NULL) 200 return (EINVAL); 201 202 return (ti_scm_padconf_set_internal(ti_scm_sc, padconf, muxmode, state)); 203 } 204 205 /** 206 * ti_scm_padconf_get - gets the muxmode and state for a pad/pin 207 * @padname: the name of the pad, i.e. "c12" 208 * @muxmode: upon return will contain the name of the muxmode of the pin 209 * @state: upon return will contain the state of the pad/pin 210 * 211 * 212 * LOCKING: 213 * Internally locks it's own context. 214 * 215 * RETURNS: 216 * 0 on success. 217 * EINVAL if pin requested is outside valid range or already in use. 218 */ 219 int 220 ti_scm_padconf_get(const char *padname, const char **muxmode, 221 unsigned int *state) 222 { 223 const struct ti_scm_padconf *padconf; 224 uint16_t reg_val; 225 226 if (!ti_scm_sc) 227 return (ENXIO); 228 229 /* find the pin in the devmap */ 230 padconf = ti_scm_padconf_from_name(padname); 231 if (padconf == NULL) 232 return (EINVAL); 233 234 /* read the register value (16-bit reads) */ 235 reg_val = ti_scm_read_2(ti_scm_sc, padconf->reg_off); 236 237 /* save the state */ 238 if (state) 239 *state = (reg_val & ti_scm_dev.padconf_sate_mask); 240 241 /* save the mode */ 242 if (muxmode) 243 *muxmode = padconf->muxmodes[(reg_val & ti_scm_dev.padconf_muxmode_mask)]; 244 245 return (0); 246 } 247 248 /** 249 * ti_scm_padconf_set_gpiomode - converts a pad to GPIO mode. 250 * @gpio: the GPIO pin number (0-195) 251 * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_??? 252 * 253 * 254 * 255 * LOCKING: 256 * Internally locks it's own context. 257 * 258 * RETURNS: 259 * 0 on success. 260 * EINVAL if pin requested is outside valid range or already in use. 261 */ 262 int 263 ti_scm_padconf_set_gpiomode(uint32_t gpio, unsigned int state) 264 { 265 const struct ti_scm_padconf *padconf; 266 uint16_t reg_val; 267 268 if (!ti_scm_sc) 269 return (ENXIO); 270 271 /* find the gpio pin in the padconf array */ 272 padconf = ti_scm_dev.padconf; 273 while (padconf->ballname != NULL) { 274 if (padconf->gpio_pin == gpio) 275 break; 276 padconf++; 277 } 278 if (padconf->ballname == NULL) 279 return (EINVAL); 280 281 /* populate the new value for the PADCONF register */ 282 reg_val = (uint16_t)(state & ti_scm_dev.padconf_sate_mask); 283 284 /* set the mux mode */ 285 reg_val |= (uint16_t)(padconf->gpio_mode & ti_scm_dev.padconf_muxmode_mask); 286 287 /* write the register value (16-bit writes) */ 288 ti_scm_write_2(ti_scm_sc, padconf->reg_off, reg_val); 289 290 return (0); 291 } 292 293 /** 294 * ti_scm_padconf_get_gpiomode - gets the current GPIO mode of the pin 295 * @gpio: the GPIO pin number (0-195) 296 * @state: upon return will contain the state 297 * 298 * 299 * 300 * LOCKING: 301 * Internally locks it's own context. 302 * 303 * RETURNS: 304 * 0 on success. 305 * EINVAL if pin requested is outside valid range or not configured as GPIO. 306 */ 307 int 308 ti_scm_padconf_get_gpiomode(uint32_t gpio, unsigned int *state) 309 { 310 const struct ti_scm_padconf *padconf; 311 uint16_t reg_val; 312 313 if (!ti_scm_sc) 314 return (ENXIO); 315 316 /* find the gpio pin in the padconf array */ 317 padconf = ti_scm_dev.padconf; 318 while (padconf->ballname != NULL) { 319 if (padconf->gpio_pin == gpio) 320 break; 321 padconf++; 322 } 323 if (padconf->ballname == NULL) 324 return (EINVAL); 325 326 /* read the current register settings */ 327 reg_val = ti_scm_read_2(ti_scm_sc, padconf->reg_off); 328 329 /* check to make sure the pins is configured as GPIO in the first state */ 330 if ((reg_val & ti_scm_dev.padconf_muxmode_mask) != padconf->gpio_mode) 331 return (EINVAL); 332 333 /* read and store the reset of the state, i.e. pull-up, pull-down, etc */ 334 if (state) 335 *state = (reg_val & ti_scm_dev.padconf_sate_mask); 336 337 return (0); 338 } 339 340 /** 341 * ti_scm_padconf_init_from_hints - processes the hints for padconf 342 * @sc: the driver soft context 343 * 344 * 345 * 346 * LOCKING: 347 * Internally locks it's own context. 348 * 349 * RETURNS: 350 * 0 on success. 351 * EINVAL if pin requested is outside valid range or already in use. 352 */ 353 static int 354 ti_scm_padconf_init_from_fdt(struct ti_scm_softc *sc) 355 { 356 const struct ti_scm_padconf *padconf; 357 const struct ti_scm_padstate *padstates; 358 int err; 359 phandle_t node; 360 int len; 361 char *fdt_pad_config; 362 int i; 363 char *padname, *muxname, *padstate; 364 365 node = ofw_bus_get_node(sc->sc_dev); 366 len = OF_getproplen(node, "scm-pad-config"); 367 OF_getprop_alloc(node, "scm-pad-config", 1, (void **)&fdt_pad_config); 368 369 i = len; 370 while (i > 0) { 371 padname = fdt_pad_config; 372 fdt_pad_config += strlen(padname) + 1; 373 i -= strlen(padname) + 1; 374 if (i <= 0) 375 break; 376 377 muxname = fdt_pad_config; 378 fdt_pad_config += strlen(muxname) + 1; 379 i -= strlen(muxname) + 1; 380 if (i <= 0) 381 break; 382 383 padstate = fdt_pad_config; 384 fdt_pad_config += strlen(padstate) + 1; 385 i -= strlen(padstate) + 1; 386 if (i < 0) 387 break; 388 389 padconf = ti_scm_dev.padconf; 390 391 while (padconf->ballname != NULL) { 392 if (strcmp(padconf->ballname, padname) == 0) { 393 padstates = ti_scm_dev.padstate; 394 err = 1; 395 while (padstates->state != NULL) { 396 if (strcmp(padstates->state, padstate) == 0) { 397 err = ti_scm_padconf_set_internal(sc, 398 padconf, muxname, padstates->reg); 399 } 400 padstates++; 401 } 402 if (err) 403 device_printf(sc->sc_dev, 404 "err: failed to configure " 405 "pin \"%s\" as \"%s\"\n", 406 padconf->ballname, 407 muxname); 408 } 409 padconf++; 410 } 411 } 412 return (0); 413 } 414 415 /* 416 * Device part of OMAP SCM driver 417 */ 418 419 static int 420 ti_scm_probe(device_t dev) 421 { 422 if (!ofw_bus_is_compatible(dev, "ti,scm")) 423 return (ENXIO); 424 425 device_set_desc(dev, "TI Control Module"); 426 return (BUS_PROBE_DEFAULT); 427 } 428 429 /** 430 * ti_scm_attach - attaches the timer to the simplebus 431 * @dev: new device 432 * 433 * Reserves memory and interrupt resources, stores the softc structure 434 * globally and registers both the timecount and eventtimer objects. 435 * 436 * RETURNS 437 * Zero on sucess or ENXIO if an error occuried. 438 */ 439 static int 440 ti_scm_attach(device_t dev) 441 { 442 struct ti_scm_softc *sc = device_get_softc(dev); 443 444 if (ti_scm_sc) 445 return (ENXIO); 446 447 sc->sc_dev = dev; 448 449 if (bus_alloc_resources(dev, ti_scm_res_spec, sc->sc_res)) { 450 device_printf(dev, "could not allocate resources\n"); 451 return (ENXIO); 452 } 453 454 /* Global timer interface */ 455 sc->sc_bst = rman_get_bustag(sc->sc_res[0]); 456 sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]); 457 458 ti_scm_sc = sc; 459 460 ti_scm_padconf_init_from_fdt(sc); 461 462 return (0); 463 } 464 465 int 466 ti_scm_reg_read_4(uint32_t reg, uint32_t *val) 467 { 468 if (!ti_scm_sc) 469 return (ENXIO); 470 471 *val = ti_scm_read_4(ti_scm_sc, reg); 472 return (0); 473 } 474 475 int 476 ti_scm_reg_write_4(uint32_t reg, uint32_t val) 477 { 478 if (!ti_scm_sc) 479 return (ENXIO); 480 481 ti_scm_write_4(ti_scm_sc, reg, val); 482 return (0); 483 } 484 485 486 static device_method_t ti_scm_methods[] = { 487 DEVMETHOD(device_probe, ti_scm_probe), 488 DEVMETHOD(device_attach, ti_scm_attach), 489 { 0, 0 } 490 }; 491 492 static driver_t ti_scm_driver = { 493 "ti_scm", 494 ti_scm_methods, 495 sizeof(struct ti_scm_softc), 496 }; 497 498 static devclass_t ti_scm_devclass; 499 500 DRIVER_MODULE(ti_scm, simplebus, ti_scm_driver, ti_scm_devclass, 0, 0); 501