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/resource.h> 65239281Sgonzo 66239281Sgonzo#include <dev/fdt/fdt_common.h> 67239281Sgonzo#include <dev/ofw/openfirm.h> 68239281Sgonzo#include <dev/ofw/ofw_bus.h> 69239281Sgonzo#include <dev/ofw/ofw_bus_subr.h> 70239281Sgonzo 71239281Sgonzo#include "ti_scm.h" 72239281Sgonzo 73239281Sgonzostatic struct resource_spec ti_scm_res_spec[] = { 74239281Sgonzo { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Control memory window */ 75239281Sgonzo { -1, 0 } 76239281Sgonzo}; 77239281Sgonzo 78239281Sgonzostatic struct ti_scm_softc *ti_scm_sc; 79239281Sgonzo 80239281Sgonzo#define ti_scm_read_2(sc, reg) \ 81239281Sgonzo bus_space_read_2((sc)->sc_bst, (sc)->sc_bsh, (reg)) 82239281Sgonzo#define ti_scm_write_2(sc, reg, val) \ 83239281Sgonzo bus_space_write_2((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 84239281Sgonzo#define ti_scm_read_4(sc, reg) \ 85239281Sgonzo bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 86239281Sgonzo#define ti_scm_write_4(sc, reg, val) \ 87239281Sgonzo bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 88239281Sgonzo 89239281Sgonzo 90239281Sgonzo/** 91239281Sgonzo * ti_padconf_devmap - Array of pins, should be defined one per SoC 92239281Sgonzo * 93239281Sgonzo * This array is typically defined in one of the targeted *_scm_pinumx.c 94239281Sgonzo * files and is specific to the given SoC platform. Each entry in the array 95239281Sgonzo * corresponds to an individual pin. 96239281Sgonzo */ 97239281Sgonzoextern const struct ti_scm_device ti_scm_dev; 98239281Sgonzo 99239281Sgonzo 100239281Sgonzo/** 101239281Sgonzo * ti_scm_padconf_from_name - searches the list of pads and returns entry 102239281Sgonzo * with matching ball name. 103239281Sgonzo * @ballname: the name of the ball 104239281Sgonzo * 105239281Sgonzo * RETURNS: 106239281Sgonzo * A pointer to the matching padconf or NULL if the ball wasn't found. 107239281Sgonzo */ 108239281Sgonzostatic const struct ti_scm_padconf* 109239281Sgonzoti_scm_padconf_from_name(const char *ballname) 110239281Sgonzo{ 111239281Sgonzo const struct ti_scm_padconf *padconf; 112239281Sgonzo 113239281Sgonzo padconf = ti_scm_dev.padconf; 114239281Sgonzo while (padconf->ballname != NULL) { 115239281Sgonzo if (strcmp(ballname, padconf->ballname) == 0) 116239281Sgonzo return(padconf); 117239281Sgonzo padconf++; 118239281Sgonzo } 119239281Sgonzo 120239281Sgonzo return (NULL); 121239281Sgonzo} 122239281Sgonzo 123239281Sgonzo/** 124239281Sgonzo * ti_scm_padconf_set_internal - sets the muxmode and state for a pad/pin 125239281Sgonzo * @padconf: pointer to the pad structure 126239281Sgonzo * @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx" 127239281Sgonzo * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_??? 128239281Sgonzo * 129239281Sgonzo * 130239281Sgonzo * LOCKING: 131239281Sgonzo * Internally locks it's own context. 132239281Sgonzo * 133239281Sgonzo * RETURNS: 134239281Sgonzo * 0 on success. 135239281Sgonzo * EINVAL if pin requested is outside valid range or already in use. 136239281Sgonzo */ 137239281Sgonzostatic int 138239281Sgonzoti_scm_padconf_set_internal(struct ti_scm_softc *sc, 139239281Sgonzo const struct ti_scm_padconf *padconf, 140239281Sgonzo const char *muxmode, unsigned int state) 141239281Sgonzo{ 142239281Sgonzo unsigned int mode; 143239281Sgonzo uint16_t reg_val; 144239281Sgonzo 145239281Sgonzo /* populate the new value for the PADCONF register */ 146239281Sgonzo reg_val = (uint16_t)(state & ti_scm_dev.padconf_sate_mask); 147239281Sgonzo 148239281Sgonzo /* find the new mode requested */ 149239281Sgonzo for (mode = 0; mode < 8; mode++) { 150239281Sgonzo if ((padconf->muxmodes[mode] != NULL) && 151239281Sgonzo (strcmp(padconf->muxmodes[mode], muxmode) == 0)) { 152239281Sgonzo break; 153239281Sgonzo } 154239281Sgonzo } 155239281Sgonzo 156239281Sgonzo /* couldn't find the mux mode */ 157245672Skientzle if (mode >= 8) { 158245672Skientzle printf("Invalid mode \"%s\"\n", muxmode); 159239281Sgonzo return (EINVAL); 160245672Skientzle } 161239281Sgonzo 162239281Sgonzo /* set the mux mode */ 163239281Sgonzo reg_val |= (uint16_t)(mode & ti_scm_dev.padconf_muxmode_mask); 164239281Sgonzo 165252229Srpaulo if (bootverbose) 166252229Srpaulo device_printf(sc->sc_dev, "setting internal %x for %s\n", 167252229Srpaulo reg_val, muxmode); 168239281Sgonzo /* write the register value (16-bit writes) */ 169239281Sgonzo ti_scm_write_2(sc, padconf->reg_off, reg_val); 170239281Sgonzo 171239281Sgonzo return (0); 172239281Sgonzo} 173239281Sgonzo 174239281Sgonzo/** 175239281Sgonzo * ti_scm_padconf_set - sets the muxmode and state for a pad/pin 176239281Sgonzo * @padname: the name of the pad, i.e. "c12" 177239281Sgonzo * @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx" 178239281Sgonzo * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_??? 179239281Sgonzo * 180239281Sgonzo * 181239281Sgonzo * LOCKING: 182239281Sgonzo * Internally locks it's own context. 183239281Sgonzo * 184239281Sgonzo * RETURNS: 185239281Sgonzo * 0 on success. 186239281Sgonzo * EINVAL if pin requested is outside valid range or already in use. 187239281Sgonzo */ 188239281Sgonzoint 189239281Sgonzoti_scm_padconf_set(const char *padname, const char *muxmode, unsigned int state) 190239281Sgonzo{ 191239281Sgonzo const struct ti_scm_padconf *padconf; 192239281Sgonzo 193239281Sgonzo if (!ti_scm_sc) 194239281Sgonzo return (ENXIO); 195239281Sgonzo 196239281Sgonzo /* find the pin in the devmap */ 197239281Sgonzo padconf = ti_scm_padconf_from_name(padname); 198239281Sgonzo if (padconf == NULL) 199239281Sgonzo return (EINVAL); 200239281Sgonzo 201239281Sgonzo return (ti_scm_padconf_set_internal(ti_scm_sc, padconf, muxmode, state)); 202239281Sgonzo} 203239281Sgonzo 204239281Sgonzo/** 205239281Sgonzo * ti_scm_padconf_get - gets the muxmode and state for a pad/pin 206239281Sgonzo * @padname: the name of the pad, i.e. "c12" 207239281Sgonzo * @muxmode: upon return will contain the name of the muxmode of the pin 208240518Seadler * @state: upon return will contain the state of the pad/pin 209239281Sgonzo * 210239281Sgonzo * 211239281Sgonzo * LOCKING: 212239281Sgonzo * Internally locks it's own context. 213239281Sgonzo * 214239281Sgonzo * RETURNS: 215239281Sgonzo * 0 on success. 216239281Sgonzo * EINVAL if pin requested is outside valid range or already in use. 217239281Sgonzo */ 218239281Sgonzoint 219239281Sgonzoti_scm_padconf_get(const char *padname, const char **muxmode, 220239281Sgonzo unsigned int *state) 221239281Sgonzo{ 222239281Sgonzo const struct ti_scm_padconf *padconf; 223239281Sgonzo uint16_t reg_val; 224239281Sgonzo 225239281Sgonzo if (!ti_scm_sc) 226239281Sgonzo return (ENXIO); 227239281Sgonzo 228239281Sgonzo /* find the pin in the devmap */ 229239281Sgonzo padconf = ti_scm_padconf_from_name(padname); 230239281Sgonzo if (padconf == NULL) 231239281Sgonzo return (EINVAL); 232239281Sgonzo 233239281Sgonzo /* read the register value (16-bit reads) */ 234239281Sgonzo reg_val = ti_scm_read_2(ti_scm_sc, padconf->reg_off); 235239281Sgonzo 236239281Sgonzo /* save the state */ 237239281Sgonzo if (state) 238239281Sgonzo *state = (reg_val & ti_scm_dev.padconf_sate_mask); 239239281Sgonzo 240239281Sgonzo /* save the mode */ 241239281Sgonzo if (muxmode) 242239281Sgonzo *muxmode = padconf->muxmodes[(reg_val & ti_scm_dev.padconf_muxmode_mask)]; 243239281Sgonzo 244239281Sgonzo return (0); 245239281Sgonzo} 246239281Sgonzo 247239281Sgonzo/** 248239281Sgonzo * ti_scm_padconf_set_gpiomode - converts a pad to GPIO mode. 249239281Sgonzo * @gpio: the GPIO pin number (0-195) 250239281Sgonzo * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_??? 251239281Sgonzo * 252239281Sgonzo * 253239281Sgonzo * 254239281Sgonzo * LOCKING: 255239281Sgonzo * Internally locks it's own context. 256239281Sgonzo * 257239281Sgonzo * RETURNS: 258239281Sgonzo * 0 on success. 259239281Sgonzo * EINVAL if pin requested is outside valid range or already in use. 260239281Sgonzo */ 261239281Sgonzoint 262239281Sgonzoti_scm_padconf_set_gpiomode(uint32_t gpio, unsigned int state) 263239281Sgonzo{ 264239281Sgonzo const struct ti_scm_padconf *padconf; 265239281Sgonzo uint16_t reg_val; 266239281Sgonzo 267239281Sgonzo if (!ti_scm_sc) 268239281Sgonzo return (ENXIO); 269239281Sgonzo 270239281Sgonzo /* find the gpio pin in the padconf array */ 271239281Sgonzo padconf = ti_scm_dev.padconf; 272239281Sgonzo while (padconf->ballname != NULL) { 273239281Sgonzo if (padconf->gpio_pin == gpio) 274239281Sgonzo break; 275239281Sgonzo padconf++; 276239281Sgonzo } 277239281Sgonzo if (padconf->ballname == NULL) 278239281Sgonzo return (EINVAL); 279239281Sgonzo 280239281Sgonzo /* populate the new value for the PADCONF register */ 281239281Sgonzo reg_val = (uint16_t)(state & ti_scm_dev.padconf_sate_mask); 282239281Sgonzo 283239281Sgonzo /* set the mux mode */ 284239281Sgonzo reg_val |= (uint16_t)(padconf->gpio_mode & ti_scm_dev.padconf_muxmode_mask); 285239281Sgonzo 286239281Sgonzo /* write the register value (16-bit writes) */ 287239281Sgonzo ti_scm_write_2(ti_scm_sc, padconf->reg_off, reg_val); 288239281Sgonzo 289239281Sgonzo return (0); 290239281Sgonzo} 291239281Sgonzo 292239281Sgonzo/** 293239281Sgonzo * ti_scm_padconf_get_gpiomode - gets the current GPIO mode of the pin 294239281Sgonzo * @gpio: the GPIO pin number (0-195) 295239281Sgonzo * @state: upon return will contain the state 296239281Sgonzo * 297239281Sgonzo * 298239281Sgonzo * 299239281Sgonzo * LOCKING: 300239281Sgonzo * Internally locks it's own context. 301239281Sgonzo * 302239281Sgonzo * RETURNS: 303239281Sgonzo * 0 on success. 304239281Sgonzo * EINVAL if pin requested is outside valid range or not configured as GPIO. 305239281Sgonzo */ 306239281Sgonzoint 307239281Sgonzoti_scm_padconf_get_gpiomode(uint32_t gpio, unsigned int *state) 308239281Sgonzo{ 309239281Sgonzo const struct ti_scm_padconf *padconf; 310239281Sgonzo uint16_t reg_val; 311239281Sgonzo 312239281Sgonzo if (!ti_scm_sc) 313239281Sgonzo return (ENXIO); 314239281Sgonzo 315239281Sgonzo /* find the gpio pin in the padconf array */ 316239281Sgonzo padconf = ti_scm_dev.padconf; 317239281Sgonzo while (padconf->ballname != NULL) { 318239281Sgonzo if (padconf->gpio_pin == gpio) 319239281Sgonzo break; 320239281Sgonzo padconf++; 321239281Sgonzo } 322239281Sgonzo if (padconf->ballname == NULL) 323239281Sgonzo return (EINVAL); 324239281Sgonzo 325239281Sgonzo /* read the current register settings */ 326239281Sgonzo reg_val = ti_scm_read_2(ti_scm_sc, padconf->reg_off); 327239281Sgonzo 328239281Sgonzo /* check to make sure the pins is configured as GPIO in the first state */ 329239281Sgonzo if ((reg_val & ti_scm_dev.padconf_muxmode_mask) != padconf->gpio_mode) 330239281Sgonzo return (EINVAL); 331239281Sgonzo 332239281Sgonzo /* read and store the reset of the state, i.e. pull-up, pull-down, etc */ 333239281Sgonzo if (state) 334239281Sgonzo *state = (reg_val & ti_scm_dev.padconf_sate_mask); 335239281Sgonzo 336239281Sgonzo return (0); 337239281Sgonzo} 338239281Sgonzo 339239281Sgonzo/** 340239281Sgonzo * ti_scm_padconf_init_from_hints - processes the hints for padconf 341239281Sgonzo * @sc: the driver soft context 342239281Sgonzo * 343239281Sgonzo * 344239281Sgonzo * 345239281Sgonzo * LOCKING: 346239281Sgonzo * Internally locks it's own context. 347239281Sgonzo * 348239281Sgonzo * RETURNS: 349239281Sgonzo * 0 on success. 350239281Sgonzo * EINVAL if pin requested is outside valid range or already in use. 351239281Sgonzo */ 352239281Sgonzostatic int 353239281Sgonzoti_scm_padconf_init_from_fdt(struct ti_scm_softc *sc) 354239281Sgonzo{ 355239281Sgonzo const struct ti_scm_padconf *padconf; 356239281Sgonzo const struct ti_scm_padstate *padstates; 357239281Sgonzo int err; 358239281Sgonzo phandle_t node; 359239281Sgonzo int len; 360239281Sgonzo char *fdt_pad_config; 361239281Sgonzo int i; 362239281Sgonzo char *padname, *muxname, *padstate; 363239281Sgonzo 364239281Sgonzo node = ofw_bus_get_node(sc->sc_dev); 365239281Sgonzo len = OF_getproplen(node, "scm-pad-config"); 366239281Sgonzo OF_getprop_alloc(node, "scm-pad-config", 1, (void **)&fdt_pad_config); 367239281Sgonzo 368239281Sgonzo i = len; 369239281Sgonzo while (i > 0) { 370239281Sgonzo padname = fdt_pad_config; 371239281Sgonzo fdt_pad_config += strlen(padname) + 1; 372239281Sgonzo i -= strlen(padname) + 1; 373239281Sgonzo if (i <= 0) 374239281Sgonzo break; 375239281Sgonzo 376239281Sgonzo muxname = fdt_pad_config; 377239281Sgonzo fdt_pad_config += strlen(muxname) + 1; 378239281Sgonzo i -= strlen(muxname) + 1; 379239281Sgonzo if (i <= 0) 380239281Sgonzo break; 381239281Sgonzo 382239281Sgonzo padstate = fdt_pad_config; 383239281Sgonzo fdt_pad_config += strlen(padstate) + 1; 384239281Sgonzo i -= strlen(padstate) + 1; 385239281Sgonzo if (i < 0) 386239281Sgonzo break; 387239281Sgonzo 388239281Sgonzo padconf = ti_scm_dev.padconf; 389239281Sgonzo 390239281Sgonzo while (padconf->ballname != NULL) { 391239281Sgonzo if (strcmp(padconf->ballname, padname) == 0) { 392239281Sgonzo padstates = ti_scm_dev.padstate; 393239281Sgonzo err = 1; 394239281Sgonzo while (padstates->state != NULL) { 395239281Sgonzo if (strcmp(padstates->state, padstate) == 0) { 396239281Sgonzo err = ti_scm_padconf_set_internal(sc, 397245672Skientzle padconf, muxname, padstates->reg); 398239281Sgonzo } 399239281Sgonzo padstates++; 400239281Sgonzo } 401239281Sgonzo if (err) 402245672Skientzle device_printf(sc->sc_dev, 403245672Skientzle "err: failed to configure " 404245672Skientzle "pin \"%s\" as \"%s\"\n", 405245672Skientzle padconf->ballname, 406245672Skientzle muxname); 407239281Sgonzo } 408239281Sgonzo padconf++; 409239281Sgonzo } 410239281Sgonzo } 411239281Sgonzo return (0); 412239281Sgonzo} 413239281Sgonzo 414239281Sgonzo/* 415239281Sgonzo * Device part of OMAP SCM driver 416239281Sgonzo */ 417239281Sgonzo 418239281Sgonzostatic int 419239281Sgonzoti_scm_probe(device_t dev) 420239281Sgonzo{ 421266152Sian 422266152Sian if (!ofw_bus_status_okay(dev)) 423266152Sian return (ENXIO); 424266152Sian 425239281Sgonzo if (!ofw_bus_is_compatible(dev, "ti,scm")) 426239281Sgonzo return (ENXIO); 427239281Sgonzo 428239281Sgonzo device_set_desc(dev, "TI Control Module"); 429239281Sgonzo return (BUS_PROBE_DEFAULT); 430239281Sgonzo} 431239281Sgonzo 432239281Sgonzo/** 433239281Sgonzo * ti_scm_attach - attaches the timer to the simplebus 434239281Sgonzo * @dev: new device 435239281Sgonzo * 436239281Sgonzo * Reserves memory and interrupt resources, stores the softc structure 437239281Sgonzo * globally and registers both the timecount and eventtimer objects. 438239281Sgonzo * 439239281Sgonzo * RETURNS 440239281Sgonzo * Zero on sucess or ENXIO if an error occuried. 441239281Sgonzo */ 442239281Sgonzostatic int 443239281Sgonzoti_scm_attach(device_t dev) 444239281Sgonzo{ 445239281Sgonzo struct ti_scm_softc *sc = device_get_softc(dev); 446239281Sgonzo 447239281Sgonzo if (ti_scm_sc) 448239281Sgonzo return (ENXIO); 449239281Sgonzo 450239281Sgonzo sc->sc_dev = dev; 451239281Sgonzo 452239281Sgonzo if (bus_alloc_resources(dev, ti_scm_res_spec, sc->sc_res)) { 453239281Sgonzo device_printf(dev, "could not allocate resources\n"); 454239281Sgonzo return (ENXIO); 455239281Sgonzo } 456239281Sgonzo 457239281Sgonzo /* Global timer interface */ 458239281Sgonzo sc->sc_bst = rman_get_bustag(sc->sc_res[0]); 459239281Sgonzo sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]); 460239281Sgonzo 461239281Sgonzo ti_scm_sc = sc; 462239281Sgonzo 463239281Sgonzo ti_scm_padconf_init_from_fdt(sc); 464239281Sgonzo 465239281Sgonzo return (0); 466239281Sgonzo} 467239281Sgonzo 468239281Sgonzoint 469239281Sgonzoti_scm_reg_read_4(uint32_t reg, uint32_t *val) 470239281Sgonzo{ 471239281Sgonzo if (!ti_scm_sc) 472239281Sgonzo return (ENXIO); 473239281Sgonzo 474239281Sgonzo *val = ti_scm_read_4(ti_scm_sc, reg); 475239281Sgonzo return (0); 476239281Sgonzo} 477239281Sgonzo 478239281Sgonzoint 479239281Sgonzoti_scm_reg_write_4(uint32_t reg, uint32_t val) 480239281Sgonzo{ 481239281Sgonzo if (!ti_scm_sc) 482239281Sgonzo return (ENXIO); 483239281Sgonzo 484239281Sgonzo ti_scm_write_4(ti_scm_sc, reg, val); 485239281Sgonzo return (0); 486239281Sgonzo} 487239281Sgonzo 488239281Sgonzo 489239281Sgonzostatic device_method_t ti_scm_methods[] = { 490239281Sgonzo DEVMETHOD(device_probe, ti_scm_probe), 491239281Sgonzo DEVMETHOD(device_attach, ti_scm_attach), 492239281Sgonzo { 0, 0 } 493239281Sgonzo}; 494239281Sgonzo 495239281Sgonzostatic driver_t ti_scm_driver = { 496239281Sgonzo "ti_scm", 497239281Sgonzo ti_scm_methods, 498239281Sgonzo sizeof(struct ti_scm_softc), 499239281Sgonzo}; 500239281Sgonzo 501239281Sgonzostatic devclass_t ti_scm_devclass; 502239281Sgonzo 503239281SgonzoDRIVER_MODULE(ti_scm, simplebus, ti_scm_driver, ti_scm_devclass, 0, 0); 504