1239281Sgonzo/* 2239281Sgonzo * Copyright (c) 2010 3239281Sgonzo * Ben Gray <ben.r.gray@gmail.com>. 4239281Sgonzo * All rights reserved. 5239281Sgonzo * 6239281Sgonzo * Redistribution and use in source and binary forms, with or without 7239281Sgonzo * modification, are permitted provided that the following conditions 8239281Sgonzo * are met: 9239281Sgonzo * 1. Redistributions of source code must retain the above copyright 10239281Sgonzo * notice, this list of conditions and the following disclaimer. 11239281Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 12239281Sgonzo * notice, this list of conditions and the following disclaimer in the 13239281Sgonzo * documentation and/or other materials provided with the distribution. 14239281Sgonzo * 3. All advertising materials mentioning features or use of this software 15239281Sgonzo * must display the following acknowledgement: 16239281Sgonzo * This product includes software developed by Ben Gray. 17239281Sgonzo * 4. The name of the company nor the name of the author may be used to 18239281Sgonzo * endorse or promote products derived from this software without specific 19239281Sgonzo * prior written permission. 20239281Sgonzo * 21239281Sgonzo * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR 22239281Sgonzo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23239281Sgonzo * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24239281Sgonzo * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25239281Sgonzo * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26239281Sgonzo * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 27239281Sgonzo * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28239281Sgonzo * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29239281Sgonzo * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 30239281Sgonzo * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31239281Sgonzo */ 32239281Sgonzo 33239281Sgonzo/** 34239281Sgonzo * SCM - System Control Module 35239281Sgonzo * 36239281Sgonzo * Hopefully in the end this module will contain a bunch of utility functions 37239281Sgonzo * for configuring and querying the general system control registers, but for 38239281Sgonzo * now it only does pin(pad) multiplexing. 39239281Sgonzo * 40239281Sgonzo * This is different from the GPIO module in that it is used to configure the 41239281Sgonzo * pins between modules not just GPIO input/output. 42239281Sgonzo * 43239281Sgonzo * This file contains the generic top level driver, however it relies on chip 44239281Sgonzo * specific settings and therefore expects an array of ti_scm_padconf structs 45239281Sgonzo * call ti_padconf_devmap to be located somewhere in the kernel. 46239281Sgonzo * 47239281Sgonzo */ 48239281Sgonzo#include <sys/cdefs.h> 49239281Sgonzo__FBSDID("$FreeBSD$"); 50239281Sgonzo 51239281Sgonzo#include <sys/param.h> 52239281Sgonzo#include <sys/systm.h> 53239281Sgonzo#include <sys/kernel.h> 54239281Sgonzo#include <sys/module.h> 55239281Sgonzo#include <sys/bus.h> 56239281Sgonzo#include <sys/resource.h> 57239281Sgonzo#include <sys/rman.h> 58239281Sgonzo#include <sys/lock.h> 59239281Sgonzo#include <sys/mutex.h> 60239281Sgonzo 61239281Sgonzo#include <machine/bus.h> 62239281Sgonzo#include <machine/cpu.h> 63239281Sgonzo#include <machine/cpufunc.h> 64239281Sgonzo#include <machine/frame.h> 65239281Sgonzo#include <machine/resource.h> 66239281Sgonzo 67239281Sgonzo#include <dev/fdt/fdt_common.h> 68239281Sgonzo#include <dev/ofw/openfirm.h> 69239281Sgonzo#include <dev/ofw/ofw_bus.h> 70239281Sgonzo#include <dev/ofw/ofw_bus_subr.h> 71239281Sgonzo 72239281Sgonzo#include "ti_scm.h" 73239281Sgonzo 74239281Sgonzostatic struct resource_spec ti_scm_res_spec[] = { 75239281Sgonzo { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Control memory window */ 76239281Sgonzo { -1, 0 } 77239281Sgonzo}; 78239281Sgonzo 79239281Sgonzostatic struct ti_scm_softc *ti_scm_sc; 80239281Sgonzo 81239281Sgonzo#define ti_scm_read_2(sc, reg) \ 82239281Sgonzo bus_space_read_2((sc)->sc_bst, (sc)->sc_bsh, (reg)) 83239281Sgonzo#define ti_scm_write_2(sc, reg, val) \ 84239281Sgonzo bus_space_write_2((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 85239281Sgonzo#define ti_scm_read_4(sc, reg) \ 86239281Sgonzo bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 87239281Sgonzo#define ti_scm_write_4(sc, reg, val) \ 88239281Sgonzo bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 89239281Sgonzo 90239281Sgonzo 91239281Sgonzo/** 92239281Sgonzo * ti_padconf_devmap - Array of pins, should be defined one per SoC 93239281Sgonzo * 94239281Sgonzo * This array is typically defined in one of the targeted *_scm_pinumx.c 95239281Sgonzo * files and is specific to the given SoC platform. Each entry in the array 96239281Sgonzo * corresponds to an individual pin. 97239281Sgonzo */ 98239281Sgonzoextern const struct ti_scm_device ti_scm_dev; 99239281Sgonzo 100239281Sgonzo 101239281Sgonzo/** 102239281Sgonzo * ti_scm_padconf_from_name - searches the list of pads and returns entry 103239281Sgonzo * with matching ball name. 104239281Sgonzo * @ballname: the name of the ball 105239281Sgonzo * 106239281Sgonzo * RETURNS: 107239281Sgonzo * A pointer to the matching padconf or NULL if the ball wasn't found. 108239281Sgonzo */ 109239281Sgonzostatic const struct ti_scm_padconf* 110239281Sgonzoti_scm_padconf_from_name(const char *ballname) 111239281Sgonzo{ 112239281Sgonzo const struct ti_scm_padconf *padconf; 113239281Sgonzo 114239281Sgonzo padconf = ti_scm_dev.padconf; 115239281Sgonzo while (padconf->ballname != NULL) { 116239281Sgonzo if (strcmp(ballname, padconf->ballname) == 0) 117239281Sgonzo return(padconf); 118239281Sgonzo padconf++; 119239281Sgonzo } 120239281Sgonzo 121239281Sgonzo return (NULL); 122239281Sgonzo} 123239281Sgonzo 124239281Sgonzo/** 125239281Sgonzo * ti_scm_padconf_set_internal - sets the muxmode and state for a pad/pin 126239281Sgonzo * @padconf: pointer to the pad structure 127239281Sgonzo * @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx" 128239281Sgonzo * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_??? 129239281Sgonzo * 130239281Sgonzo * 131239281Sgonzo * LOCKING: 132239281Sgonzo * Internally locks it's own context. 133239281Sgonzo * 134239281Sgonzo * RETURNS: 135239281Sgonzo * 0 on success. 136239281Sgonzo * EINVAL if pin requested is outside valid range or already in use. 137239281Sgonzo */ 138239281Sgonzostatic int 139239281Sgonzoti_scm_padconf_set_internal(struct ti_scm_softc *sc, 140239281Sgonzo const struct ti_scm_padconf *padconf, 141239281Sgonzo const char *muxmode, unsigned int state) 142239281Sgonzo{ 143239281Sgonzo unsigned int mode; 144239281Sgonzo uint16_t reg_val; 145239281Sgonzo 146239281Sgonzo /* populate the new value for the PADCONF register */ 147239281Sgonzo reg_val = (uint16_t)(state & ti_scm_dev.padconf_sate_mask); 148239281Sgonzo 149239281Sgonzo /* find the new mode requested */ 150239281Sgonzo for (mode = 0; mode < 8; mode++) { 151239281Sgonzo if ((padconf->muxmodes[mode] != NULL) && 152239281Sgonzo (strcmp(padconf->muxmodes[mode], muxmode) == 0)) { 153239281Sgonzo break; 154239281Sgonzo } 155239281Sgonzo } 156239281Sgonzo 157239281Sgonzo /* couldn't find the mux mode */ 158245672Skientzle if (mode >= 8) { 159245672Skientzle printf("Invalid mode \"%s\"\n", muxmode); 160239281Sgonzo return (EINVAL); 161245672Skientzle } 162239281Sgonzo 163239281Sgonzo /* set the mux mode */ 164239281Sgonzo reg_val |= (uint16_t)(mode & ti_scm_dev.padconf_muxmode_mask); 165239281Sgonzo 166252229Srpaulo if (bootverbose) 167252229Srpaulo device_printf(sc->sc_dev, "setting internal %x for %s\n", 168252229Srpaulo reg_val, muxmode); 169239281Sgonzo /* write the register value (16-bit writes) */ 170239281Sgonzo ti_scm_write_2(sc, padconf->reg_off, reg_val); 171239281Sgonzo 172239281Sgonzo return (0); 173239281Sgonzo} 174239281Sgonzo 175239281Sgonzo/** 176239281Sgonzo * ti_scm_padconf_set - sets the muxmode and state for a pad/pin 177239281Sgonzo * @padname: the name of the pad, i.e. "c12" 178239281Sgonzo * @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx" 179239281Sgonzo * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_??? 180239281Sgonzo * 181239281Sgonzo * 182239281Sgonzo * LOCKING: 183239281Sgonzo * Internally locks it's own context. 184239281Sgonzo * 185239281Sgonzo * RETURNS: 186239281Sgonzo * 0 on success. 187239281Sgonzo * EINVAL if pin requested is outside valid range or already in use. 188239281Sgonzo */ 189239281Sgonzoint 190239281Sgonzoti_scm_padconf_set(const char *padname, const char *muxmode, unsigned int state) 191239281Sgonzo{ 192239281Sgonzo const struct ti_scm_padconf *padconf; 193239281Sgonzo 194239281Sgonzo if (!ti_scm_sc) 195239281Sgonzo return (ENXIO); 196239281Sgonzo 197239281Sgonzo /* find the pin in the devmap */ 198239281Sgonzo padconf = ti_scm_padconf_from_name(padname); 199239281Sgonzo if (padconf == NULL) 200239281Sgonzo return (EINVAL); 201239281Sgonzo 202239281Sgonzo return (ti_scm_padconf_set_internal(ti_scm_sc, padconf, muxmode, state)); 203239281Sgonzo} 204239281Sgonzo 205239281Sgonzo/** 206239281Sgonzo * ti_scm_padconf_get - gets the muxmode and state for a pad/pin 207239281Sgonzo * @padname: the name of the pad, i.e. "c12" 208239281Sgonzo * @muxmode: upon return will contain the name of the muxmode of the pin 209240518Seadler * @state: upon return will contain the state of the pad/pin 210239281Sgonzo * 211239281Sgonzo * 212239281Sgonzo * LOCKING: 213239281Sgonzo * Internally locks it's own context. 214239281Sgonzo * 215239281Sgonzo * RETURNS: 216239281Sgonzo * 0 on success. 217239281Sgonzo * EINVAL if pin requested is outside valid range or already in use. 218239281Sgonzo */ 219239281Sgonzoint 220239281Sgonzoti_scm_padconf_get(const char *padname, const char **muxmode, 221239281Sgonzo unsigned int *state) 222239281Sgonzo{ 223239281Sgonzo const struct ti_scm_padconf *padconf; 224239281Sgonzo uint16_t reg_val; 225239281Sgonzo 226239281Sgonzo if (!ti_scm_sc) 227239281Sgonzo return (ENXIO); 228239281Sgonzo 229239281Sgonzo /* find the pin in the devmap */ 230239281Sgonzo padconf = ti_scm_padconf_from_name(padname); 231239281Sgonzo if (padconf == NULL) 232239281Sgonzo return (EINVAL); 233239281Sgonzo 234239281Sgonzo /* read the register value (16-bit reads) */ 235239281Sgonzo reg_val = ti_scm_read_2(ti_scm_sc, padconf->reg_off); 236239281Sgonzo 237239281Sgonzo /* save the state */ 238239281Sgonzo if (state) 239239281Sgonzo *state = (reg_val & ti_scm_dev.padconf_sate_mask); 240239281Sgonzo 241239281Sgonzo /* save the mode */ 242239281Sgonzo if (muxmode) 243239281Sgonzo *muxmode = padconf->muxmodes[(reg_val & ti_scm_dev.padconf_muxmode_mask)]; 244239281Sgonzo 245239281Sgonzo return (0); 246239281Sgonzo} 247239281Sgonzo 248239281Sgonzo/** 249239281Sgonzo * ti_scm_padconf_set_gpiomode - converts a pad to GPIO mode. 250239281Sgonzo * @gpio: the GPIO pin number (0-195) 251239281Sgonzo * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_??? 252239281Sgonzo * 253239281Sgonzo * 254239281Sgonzo * 255239281Sgonzo * LOCKING: 256239281Sgonzo * Internally locks it's own context. 257239281Sgonzo * 258239281Sgonzo * RETURNS: 259239281Sgonzo * 0 on success. 260239281Sgonzo * EINVAL if pin requested is outside valid range or already in use. 261239281Sgonzo */ 262239281Sgonzoint 263239281Sgonzoti_scm_padconf_set_gpiomode(uint32_t gpio, unsigned int state) 264239281Sgonzo{ 265239281Sgonzo const struct ti_scm_padconf *padconf; 266239281Sgonzo uint16_t reg_val; 267239281Sgonzo 268239281Sgonzo if (!ti_scm_sc) 269239281Sgonzo return (ENXIO); 270239281Sgonzo 271239281Sgonzo /* find the gpio pin in the padconf array */ 272239281Sgonzo padconf = ti_scm_dev.padconf; 273239281Sgonzo while (padconf->ballname != NULL) { 274239281Sgonzo if (padconf->gpio_pin == gpio) 275239281Sgonzo break; 276239281Sgonzo padconf++; 277239281Sgonzo } 278239281Sgonzo if (padconf->ballname == NULL) 279239281Sgonzo return (EINVAL); 280239281Sgonzo 281239281Sgonzo /* populate the new value for the PADCONF register */ 282239281Sgonzo reg_val = (uint16_t)(state & ti_scm_dev.padconf_sate_mask); 283239281Sgonzo 284239281Sgonzo /* set the mux mode */ 285239281Sgonzo reg_val |= (uint16_t)(padconf->gpio_mode & ti_scm_dev.padconf_muxmode_mask); 286239281Sgonzo 287239281Sgonzo /* write the register value (16-bit writes) */ 288239281Sgonzo ti_scm_write_2(ti_scm_sc, padconf->reg_off, reg_val); 289239281Sgonzo 290239281Sgonzo return (0); 291239281Sgonzo} 292239281Sgonzo 293239281Sgonzo/** 294239281Sgonzo * ti_scm_padconf_get_gpiomode - gets the current GPIO mode of the pin 295239281Sgonzo * @gpio: the GPIO pin number (0-195) 296239281Sgonzo * @state: upon return will contain the state 297239281Sgonzo * 298239281Sgonzo * 299239281Sgonzo * 300239281Sgonzo * LOCKING: 301239281Sgonzo * Internally locks it's own context. 302239281Sgonzo * 303239281Sgonzo * RETURNS: 304239281Sgonzo * 0 on success. 305239281Sgonzo * EINVAL if pin requested is outside valid range or not configured as GPIO. 306239281Sgonzo */ 307239281Sgonzoint 308239281Sgonzoti_scm_padconf_get_gpiomode(uint32_t gpio, unsigned int *state) 309239281Sgonzo{ 310239281Sgonzo const struct ti_scm_padconf *padconf; 311239281Sgonzo uint16_t reg_val; 312239281Sgonzo 313239281Sgonzo if (!ti_scm_sc) 314239281Sgonzo return (ENXIO); 315239281Sgonzo 316239281Sgonzo /* find the gpio pin in the padconf array */ 317239281Sgonzo padconf = ti_scm_dev.padconf; 318239281Sgonzo while (padconf->ballname != NULL) { 319239281Sgonzo if (padconf->gpio_pin == gpio) 320239281Sgonzo break; 321239281Sgonzo padconf++; 322239281Sgonzo } 323239281Sgonzo if (padconf->ballname == NULL) 324239281Sgonzo return (EINVAL); 325239281Sgonzo 326239281Sgonzo /* read the current register settings */ 327239281Sgonzo reg_val = ti_scm_read_2(ti_scm_sc, padconf->reg_off); 328239281Sgonzo 329239281Sgonzo /* check to make sure the pins is configured as GPIO in the first state */ 330239281Sgonzo if ((reg_val & ti_scm_dev.padconf_muxmode_mask) != padconf->gpio_mode) 331239281Sgonzo return (EINVAL); 332239281Sgonzo 333239281Sgonzo /* read and store the reset of the state, i.e. pull-up, pull-down, etc */ 334239281Sgonzo if (state) 335239281Sgonzo *state = (reg_val & ti_scm_dev.padconf_sate_mask); 336239281Sgonzo 337239281Sgonzo return (0); 338239281Sgonzo} 339239281Sgonzo 340239281Sgonzo/** 341239281Sgonzo * ti_scm_padconf_init_from_hints - processes the hints for padconf 342239281Sgonzo * @sc: the driver soft context 343239281Sgonzo * 344239281Sgonzo * 345239281Sgonzo * 346239281Sgonzo * LOCKING: 347239281Sgonzo * Internally locks it's own context. 348239281Sgonzo * 349239281Sgonzo * RETURNS: 350239281Sgonzo * 0 on success. 351239281Sgonzo * EINVAL if pin requested is outside valid range or already in use. 352239281Sgonzo */ 353239281Sgonzostatic int 354239281Sgonzoti_scm_padconf_init_from_fdt(struct ti_scm_softc *sc) 355239281Sgonzo{ 356239281Sgonzo const struct ti_scm_padconf *padconf; 357239281Sgonzo const struct ti_scm_padstate *padstates; 358239281Sgonzo int err; 359239281Sgonzo phandle_t node; 360239281Sgonzo int len; 361239281Sgonzo char *fdt_pad_config; 362239281Sgonzo int i; 363239281Sgonzo char *padname, *muxname, *padstate; 364239281Sgonzo 365239281Sgonzo node = ofw_bus_get_node(sc->sc_dev); 366239281Sgonzo len = OF_getproplen(node, "scm-pad-config"); 367239281Sgonzo OF_getprop_alloc(node, "scm-pad-config", 1, (void **)&fdt_pad_config); 368239281Sgonzo 369239281Sgonzo i = len; 370239281Sgonzo while (i > 0) { 371239281Sgonzo padname = fdt_pad_config; 372239281Sgonzo fdt_pad_config += strlen(padname) + 1; 373239281Sgonzo i -= strlen(padname) + 1; 374239281Sgonzo if (i <= 0) 375239281Sgonzo break; 376239281Sgonzo 377239281Sgonzo muxname = fdt_pad_config; 378239281Sgonzo fdt_pad_config += strlen(muxname) + 1; 379239281Sgonzo i -= strlen(muxname) + 1; 380239281Sgonzo if (i <= 0) 381239281Sgonzo break; 382239281Sgonzo 383239281Sgonzo padstate = fdt_pad_config; 384239281Sgonzo fdt_pad_config += strlen(padstate) + 1; 385239281Sgonzo i -= strlen(padstate) + 1; 386239281Sgonzo if (i < 0) 387239281Sgonzo break; 388239281Sgonzo 389239281Sgonzo padconf = ti_scm_dev.padconf; 390239281Sgonzo 391239281Sgonzo while (padconf->ballname != NULL) { 392239281Sgonzo if (strcmp(padconf->ballname, padname) == 0) { 393239281Sgonzo padstates = ti_scm_dev.padstate; 394239281Sgonzo err = 1; 395239281Sgonzo while (padstates->state != NULL) { 396239281Sgonzo if (strcmp(padstates->state, padstate) == 0) { 397239281Sgonzo err = ti_scm_padconf_set_internal(sc, 398245672Skientzle padconf, muxname, padstates->reg); 399239281Sgonzo } 400239281Sgonzo padstates++; 401239281Sgonzo } 402239281Sgonzo if (err) 403245672Skientzle device_printf(sc->sc_dev, 404245672Skientzle "err: failed to configure " 405245672Skientzle "pin \"%s\" as \"%s\"\n", 406245672Skientzle padconf->ballname, 407245672Skientzle muxname); 408239281Sgonzo } 409239281Sgonzo padconf++; 410239281Sgonzo } 411239281Sgonzo } 412239281Sgonzo return (0); 413239281Sgonzo} 414239281Sgonzo 415239281Sgonzo/* 416239281Sgonzo * Device part of OMAP SCM driver 417239281Sgonzo */ 418239281Sgonzo 419239281Sgonzostatic int 420239281Sgonzoti_scm_probe(device_t dev) 421239281Sgonzo{ 422239281Sgonzo if (!ofw_bus_is_compatible(dev, "ti,scm")) 423239281Sgonzo return (ENXIO); 424239281Sgonzo 425239281Sgonzo device_set_desc(dev, "TI Control Module"); 426239281Sgonzo return (BUS_PROBE_DEFAULT); 427239281Sgonzo} 428239281Sgonzo 429239281Sgonzo/** 430239281Sgonzo * ti_scm_attach - attaches the timer to the simplebus 431239281Sgonzo * @dev: new device 432239281Sgonzo * 433239281Sgonzo * Reserves memory and interrupt resources, stores the softc structure 434239281Sgonzo * globally and registers both the timecount and eventtimer objects. 435239281Sgonzo * 436239281Sgonzo * RETURNS 437239281Sgonzo * Zero on sucess or ENXIO if an error occuried. 438239281Sgonzo */ 439239281Sgonzostatic int 440239281Sgonzoti_scm_attach(device_t dev) 441239281Sgonzo{ 442239281Sgonzo struct ti_scm_softc *sc = device_get_softc(dev); 443239281Sgonzo 444239281Sgonzo if (ti_scm_sc) 445239281Sgonzo return (ENXIO); 446239281Sgonzo 447239281Sgonzo sc->sc_dev = dev; 448239281Sgonzo 449239281Sgonzo if (bus_alloc_resources(dev, ti_scm_res_spec, sc->sc_res)) { 450239281Sgonzo device_printf(dev, "could not allocate resources\n"); 451239281Sgonzo return (ENXIO); 452239281Sgonzo } 453239281Sgonzo 454239281Sgonzo /* Global timer interface */ 455239281Sgonzo sc->sc_bst = rman_get_bustag(sc->sc_res[0]); 456239281Sgonzo sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]); 457239281Sgonzo 458239281Sgonzo ti_scm_sc = sc; 459239281Sgonzo 460239281Sgonzo ti_scm_padconf_init_from_fdt(sc); 461239281Sgonzo 462239281Sgonzo return (0); 463239281Sgonzo} 464239281Sgonzo 465239281Sgonzoint 466239281Sgonzoti_scm_reg_read_4(uint32_t reg, uint32_t *val) 467239281Sgonzo{ 468239281Sgonzo if (!ti_scm_sc) 469239281Sgonzo return (ENXIO); 470239281Sgonzo 471239281Sgonzo *val = ti_scm_read_4(ti_scm_sc, reg); 472239281Sgonzo return (0); 473239281Sgonzo} 474239281Sgonzo 475239281Sgonzoint 476239281Sgonzoti_scm_reg_write_4(uint32_t reg, uint32_t val) 477239281Sgonzo{ 478239281Sgonzo if (!ti_scm_sc) 479239281Sgonzo return (ENXIO); 480239281Sgonzo 481239281Sgonzo ti_scm_write_4(ti_scm_sc, reg, val); 482239281Sgonzo return (0); 483239281Sgonzo} 484239281Sgonzo 485239281Sgonzo 486239281Sgonzostatic device_method_t ti_scm_methods[] = { 487239281Sgonzo DEVMETHOD(device_probe, ti_scm_probe), 488239281Sgonzo DEVMETHOD(device_attach, ti_scm_attach), 489239281Sgonzo { 0, 0 } 490239281Sgonzo}; 491239281Sgonzo 492239281Sgonzostatic driver_t ti_scm_driver = { 493239281Sgonzo "ti_scm", 494239281Sgonzo ti_scm_methods, 495239281Sgonzo sizeof(struct ti_scm_softc), 496239281Sgonzo}; 497239281Sgonzo 498239281Sgonzostatic devclass_t ti_scm_devclass; 499239281Sgonzo 500239281SgonzoDRIVER_MODULE(ti_scm, simplebus, ti_scm_driver, ti_scm_devclass, 0, 0); 501