chipc.c revision 300015
1132744Skan/*- 290285Sobrien * Copyright (c) 2015 Landon Fuller <landon@landonf.org> 3169706Skan * All rights reserved. 418334Speter * 5132744Skan * Redistribution and use in source and binary forms, with or without 618334Speter * modification, are permitted provided that the following conditions 7132744Skan * are met: 818334Speter * 1. Redistributions of source code must retain the above copyright 918334Speter * notice, this list of conditions and the following disclaimer, 1018334Speter * without modification. 1118334Speter * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12132744Skan * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 1318334Speter * redistribution must be conditioned upon including a substantially 1418334Speter * similar Disclaimer requirement for further binary redistribution. 1518334Speter * 1618334Speter * NO WARRANTY 1718334Speter * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18132744Skan * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19169706Skan * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20169706Skan * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 2118334Speter * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 2218334Speter * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2318334Speter * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2418334Speter * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 2518334Speter * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2618334Speter * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 2718334Speter * THE POSSIBILITY OF SUCH DAMAGES. 2818334Speter */ 2918334Speter 3018334Speter#include <sys/cdefs.h> 3118334Speter__FBSDID("$FreeBSD: head/sys/dev/bhnd/cores/chipc/chipc.c 300015 2016-05-17 06:52:53Z adrian $"); 3218334Speter 3390285Sobrien/* 3490285Sobrien * Broadcom ChipCommon driver. 3590285Sobrien * 3618334Speter * With the exception of some very early chipsets, the ChipCommon core 3750654Sobrien * has been included in all HND SoCs and chipsets based on the siba(4) 3850654Sobrien * and bcma(4) interconnects, providing a common interface to chipset 3950654Sobrien * identification, bus enumeration, UARTs, clocks, watchdog interrupts, GPIO, 4090285Sobrien * flash, etc. 4190285Sobrien */ 4290285Sobrien 4390285Sobrien#include <sys/param.h> 44169706Skan#include <sys/kernel.h> 45132744Skan#include <sys/bus.h> 4690285Sobrien#include <sys/module.h> 47169706Skan#include <sys/systm.h> 48132744Skan 4990285Sobrien#include <machine/bus.h> 5090285Sobrien#include <sys/rman.h> 5190285Sobrien#include <machine/resource.h> 5290285Sobrien 5390285Sobrien#include <dev/bhnd/bhnd.h> 5490285Sobrien 5590285Sobrien#include "bhnd_nvram_if.h" 5690285Sobrien 5790285Sobrien#include "chipcreg.h" 5890285Sobrien#include "chipcvar.h" 5990285Sobrien 6090285Sobriendevclass_t bhnd_chipc_devclass; /**< bhnd(4) chipcommon device class */ 6190285Sobrien 6290285Sobrienstatic const struct resource_spec chipc_rspec[CHIPC_MAX_RSPEC] = { 6390285Sobrien { SYS_RES_MEMORY, 0, RF_ACTIVE }, 6490285Sobrien { -1, -1, 0 } 6590285Sobrien}; 6690285Sobrien 6790285Sobrienstatic struct bhnd_device_quirk chipc_quirks[]; 6890285Sobrienstatic struct bhnd_chip_quirk chipc_chip_quirks[]; 6990285Sobrien 7090285Sobrien/* Supported device identifiers */ 7190285Sobrienstatic const struct bhnd_device chipc_devices[] = { 7290285Sobrien BHND_DEVICE(CC, "CC", chipc_quirks, chipc_chip_quirks), 7390285Sobrien BHND_DEVICE_END 7490285Sobrien}; 7590285Sobrien 7690285Sobrien 7790285Sobrien/* Device quirks table */ 7890285Sobrienstatic struct bhnd_device_quirk chipc_quirks[] = { 7990285Sobrien { BHND_HWREV_GTE (32), CHIPC_QUIRK_SUPPORTS_SPROM }, 80132744Skan { BHND_HWREV_GTE (35), CHIPC_QUIRK_SUPPORTS_NFLASH }, 81117407Skan BHND_DEVICE_QUIRK_END 82117407Skan}; 83117407Skan 84117407Skan/* Chip-specific quirks table */ 85117407Skanstatic struct bhnd_chip_quirk chipc_chip_quirks[] = { 86117407Skan /* 4331 12x9 packages */ 8750654Sobrien {{ BHND_CHIP_IP(4331, 4331TN) }, 8850654Sobrien CHIPC_QUIRK_4331_GPIO2_5_MUX_SPROM 8990285Sobrien }, 9050654Sobrien {{ BHND_CHIP_IP(4331, 4331TNA0) }, 9118334Speter CHIPC_QUIRK_4331_GPIO2_5_MUX_SPROM 9218334Speter }, 9318334Speter 9490285Sobrien /* 4331 12x12 packages */ 9518334Speter {{ BHND_CHIP_IPR(4331, 4331TT, HWREV_GTE(1)) }, 96169706Skan CHIPC_QUIRK_4331_EXTPA2_MUX_SPROM 9718334Speter }, 98169706Skan 99169706Skan /* 4331 (all packages/revisions) */ 100169706Skan {{ BHND_CHIP_ID(4331) }, 101169706Skan CHIPC_QUIRK_4331_EXTPA_MUX_SPROM 102132744Skan }, 10318334Speter 104169706Skan /* 4360 family (all revs <= 2) */ 105117407Skan {{ BHND_CHIP_IR(4352, HWREV_LTE(2)) }, 106117407Skan CHIPC_QUIRK_4360_FEM_MUX_SPROM }, 107117407Skan {{ BHND_CHIP_IR(43460, HWREV_LTE(2)) }, 108117407Skan CHIPC_QUIRK_4360_FEM_MUX_SPROM }, 109169706Skan {{ BHND_CHIP_IR(43462, HWREV_LTE(2)) }, 110117407Skan CHIPC_QUIRK_4360_FEM_MUX_SPROM }, 111117407Skan {{ BHND_CHIP_IR(43602, HWREV_LTE(2)) }, 112117407Skan CHIPC_QUIRK_4360_FEM_MUX_SPROM }, 113117407Skan 114117407Skan BHND_CHIP_QUIRK_END 115117407Skan}; 116169706Skan 117169706Skan/* quirk and capability flag convenience macros */ 118117407Skan#define CHIPC_QUIRK(_sc, _name) \ 11990285Sobrien ((_sc)->quirks & CHIPC_QUIRK_ ## _name) 12090285Sobrien 12190285Sobrien#define CHIPC_CAP(_sc, _name) \ 12290285Sobrien ((_sc)->caps & CHIPC_ ## _name) 12390285Sobrien 124117407Skan#define CHIPC_ASSERT_QUIRK(_sc, name) \ 12518334Speter KASSERT(CHIPC_QUIRK((_sc), name), ("quirk " __STRING(_name) " not set")) 126169706Skan 127169706Skan#define CHIPC_ASSERT_CAP(_sc, name) \ 12852295Sobrien KASSERT(CHIPC_CAP((_sc), name), ("capability " __STRING(_name) " not set")) 129132744Skan 130132744Skanstatic bhnd_nvram_src_t chipc_nvram_identify(struct chipc_softc *sc); 131132744Skanstatic int chipc_sprom_init(struct chipc_softc *); 132132744Skanstatic int chipc_enable_sprom_pins(struct chipc_softc *); 133132744Skanstatic int chipc_disable_sprom_pins(struct chipc_softc *); 134132744Skan 135132744Skan 136132744Skanstatic int 137132744Skanchipc_probe(device_t dev) 138169706Skan{ 139169706Skan const struct bhnd_device *id; 140169706Skan 141169706Skan id = bhnd_device_lookup(dev, chipc_devices, sizeof(chipc_devices[0])); 142132744Skan if (id == NULL) 143132744Skan return (ENXIO); 14452295Sobrien 14552295Sobrien bhnd_set_default_core_desc(dev); 14690285Sobrien return (BUS_PROBE_DEFAULT); 14790285Sobrien} 148169706Skan 149169706Skanstatic int 15090285Sobrienchipc_attach(device_t dev) 151117407Skan{ 15290285Sobrien struct chipc_softc *sc; 15390285Sobrien bhnd_addr_t enum_addr; 15490285Sobrien uint32_t ccid_reg; 15590285Sobrien uint8_t chip_type; 15690285Sobrien int error; 15790285Sobrien 158117407Skan sc = device_get_softc(dev); 159169706Skan sc->dev = dev; 160132744Skan sc->quirks = bhnd_device_quirks(dev, chipc_devices, 161169706Skan sizeof(chipc_devices[0])); 162169706Skan 163169706Skan CHIPC_LOCK_INIT(sc); 164169706Skan 165169706Skan /* Allocate bus resources */ 166169706Skan memcpy(sc->rspec, chipc_rspec, sizeof(sc->rspec)); 167169706Skan if ((error = bhnd_alloc_resources(dev, sc->rspec, sc->res))) 16890285Sobrien return (error); 16952295Sobrien 170132744Skan sc->core = sc->res[0]; 171132744Skan 172132744Skan /* Fetch our chipset identification data */ 173132744Skan ccid_reg = bhnd_bus_read_4(sc->core, CHIPC_ID); 174132744Skan chip_type = CHIPC_GET_ATTR(ccid_reg, ID_BUS); 17590285Sobrien 17690285Sobrien switch (chip_type) { 17790285Sobrien case BHND_CHIPTYPE_SIBA: 178169706Skan /* enumeration space starts at the ChipCommon register base. */ 179132744Skan enum_addr = rman_get_start(sc->core->res); 180132744Skan break; 181132744Skan case BHND_CHIPTYPE_BCMA: 182132744Skan case BHND_CHIPTYPE_BCMA_ALT: 183132744Skan enum_addr = bhnd_bus_read_4(sc->core, CHIPC_EROMPTR); 184132744Skan break; 185169706Skan default: 186169706Skan device_printf(dev, "unsupported chip type %hhu\n", chip_type); 187169706Skan error = ENODEV; 188132744Skan goto cleanup; 189132744Skan } 190132744Skan 191132744Skan sc->ccid = bhnd_parse_chipid(ccid_reg, enum_addr); 192132744Skan 193132744Skan /* Fetch capability and status register values */ 194132744Skan sc->caps = bhnd_bus_read_4(sc->core, CHIPC_CAPABILITIES); 195132744Skan sc->cst = bhnd_bus_read_4(sc->core, CHIPC_CHIPST); 196132744Skan 197132744Skan /* Identify NVRAM source */ 198132744Skan sc->nvram_src = chipc_nvram_identify(sc); 199132744Skan 200132744Skan /* Read NVRAM data */ 201132744Skan switch (sc->nvram_src) { 202132744Skan case BHND_NVRAM_SRC_OTP: 203132744Skan // TODO (requires access to OTP hardware) 204132744Skan device_printf(sc->dev, "NVRAM-OTP unsupported\n"); 205132744Skan break; 206132744Skan 207132744Skan case BHND_NVRAM_SRC_NFLASH: 208169706Skan // TODO (requires access to NFLASH hardware) 209132744Skan device_printf(sc->dev, "NVRAM-NFLASH unsupported\n"); 210132744Skan break; 211132744Skan 212132744Skan case BHND_NVRAM_SRC_SPROM: 213132744Skan if ((error = chipc_sprom_init(sc))) 21490285Sobrien goto cleanup; 215132744Skan break; 216132744Skan 217132744Skan case BHND_NVRAM_SRC_UNKNOWN: 218132744Skan /* Handled externally */ 219169706Skan break; 220169706Skan } 221169706Skan 222169706Skan return (0); 223169706Skan 22452295Sobriencleanup: 22590285Sobrien bhnd_release_resources(dev, sc->rspec, sc->res); 22690285Sobrien CHIPC_LOCK_DESTROY(sc); 22790285Sobrien return (error); 22890285Sobrien} 22990285Sobrien 23090285Sobrienstatic int 231117407Skanchipc_detach(device_t dev) 232169706Skan{ 233169706Skan struct chipc_softc *sc; 234117407Skan 235117407Skan sc = device_get_softc(dev); 236169706Skan bhnd_release_resources(dev, sc->rspec, sc->res); 237169706Skan bhnd_sprom_fini(&sc->sprom); 238169706Skan 239169706Skan CHIPC_LOCK_DESTROY(sc); 24096294Sobrien 241117407Skan return (0); 242117407Skan} 24390285Sobrien 244132744Skanstatic int 245132744Skanchipc_suspend(device_t dev) 246132744Skan{ 24790285Sobrien return (0); 248117407Skan} 249117407Skan 250117407Skanstatic int 251117407Skanchipc_resume(device_t dev) 25250654Sobrien{ 253117407Skan return (0); 254117407Skan} 255117407Skan 256117407Skan/** 25750654Sobrien * Initialize local SPROM shadow, if required. 258146908Skan * 259146908Skan * @param sc chipc driver state. 260146908Skan */ 261146908Skanstatic int 26218334Speterchipc_sprom_init(struct chipc_softc *sc) 26318334Speter{ 26418334Speter int error; 26518334Speter 26618334Speter KASSERT(sc->nvram_src == BHND_NVRAM_SRC_SPROM, 26718334Speter ("non-SPROM source (%u)\n", sc->nvram_src)); 26818334Speter 26918334Speter /* Enable access to the SPROM */ 27018334Speter CHIPC_LOCK(sc); 27118334Speter if ((error = chipc_enable_sprom_pins(sc))) 27218334Speter goto failed; 27350654Sobrien 27490285Sobrien /* Initialize SPROM parser */ 27590285Sobrien error = bhnd_sprom_init(&sc->sprom, sc->core, CHIPC_SPROM_OTP); 27650654Sobrien if (error) { 277169706Skan device_printf(sc->dev, "SPROM identification failed: %d\n", 278169706Skan error); 279169706Skan 280169706Skan chipc_disable_sprom_pins(sc); 281169706Skan goto failed; 282169706Skan } 283169706Skan 284169706Skan /* Drop access to the SPROM lines */ 285169706Skan if ((error = chipc_disable_sprom_pins(sc))) { 286169706Skan bhnd_sprom_fini(&sc->sprom); 287169706Skan goto failed; 288169706Skan } 289169706Skan CHIPC_UNLOCK(sc); 290169706Skan 291132744Skan return (0); 292132744Skan 293169706Skanfailed: 294169706Skan CHIPC_UNLOCK(sc); 295132744Skan return (error); 29650654Sobrien} 29750654Sobrien 29850654Sobrien/** 299169706Skan * Determine the NVRAM data source for this device. 300132744Skan * 301132744Skan * @param sc chipc driver state. 302132744Skan */ 303132744Skanstatic bhnd_nvram_src_t 304132744Skanchipc_nvram_identify(struct chipc_softc *sc) 305132744Skan{ 306132744Skan uint32_t srom_ctrl; 307132744Skan 308132744Skan /* Very early devices vend SPROM/OTP/CIS (if at all) via the 309132744Skan * host bridge interface instead of ChipCommon. */ 310132744Skan if (!CHIPC_QUIRK(sc, SUPPORTS_SPROM)) 311132744Skan return (BHND_NVRAM_SRC_UNKNOWN); 31290285Sobrien 31390285Sobrien /* 31490285Sobrien * Later chipset revisions standardized the SPROM capability flags and 31590285Sobrien * register interfaces. 316169706Skan * 317169706Skan * We check for hardware presence in order of precedence. For example, 318169706Skan * SPROM is is always used in preference to internal OTP if found. 319169706Skan */ 320169706Skan if (CHIPC_CAP(sc, CAP_SPROM)) { 321169706Skan srom_ctrl = bhnd_bus_read_4(sc->core, CHIPC_SPROM_CTRL); 322169706Skan if (srom_ctrl & CHIPC_SRC_PRESENT) 323169706Skan return (BHND_NVRAM_SRC_SPROM); 32450654Sobrien } 325169706Skan 32618334Speter /* Check for OTP */ 327117407Skan if (CHIPC_CAP(sc, CAP_OTP_SIZE)) 328117407Skan return (BHND_NVRAM_SRC_OTP); 329117407Skan 330117407Skan /* 331117407Skan * Finally, Northstar chipsets (and possibly other chipsets?) support 332132744Skan * external NAND flash. 333117407Skan */ 334132744Skan if (CHIPC_QUIRK(sc, SUPPORTS_NFLASH) && CHIPC_CAP(sc, CAP_NFLASH)) 335117407Skan return (BHND_NVRAM_SRC_NFLASH); 336117407Skan 337117407Skan /* No NVRAM hardware capability declared */ 338117407Skan return (BHND_NVRAM_SRC_UNKNOWN); 339132744Skan} 340132744Skan 341132744Skan 342117407Skan/** 343117407Skan * If required by this device, enable access to the SPROM. 344117407Skan * 345117407Skan * @param sc chipc driver state. 346117407Skan */ 347117407Skanstatic int 348117407Skanchipc_enable_sprom_pins(struct chipc_softc *sc) 349117407Skan{ 350117407Skan uint32_t cctrl; 351117407Skan 352132744Skan CHIPC_LOCK_ASSERT(sc, MA_OWNED); 353132744Skan 354117407Skan /* Nothing to do? */ 355117407Skan if (!CHIPC_QUIRK(sc, MUX_SPROM)) 356117407Skan return (0); 357117407Skan 358117407Skan cctrl = bhnd_bus_read_4(sc->core, CHIPC_CHIPCTRL); 359117407Skan 360117407Skan /* 4331 devices */ 361117407Skan if (CHIPC_QUIRK(sc, 4331_EXTPA_MUX_SPROM)) { 362132744Skan cctrl &= ~CHIPC_CCTRL4331_EXTPA_EN; 363117407Skan 364117407Skan if (CHIPC_QUIRK(sc, 4331_GPIO2_5_MUX_SPROM)) 365117407Skan cctrl &= ~CHIPC_CCTRL4331_EXTPA_ON_GPIO2_5; 366117407Skan 367117407Skan if (CHIPC_QUIRK(sc, 4331_EXTPA2_MUX_SPROM)) 368117407Skan cctrl &= ~CHIPC_CCTRL4331_EXTPA_EN2; 369132744Skan 370117407Skan bhnd_bus_write_4(sc->core, CHIPC_CHIPCTRL, cctrl); 371117407Skan return (0); 372117407Skan } 373117407Skan 374117407Skan /* 4360 devices */ 375117407Skan if (CHIPC_QUIRK(sc, 4360_FEM_MUX_SPROM)) { 376117407Skan /* Unimplemented */ 377117407Skan } 378117407Skan 379117407Skan /* Refuse to proceed on unsupported devices with muxed SPROM pins */ 380117407Skan device_printf(sc->dev, "muxed sprom lines on unrecognized device\n"); 381117407Skan return (ENXIO); 382132744Skan} 383117407Skan 384132744Skan/** 385117407Skan * If required by this device, revert any GPIO/pin configuration applied 386117407Skan * to allow SPROM access. 387117407Skan * 388117407Skan * @param sc chipc driver state. 389117407Skan */ 390148163Sobrienstatic int 391148163Sobrienchipc_disable_sprom_pins(struct chipc_softc *sc) 392117407Skan{ 393117407Skan uint32_t cctrl; 394132744Skan 395132744Skan CHIPC_LOCK_ASSERT(sc, MA_OWNED); 396117407Skan 397117407Skan /* Nothing to do? */ 398169706Skan if (!CHIPC_QUIRK(sc, MUX_SPROM)) 399169706Skan return (0); 400117407Skan 401117407Skan cctrl = bhnd_bus_read_4(sc->core, CHIPC_CHIPCTRL); 402117407Skan 403117407Skan /* 4331 devices */ 404117407Skan if (CHIPC_QUIRK(sc, 4331_EXTPA_MUX_SPROM)) { 405117407Skan cctrl |= CHIPC_CCTRL4331_EXTPA_EN; 406117407Skan 407117407Skan if (CHIPC_QUIRK(sc, 4331_GPIO2_5_MUX_SPROM)) 408117407Skan cctrl |= CHIPC_CCTRL4331_EXTPA_ON_GPIO2_5; 409117407Skan 410117407Skan if (CHIPC_QUIRK(sc, 4331_EXTPA2_MUX_SPROM)) 411132744Skan cctrl |= CHIPC_CCTRL4331_EXTPA_EN2; 412169706Skan 413117407Skan bhnd_bus_write_4(sc->core, CHIPC_CHIPCTRL, cctrl); 414117407Skan return (0); 415117407Skan } 416117407Skan 417117407Skan /* 4360 devices */ 418117407Skan if (CHIPC_QUIRK(sc, 4360_FEM_MUX_SPROM)) { 419117407Skan /* Unimplemented */ 420117407Skan } 421117407Skan 422117407Skan /* Refuse to proceed on unsupported devices with muxed SPROM pins */ 423117407Skan device_printf(sc->dev, "muxed sprom lines on unrecognized device\n"); 424117407Skan return (ENXIO); 425117407Skan} 426117407Skan 427117407Skanstatic bhnd_nvram_src_t 428117407Skanchipc_nvram_src(device_t dev) 429117407Skan{ 430117407Skan struct chipc_softc *sc = device_get_softc(dev); 431117407Skan return (sc->nvram_src); 432117407Skan} 433117407Skan 434117407Skanstatic int 435117407Skanchipc_nvram_getvar(device_t dev, const char *name, void *buf, size_t *len) 436117407Skan{ 437117407Skan struct chipc_softc *sc; 438117407Skan int error; 439117407Skan 440117407Skan sc = device_get_softc(dev); 441117407Skan 442117407Skan switch (sc->nvram_src) { 443117407Skan case BHND_NVRAM_SRC_SPROM: 444117407Skan CHIPC_LOCK(sc); 445117407Skan error = bhnd_sprom_getvar(&sc->sprom, name, buf, len); 446117407Skan CHIPC_UNLOCK(sc); 447117407Skan return (error); 448117407Skan 449117407Skan case BHND_NVRAM_SRC_OTP: 450117407Skan case BHND_NVRAM_SRC_NFLASH: 451117407Skan /* Currently unsupported */ 452117407Skan return (ENXIO); 453117407Skan 454148163Sobrien case BHND_NVRAM_SRC_UNKNOWN: 455148163Sobrien return (ENODEV); 456117407Skan } 457117407Skan 458132744Skan /* Unknown NVRAM source */ 459132744Skan return (ENODEV); 460132744Skan} 461132744Skan 462132744Skanstatic int 463117407Skanchipc_nvram_setvar(device_t dev, const char *name, const void *buf, 464117407Skan size_t len) 465117407Skan{ 466117407Skan struct chipc_softc *sc; 467117407Skan int error; 468169706Skan 469169706Skan sc = device_get_softc(dev); 470169706Skan 471169706Skan switch (sc->nvram_src) { 472169706Skan case BHND_NVRAM_SRC_SPROM: 473117407Skan CHIPC_LOCK(sc); 474117407Skan error = bhnd_sprom_setvar(&sc->sprom, name, buf, len); 475117407Skan CHIPC_UNLOCK(sc); 47690285Sobrien return (error); 47790285Sobrien 47890285Sobrien case BHND_NVRAM_SRC_OTP: 47990285Sobrien case BHND_NVRAM_SRC_NFLASH: 48090285Sobrien /* Currently unsupported */ 48190285Sobrien return (ENXIO); 48290285Sobrien 48390285Sobrien case BHND_NVRAM_SRC_UNKNOWN: 48490285Sobrien default: 48590285Sobrien return (ENODEV); 48690285Sobrien } 48790285Sobrien 48890285Sobrien /* Unknown NVRAM source */ 489132744Skan return (ENODEV); 490132744Skan} 491132744Skan 492132744Skanstatic void 493169706Skanchipc_write_chipctrl(device_t dev, uint32_t value, uint32_t mask) 49450654Sobrien{ 49590285Sobrien struct chipc_softc *sc; 49690285Sobrien uint32_t cctrl; 49790285Sobrien 498132744Skan sc = device_get_softc(dev); 499169706Skan 500169706Skan CHIPC_LOCK(sc); 50150654Sobrien 50250654Sobrien cctrl = bhnd_bus_read_4(sc->core, CHIPC_CHIPCTRL); 50390285Sobrien cctrl = (cctrl & ~mask) | (value | mask); 50450654Sobrien bhnd_bus_write_4(sc->core, CHIPC_CHIPCTRL, cctrl); 50550654Sobrien 50650654Sobrien CHIPC_UNLOCK(sc); 50750654Sobrien} 50850654Sobrien 50950654Sobrienstatic device_method_t chipc_methods[] = { 51050654Sobrien /* Device interface */ 511132744Skan DEVMETHOD(device_probe, chipc_probe), 51250654Sobrien DEVMETHOD(device_attach, chipc_attach), 51350654Sobrien DEVMETHOD(device_detach, chipc_detach), 51450654Sobrien DEVMETHOD(device_suspend, chipc_suspend), 51550654Sobrien DEVMETHOD(device_resume, chipc_resume), 51650654Sobrien 51750654Sobrien /* ChipCommon interface */ 51850654Sobrien DEVMETHOD(bhnd_chipc_nvram_src, chipc_nvram_src), 51950654Sobrien DEVMETHOD(bhnd_chipc_write_chipctrl, chipc_write_chipctrl), 52050654Sobrien 52150654Sobrien /* NVRAM interface */ 52250654Sobrien DEVMETHOD(bhnd_nvram_getvar, chipc_nvram_getvar), 52350654Sobrien DEVMETHOD(bhnd_nvram_setvar, chipc_nvram_setvar), 52418334Speter 52518334Speter DEVMETHOD_END 526169706Skan}; 52718334Speter 528117407SkanDEFINE_CLASS_0(bhnd_chipc, chipc_driver, chipc_methods, sizeof(struct chipc_softc)); 529117407SkanDRIVER_MODULE(bhnd_chipc, bhnd, chipc_driver, bhnd_chipc_devclass, 0, 0); 530117407SkanMODULE_DEPEND(bhnd_chipc, bhnd, 1, 1, 1); 531117407SkanMODULE_VERSION(bhnd_chipc, 1); 532117407Skan