ti_scm.c revision 245672
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: head/sys/arm/ti/ti_scm.c 245672 2013-01-19 17:12:23Z kientzle $"); 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 166239281Sgonzo printf("setting internal %x for %s\n", reg_val, muxmode); 167239281Sgonzo /* write the register value (16-bit writes) */ 168239281Sgonzo ti_scm_write_2(sc, padconf->reg_off, reg_val); 169239281Sgonzo 170239281Sgonzo return (0); 171239281Sgonzo} 172239281Sgonzo 173239281Sgonzo/** 174239281Sgonzo * ti_scm_padconf_set - sets the muxmode and state for a pad/pin 175239281Sgonzo * @padname: the name of the pad, i.e. "c12" 176239281Sgonzo * @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx" 177239281Sgonzo * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_??? 178239281Sgonzo * 179239281Sgonzo * 180239281Sgonzo * LOCKING: 181239281Sgonzo * Internally locks it's own context. 182239281Sgonzo * 183239281Sgonzo * RETURNS: 184239281Sgonzo * 0 on success. 185239281Sgonzo * EINVAL if pin requested is outside valid range or already in use. 186239281Sgonzo */ 187239281Sgonzoint 188239281Sgonzoti_scm_padconf_set(const char *padname, const char *muxmode, unsigned int state) 189239281Sgonzo{ 190239281Sgonzo const struct ti_scm_padconf *padconf; 191239281Sgonzo 192239281Sgonzo if (!ti_scm_sc) 193239281Sgonzo return (ENXIO); 194239281Sgonzo 195239281Sgonzo /* find the pin in the devmap */ 196239281Sgonzo padconf = ti_scm_padconf_from_name(padname); 197239281Sgonzo if (padconf == NULL) 198239281Sgonzo return (EINVAL); 199239281Sgonzo 200239281Sgonzo return (ti_scm_padconf_set_internal(ti_scm_sc, padconf, muxmode, state)); 201239281Sgonzo} 202239281Sgonzo 203239281Sgonzo/** 204239281Sgonzo * ti_scm_padconf_get - gets the muxmode and state for a pad/pin 205239281Sgonzo * @padname: the name of the pad, i.e. "c12" 206239281Sgonzo * @muxmode: upon return will contain the name of the muxmode of the pin 207240518Seadler * @state: upon return will contain the state of the pad/pin 208239281Sgonzo * 209239281Sgonzo * 210239281Sgonzo * LOCKING: 211239281Sgonzo * Internally locks it's own context. 212239281Sgonzo * 213239281Sgonzo * RETURNS: 214239281Sgonzo * 0 on success. 215239281Sgonzo * EINVAL if pin requested is outside valid range or already in use. 216239281Sgonzo */ 217239281Sgonzoint 218239281Sgonzoti_scm_padconf_get(const char *padname, const char **muxmode, 219239281Sgonzo unsigned int *state) 220239281Sgonzo{ 221239281Sgonzo const struct ti_scm_padconf *padconf; 222239281Sgonzo uint16_t reg_val; 223239281Sgonzo 224239281Sgonzo if (!ti_scm_sc) 225239281Sgonzo return (ENXIO); 226239281Sgonzo 227239281Sgonzo /* find the pin in the devmap */ 228239281Sgonzo padconf = ti_scm_padconf_from_name(padname); 229239281Sgonzo if (padconf == NULL) 230239281Sgonzo return (EINVAL); 231239281Sgonzo 232239281Sgonzo /* read the register value (16-bit reads) */ 233239281Sgonzo reg_val = ti_scm_read_2(ti_scm_sc, padconf->reg_off); 234239281Sgonzo 235239281Sgonzo /* save the state */ 236239281Sgonzo if (state) 237239281Sgonzo *state = (reg_val & ti_scm_dev.padconf_sate_mask); 238239281Sgonzo 239239281Sgonzo /* save the mode */ 240239281Sgonzo if (muxmode) 241239281Sgonzo *muxmode = padconf->muxmodes[(reg_val & ti_scm_dev.padconf_muxmode_mask)]; 242239281Sgonzo 243239281Sgonzo return (0); 244239281Sgonzo} 245239281Sgonzo 246239281Sgonzo/** 247239281Sgonzo * ti_scm_padconf_set_gpiomode - converts a pad to GPIO mode. 248239281Sgonzo * @gpio: the GPIO pin number (0-195) 249239281Sgonzo * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_??? 250239281Sgonzo * 251239281Sgonzo * 252239281Sgonzo * 253239281Sgonzo * LOCKING: 254239281Sgonzo * Internally locks it's own context. 255239281Sgonzo * 256239281Sgonzo * RETURNS: 257239281Sgonzo * 0 on success. 258239281Sgonzo * EINVAL if pin requested is outside valid range or already in use. 259239281Sgonzo */ 260239281Sgonzoint 261239281Sgonzoti_scm_padconf_set_gpiomode(uint32_t gpio, unsigned int state) 262239281Sgonzo{ 263239281Sgonzo const struct ti_scm_padconf *padconf; 264239281Sgonzo uint16_t reg_val; 265239281Sgonzo 266239281Sgonzo if (!ti_scm_sc) 267239281Sgonzo return (ENXIO); 268239281Sgonzo 269239281Sgonzo /* find the gpio pin in the padconf array */ 270239281Sgonzo padconf = ti_scm_dev.padconf; 271239281Sgonzo while (padconf->ballname != NULL) { 272239281Sgonzo if (padconf->gpio_pin == gpio) 273239281Sgonzo break; 274239281Sgonzo padconf++; 275239281Sgonzo } 276239281Sgonzo if (padconf->ballname == NULL) 277239281Sgonzo return (EINVAL); 278239281Sgonzo 279239281Sgonzo /* populate the new value for the PADCONF register */ 280239281Sgonzo reg_val = (uint16_t)(state & ti_scm_dev.padconf_sate_mask); 281239281Sgonzo 282239281Sgonzo /* set the mux mode */ 283239281Sgonzo reg_val |= (uint16_t)(padconf->gpio_mode & ti_scm_dev.padconf_muxmode_mask); 284239281Sgonzo 285239281Sgonzo /* write the register value (16-bit writes) */ 286239281Sgonzo ti_scm_write_2(ti_scm_sc, padconf->reg_off, reg_val); 287239281Sgonzo 288239281Sgonzo return (0); 289239281Sgonzo} 290239281Sgonzo 291239281Sgonzo/** 292239281Sgonzo * ti_scm_padconf_get_gpiomode - gets the current GPIO mode of the pin 293239281Sgonzo * @gpio: the GPIO pin number (0-195) 294239281Sgonzo * @state: upon return will contain the state 295239281Sgonzo * 296239281Sgonzo * 297239281Sgonzo * 298239281Sgonzo * LOCKING: 299239281Sgonzo * Internally locks it's own context. 300239281Sgonzo * 301239281Sgonzo * RETURNS: 302239281Sgonzo * 0 on success. 303239281Sgonzo * EINVAL if pin requested is outside valid range or not configured as GPIO. 304239281Sgonzo */ 305239281Sgonzoint 306239281Sgonzoti_scm_padconf_get_gpiomode(uint32_t gpio, unsigned int *state) 307239281Sgonzo{ 308239281Sgonzo const struct ti_scm_padconf *padconf; 309239281Sgonzo uint16_t reg_val; 310239281Sgonzo 311239281Sgonzo if (!ti_scm_sc) 312239281Sgonzo return (ENXIO); 313239281Sgonzo 314239281Sgonzo /* find the gpio pin in the padconf array */ 315239281Sgonzo padconf = ti_scm_dev.padconf; 316239281Sgonzo while (padconf->ballname != NULL) { 317239281Sgonzo if (padconf->gpio_pin == gpio) 318239281Sgonzo break; 319239281Sgonzo padconf++; 320239281Sgonzo } 321239281Sgonzo if (padconf->ballname == NULL) 322239281Sgonzo return (EINVAL); 323239281Sgonzo 324239281Sgonzo /* read the current register settings */ 325239281Sgonzo reg_val = ti_scm_read_2(ti_scm_sc, padconf->reg_off); 326239281Sgonzo 327239281Sgonzo /* check to make sure the pins is configured as GPIO in the first state */ 328239281Sgonzo if ((reg_val & ti_scm_dev.padconf_muxmode_mask) != padconf->gpio_mode) 329239281Sgonzo return (EINVAL); 330239281Sgonzo 331239281Sgonzo /* read and store the reset of the state, i.e. pull-up, pull-down, etc */ 332239281Sgonzo if (state) 333239281Sgonzo *state = (reg_val & ti_scm_dev.padconf_sate_mask); 334239281Sgonzo 335239281Sgonzo return (0); 336239281Sgonzo} 337239281Sgonzo 338239281Sgonzo/** 339239281Sgonzo * ti_scm_padconf_init_from_hints - processes the hints for padconf 340239281Sgonzo * @sc: the driver soft context 341239281Sgonzo * 342239281Sgonzo * 343239281Sgonzo * 344239281Sgonzo * LOCKING: 345239281Sgonzo * Internally locks it's own context. 346239281Sgonzo * 347239281Sgonzo * RETURNS: 348239281Sgonzo * 0 on success. 349239281Sgonzo * EINVAL if pin requested is outside valid range or already in use. 350239281Sgonzo */ 351239281Sgonzostatic int 352239281Sgonzoti_scm_padconf_init_from_fdt(struct ti_scm_softc *sc) 353239281Sgonzo{ 354239281Sgonzo const struct ti_scm_padconf *padconf; 355239281Sgonzo const struct ti_scm_padstate *padstates; 356239281Sgonzo int err; 357239281Sgonzo phandle_t node; 358239281Sgonzo int len; 359239281Sgonzo char *fdt_pad_config; 360239281Sgonzo int i; 361239281Sgonzo char *padname, *muxname, *padstate; 362239281Sgonzo 363239281Sgonzo node = ofw_bus_get_node(sc->sc_dev); 364239281Sgonzo len = OF_getproplen(node, "scm-pad-config"); 365239281Sgonzo OF_getprop_alloc(node, "scm-pad-config", 1, (void **)&fdt_pad_config); 366239281Sgonzo 367239281Sgonzo i = len; 368239281Sgonzo while (i > 0) { 369239281Sgonzo padname = fdt_pad_config; 370239281Sgonzo fdt_pad_config += strlen(padname) + 1; 371239281Sgonzo i -= strlen(padname) + 1; 372239281Sgonzo if (i <= 0) 373239281Sgonzo break; 374239281Sgonzo 375239281Sgonzo muxname = fdt_pad_config; 376239281Sgonzo fdt_pad_config += strlen(muxname) + 1; 377239281Sgonzo i -= strlen(muxname) + 1; 378239281Sgonzo if (i <= 0) 379239281Sgonzo break; 380239281Sgonzo 381239281Sgonzo padstate = fdt_pad_config; 382239281Sgonzo fdt_pad_config += strlen(padstate) + 1; 383239281Sgonzo i -= strlen(padstate) + 1; 384239281Sgonzo if (i < 0) 385239281Sgonzo break; 386239281Sgonzo 387239281Sgonzo padconf = ti_scm_dev.padconf; 388239281Sgonzo 389239281Sgonzo while (padconf->ballname != NULL) { 390239281Sgonzo if (strcmp(padconf->ballname, padname) == 0) { 391239281Sgonzo padstates = ti_scm_dev.padstate; 392239281Sgonzo err = 1; 393239281Sgonzo while (padstates->state != NULL) { 394239281Sgonzo if (strcmp(padstates->state, padstate) == 0) { 395239281Sgonzo err = ti_scm_padconf_set_internal(sc, 396245672Skientzle padconf, muxname, padstates->reg); 397239281Sgonzo } 398239281Sgonzo padstates++; 399239281Sgonzo } 400239281Sgonzo if (err) 401245672Skientzle device_printf(sc->sc_dev, 402245672Skientzle "err: failed to configure " 403245672Skientzle "pin \"%s\" as \"%s\"\n", 404245672Skientzle padconf->ballname, 405245672Skientzle muxname); 406239281Sgonzo } 407239281Sgonzo padconf++; 408239281Sgonzo } 409239281Sgonzo } 410239281Sgonzo return (0); 411239281Sgonzo} 412239281Sgonzo 413239281Sgonzo/* 414239281Sgonzo * Device part of OMAP SCM driver 415239281Sgonzo */ 416239281Sgonzo 417239281Sgonzostatic int 418239281Sgonzoti_scm_probe(device_t dev) 419239281Sgonzo{ 420239281Sgonzo if (!ofw_bus_is_compatible(dev, "ti,scm")) 421239281Sgonzo return (ENXIO); 422239281Sgonzo 423239281Sgonzo device_set_desc(dev, "TI Control Module"); 424239281Sgonzo return (BUS_PROBE_DEFAULT); 425239281Sgonzo} 426239281Sgonzo 427239281Sgonzo/** 428239281Sgonzo * ti_scm_attach - attaches the timer to the simplebus 429239281Sgonzo * @dev: new device 430239281Sgonzo * 431239281Sgonzo * Reserves memory and interrupt resources, stores the softc structure 432239281Sgonzo * globally and registers both the timecount and eventtimer objects. 433239281Sgonzo * 434239281Sgonzo * RETURNS 435239281Sgonzo * Zero on sucess or ENXIO if an error occuried. 436239281Sgonzo */ 437239281Sgonzostatic int 438239281Sgonzoti_scm_attach(device_t dev) 439239281Sgonzo{ 440239281Sgonzo struct ti_scm_softc *sc = device_get_softc(dev); 441239281Sgonzo 442239281Sgonzo if (ti_scm_sc) 443239281Sgonzo return (ENXIO); 444239281Sgonzo 445239281Sgonzo sc->sc_dev = dev; 446239281Sgonzo 447239281Sgonzo if (bus_alloc_resources(dev, ti_scm_res_spec, sc->sc_res)) { 448239281Sgonzo device_printf(dev, "could not allocate resources\n"); 449239281Sgonzo return (ENXIO); 450239281Sgonzo } 451239281Sgonzo 452239281Sgonzo /* Global timer interface */ 453239281Sgonzo sc->sc_bst = rman_get_bustag(sc->sc_res[0]); 454239281Sgonzo sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]); 455239281Sgonzo 456239281Sgonzo ti_scm_sc = sc; 457239281Sgonzo 458239281Sgonzo ti_scm_padconf_init_from_fdt(sc); 459239281Sgonzo 460239281Sgonzo return (0); 461239281Sgonzo} 462239281Sgonzo 463239281Sgonzoint 464239281Sgonzoti_scm_reg_read_4(uint32_t reg, uint32_t *val) 465239281Sgonzo{ 466239281Sgonzo if (!ti_scm_sc) 467239281Sgonzo return (ENXIO); 468239281Sgonzo 469239281Sgonzo *val = ti_scm_read_4(ti_scm_sc, reg); 470239281Sgonzo return (0); 471239281Sgonzo} 472239281Sgonzo 473239281Sgonzoint 474239281Sgonzoti_scm_reg_write_4(uint32_t reg, uint32_t val) 475239281Sgonzo{ 476239281Sgonzo if (!ti_scm_sc) 477239281Sgonzo return (ENXIO); 478239281Sgonzo 479239281Sgonzo ti_scm_write_4(ti_scm_sc, reg, val); 480239281Sgonzo return (0); 481239281Sgonzo} 482239281Sgonzo 483239281Sgonzo 484239281Sgonzostatic device_method_t ti_scm_methods[] = { 485239281Sgonzo DEVMETHOD(device_probe, ti_scm_probe), 486239281Sgonzo DEVMETHOD(device_attach, ti_scm_attach), 487239281Sgonzo { 0, 0 } 488239281Sgonzo}; 489239281Sgonzo 490239281Sgonzostatic driver_t ti_scm_driver = { 491239281Sgonzo "ti_scm", 492239281Sgonzo ti_scm_methods, 493239281Sgonzo sizeof(struct ti_scm_softc), 494239281Sgonzo}; 495239281Sgonzo 496239281Sgonzostatic devclass_t ti_scm_devclass; 497239281Sgonzo 498239281SgonzoDRIVER_MODULE(ti_scm, simplebus, ti_scm_driver, ti_scm_devclass, 0, 0); 499