1308295Sgonzo/*- 2308295Sgonzo * Copyright (c) 2016 Oleksandr Tymoshenko <gonzo@FreeBSD.org> 3308295Sgonzo * All rights reserved. 4308295Sgonzo * 5308295Sgonzo * Redistribution and use in source and binary forms, with or without 6308295Sgonzo * modification, are permitted provided that the following conditions 7308295Sgonzo * are met: 8308295Sgonzo * 1. Redistributions of source code must retain the above copyright 9308295Sgonzo * notice, this list of conditions and the following disclaimer. 10308295Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 11308295Sgonzo * notice, this list of conditions and the following disclaimer in the 12308295Sgonzo * documentation and/or other materials provided with the distribution. 13308295Sgonzo * 14308295Sgonzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15308295Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16308295Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17308295Sgonzo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18308295Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19308295Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20308295Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21308295Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22308295Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23308295Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24308295Sgonzo * SUCH DAMAGE. 25308295Sgonzo */ 26308295Sgonzo 27308295Sgonzo#include <sys/cdefs.h> 28308295Sgonzo__FBSDID("$FreeBSD: stable/11/sys/dev/gpio/bytgpio.c 309375 2016-12-01 22:22:19Z gonzo $"); 29308295Sgonzo 30308295Sgonzo#include "opt_acpi.h" 31308295Sgonzo 32308295Sgonzo#include <sys/param.h> 33308295Sgonzo#include <sys/bus.h> 34308295Sgonzo#include <sys/gpio.h> 35308295Sgonzo#include <sys/kernel.h> 36308295Sgonzo#include <sys/module.h> 37308295Sgonzo#include <sys/proc.h> 38308295Sgonzo#include <sys/rman.h> 39308295Sgonzo 40308295Sgonzo#include <machine/bus.h> 41308295Sgonzo#include <machine/resource.h> 42308295Sgonzo 43308295Sgonzo#include <contrib/dev/acpica/include/acpi.h> 44308295Sgonzo#include <contrib/dev/acpica/include/accommon.h> 45308295Sgonzo 46308295Sgonzo#include <dev/acpica/acpivar.h> 47308295Sgonzo#include <dev/gpio/gpiobusvar.h> 48308295Sgonzo 49308295Sgonzo#include "gpio_if.h" 50308295Sgonzo 51308295Sgonzo/** 52308295Sgonzo * Macros for driver mutex locking 53308295Sgonzo */ 54308295Sgonzo#define BYTGPIO_LOCK(_sc) mtx_lock_spin(&(_sc)->sc_mtx) 55308295Sgonzo#define BYTGPIO_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->sc_mtx) 56308295Sgonzo#define BYTGPIO_LOCK_INIT(_sc) \ 57308295Sgonzo mtx_init(&_sc->sc_mtx, device_get_nameunit((_sc)->sc_dev), \ 58308295Sgonzo "bytgpio", MTX_SPIN) 59308295Sgonzo#define BYTGPIO_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx) 60308295Sgonzo#define BYTGPIO_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED) 61308295Sgonzo#define BYTGPIO_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->sc_mtx, MA_NOTOWNED) 62308295Sgonzo 63309375Sgonzostruct pinmap_info { 64309375Sgonzo int reg; 65309375Sgonzo int pad_func; 66309375Sgonzo}; 67309375Sgonzo 68309375Sgonzo/* Ignore function check, no info is available at the moment */ 69309375Sgonzo#define PADCONF_FUNC_ANY -1 70309375Sgonzo 71309375Sgonzo#define GPIO_PIN_MAP(r, f) { .reg = (r), .pad_func = (f) } 72309375Sgonzo 73308295Sgonzostruct bytgpio_softc { 74308295Sgonzo ACPI_HANDLE sc_handle; 75308295Sgonzo device_t sc_dev; 76308295Sgonzo device_t sc_busdev; 77308295Sgonzo struct mtx sc_mtx; 78308295Sgonzo int sc_mem_rid; 79308295Sgonzo struct resource *sc_mem_res; 80308295Sgonzo int sc_npins; 81308295Sgonzo const char* sc_bank_prefix; 82309375Sgonzo const struct pinmap_info *sc_pinpad_map; 83309375Sgonzo /* List of current functions for pads shared by GPIO */ 84309375Sgonzo int *sc_pad_funcs; 85308295Sgonzo}; 86308295Sgonzo 87308295Sgonzostatic int bytgpio_probe(device_t dev); 88308295Sgonzostatic int bytgpio_attach(device_t dev); 89309375Sgonzostatic int bytgpio_detach(device_t dev); 90308295Sgonzo 91309375Sgonzo#define SCORE_UID 1 92309375Sgonzo#define SCORE_BANK_PREFIX "GPIO_S0_SC" 93309375Sgonzoconst struct pinmap_info bytgpio_score_pins[] = { 94309375Sgonzo GPIO_PIN_MAP(85, 0), 95309375Sgonzo GPIO_PIN_MAP(89, 0), 96309375Sgonzo GPIO_PIN_MAP(93, 0), 97309375Sgonzo GPIO_PIN_MAP(96, 0), 98309375Sgonzo GPIO_PIN_MAP(99, 0), 99309375Sgonzo GPIO_PIN_MAP(102, 0), 100309375Sgonzo GPIO_PIN_MAP(98, 0), 101309375Sgonzo GPIO_PIN_MAP(101, 0), 102309375Sgonzo GPIO_PIN_MAP(34, 0), 103309375Sgonzo GPIO_PIN_MAP(37, 0), 104309375Sgonzo GPIO_PIN_MAP(36, 0), 105309375Sgonzo GPIO_PIN_MAP(38, 0), 106309375Sgonzo GPIO_PIN_MAP(39, 0), 107309375Sgonzo GPIO_PIN_MAP(35, 0), 108309375Sgonzo GPIO_PIN_MAP(40, 0), 109309375Sgonzo GPIO_PIN_MAP(84, 0), 110309375Sgonzo GPIO_PIN_MAP(62, 0), 111309375Sgonzo GPIO_PIN_MAP(61, 0), 112309375Sgonzo GPIO_PIN_MAP(64, 0), 113309375Sgonzo GPIO_PIN_MAP(59, 0), 114309375Sgonzo GPIO_PIN_MAP(54, 0), 115309375Sgonzo GPIO_PIN_MAP(56, 0), 116309375Sgonzo GPIO_PIN_MAP(60, 0), 117309375Sgonzo GPIO_PIN_MAP(55, 0), 118309375Sgonzo GPIO_PIN_MAP(63, 0), 119309375Sgonzo GPIO_PIN_MAP(57, 0), 120309375Sgonzo GPIO_PIN_MAP(51, 0), 121309375Sgonzo GPIO_PIN_MAP(50, 0), 122309375Sgonzo GPIO_PIN_MAP(53, 0), 123309375Sgonzo GPIO_PIN_MAP(47, 0), 124309375Sgonzo GPIO_PIN_MAP(52, 0), 125309375Sgonzo GPIO_PIN_MAP(49, 0), 126309375Sgonzo GPIO_PIN_MAP(48, 0), 127309375Sgonzo GPIO_PIN_MAP(43, 0), 128309375Sgonzo GPIO_PIN_MAP(46, 0), 129309375Sgonzo GPIO_PIN_MAP(41, 0), 130309375Sgonzo GPIO_PIN_MAP(45, 0), 131309375Sgonzo GPIO_PIN_MAP(42, 0), 132309375Sgonzo GPIO_PIN_MAP(58, 0), 133309375Sgonzo GPIO_PIN_MAP(44, 0), 134309375Sgonzo GPIO_PIN_MAP(95, 0), 135309375Sgonzo GPIO_PIN_MAP(105, 0), 136309375Sgonzo GPIO_PIN_MAP(70, 0), 137309375Sgonzo GPIO_PIN_MAP(68, 0), 138309375Sgonzo GPIO_PIN_MAP(67, 0), 139309375Sgonzo GPIO_PIN_MAP(66, 0), 140309375Sgonzo GPIO_PIN_MAP(69, 0), 141309375Sgonzo GPIO_PIN_MAP(71, 0), 142309375Sgonzo GPIO_PIN_MAP(65, 0), 143309375Sgonzo GPIO_PIN_MAP(72, 0), 144309375Sgonzo GPIO_PIN_MAP(86, 0), 145309375Sgonzo GPIO_PIN_MAP(90, 0), 146309375Sgonzo GPIO_PIN_MAP(88, 0), 147309375Sgonzo GPIO_PIN_MAP(92, 0), 148309375Sgonzo GPIO_PIN_MAP(103, 0), 149309375Sgonzo GPIO_PIN_MAP(77, 0), 150309375Sgonzo GPIO_PIN_MAP(79, 0), 151309375Sgonzo GPIO_PIN_MAP(83, 0), 152309375Sgonzo GPIO_PIN_MAP(78, 0), 153309375Sgonzo GPIO_PIN_MAP(81, 0), 154309375Sgonzo GPIO_PIN_MAP(80, 0), 155309375Sgonzo GPIO_PIN_MAP(82, 0), 156309375Sgonzo GPIO_PIN_MAP(13, 0), 157309375Sgonzo GPIO_PIN_MAP(12, 0), 158309375Sgonzo GPIO_PIN_MAP(15, 0), 159309375Sgonzo GPIO_PIN_MAP(14, 0), 160309375Sgonzo GPIO_PIN_MAP(17, 0), 161309375Sgonzo GPIO_PIN_MAP(18, 0), 162309375Sgonzo GPIO_PIN_MAP(19, 0), 163309375Sgonzo GPIO_PIN_MAP(16, 0), 164309375Sgonzo GPIO_PIN_MAP(2, 0), 165309375Sgonzo GPIO_PIN_MAP(1, 0), 166309375Sgonzo GPIO_PIN_MAP(0, 0), 167309375Sgonzo GPIO_PIN_MAP(4, 0), 168309375Sgonzo GPIO_PIN_MAP(6, 0), 169309375Sgonzo GPIO_PIN_MAP(7, 0), 170309375Sgonzo GPIO_PIN_MAP(9, 0), 171309375Sgonzo GPIO_PIN_MAP(8, 0), 172309375Sgonzo GPIO_PIN_MAP(33, 0), 173309375Sgonzo GPIO_PIN_MAP(32, 0), 174309375Sgonzo GPIO_PIN_MAP(31, 0), 175309375Sgonzo GPIO_PIN_MAP(30, 0), 176309375Sgonzo GPIO_PIN_MAP(29, 0), 177309375Sgonzo GPIO_PIN_MAP(27, 0), 178309375Sgonzo GPIO_PIN_MAP(25, 0), 179309375Sgonzo GPIO_PIN_MAP(28, 0), 180309375Sgonzo GPIO_PIN_MAP(26, 0), 181309375Sgonzo GPIO_PIN_MAP(23, 0), 182309375Sgonzo GPIO_PIN_MAP(21, 0), 183309375Sgonzo GPIO_PIN_MAP(20, 0), 184309375Sgonzo GPIO_PIN_MAP(24, 0), 185309375Sgonzo GPIO_PIN_MAP(22, 0), 186309375Sgonzo GPIO_PIN_MAP(5, 1), 187309375Sgonzo GPIO_PIN_MAP(3, 1), 188309375Sgonzo GPIO_PIN_MAP(10, 0), 189309375Sgonzo GPIO_PIN_MAP(11, 0), 190309375Sgonzo GPIO_PIN_MAP(106, 0), 191309375Sgonzo GPIO_PIN_MAP(87, 0), 192309375Sgonzo GPIO_PIN_MAP(91, 0), 193309375Sgonzo GPIO_PIN_MAP(104, 0), 194309375Sgonzo GPIO_PIN_MAP(97, 0), 195309375Sgonzo GPIO_PIN_MAP(100, 0) 196308295Sgonzo}; 197308295Sgonzo 198309375Sgonzo#define SCORE_PINS nitems(bytgpio_score_pins) 199309375Sgonzo 200309375Sgonzo#define NCORE_UID 2 201309375Sgonzo#define NCORE_BANK_PREFIX "GPIO_S0_NC" 202309375Sgonzoconst struct pinmap_info bytgpio_ncore_pins[] = { 203309375Sgonzo GPIO_PIN_MAP(19, PADCONF_FUNC_ANY), 204309375Sgonzo GPIO_PIN_MAP(18, PADCONF_FUNC_ANY), 205309375Sgonzo GPIO_PIN_MAP(17, PADCONF_FUNC_ANY), 206309375Sgonzo GPIO_PIN_MAP(20, PADCONF_FUNC_ANY), 207309375Sgonzo GPIO_PIN_MAP(21, PADCONF_FUNC_ANY), 208309375Sgonzo GPIO_PIN_MAP(22, PADCONF_FUNC_ANY), 209309375Sgonzo GPIO_PIN_MAP(24, PADCONF_FUNC_ANY), 210309375Sgonzo GPIO_PIN_MAP(25, PADCONF_FUNC_ANY), 211309375Sgonzo GPIO_PIN_MAP(23, PADCONF_FUNC_ANY), 212309375Sgonzo GPIO_PIN_MAP(16, PADCONF_FUNC_ANY), 213309375Sgonzo GPIO_PIN_MAP(14, PADCONF_FUNC_ANY), 214309375Sgonzo GPIO_PIN_MAP(15, PADCONF_FUNC_ANY), 215309375Sgonzo GPIO_PIN_MAP(12, PADCONF_FUNC_ANY), 216309375Sgonzo GPIO_PIN_MAP(26, PADCONF_FUNC_ANY), 217309375Sgonzo GPIO_PIN_MAP(27, PADCONF_FUNC_ANY), 218309375Sgonzo GPIO_PIN_MAP(1, PADCONF_FUNC_ANY), 219309375Sgonzo GPIO_PIN_MAP(4, PADCONF_FUNC_ANY), 220309375Sgonzo GPIO_PIN_MAP(8, PADCONF_FUNC_ANY), 221309375Sgonzo GPIO_PIN_MAP(11, PADCONF_FUNC_ANY), 222309375Sgonzo GPIO_PIN_MAP(0, PADCONF_FUNC_ANY), 223309375Sgonzo GPIO_PIN_MAP(3, PADCONF_FUNC_ANY), 224309375Sgonzo GPIO_PIN_MAP(6, PADCONF_FUNC_ANY), 225309375Sgonzo GPIO_PIN_MAP(10, PADCONF_FUNC_ANY), 226309375Sgonzo GPIO_PIN_MAP(13, PADCONF_FUNC_ANY), 227309375Sgonzo GPIO_PIN_MAP(2, PADCONF_FUNC_ANY), 228309375Sgonzo GPIO_PIN_MAP(5, PADCONF_FUNC_ANY), 229309375Sgonzo GPIO_PIN_MAP(9, PADCONF_FUNC_ANY), 230309375Sgonzo GPIO_PIN_MAP(7, PADCONF_FUNC_ANY) 231308295Sgonzo}; 232308295Sgonzo#define NCORE_PINS nitems(bytgpio_ncore_pins) 233308295Sgonzo 234309375Sgonzo#define SUS_UID 3 235309375Sgonzo#define SUS_BANK_PREFIX "GPIO_S5_" 236309375Sgonzoconst struct pinmap_info bytgpio_sus_pins[] = { 237309375Sgonzo GPIO_PIN_MAP(29, 0), 238309375Sgonzo GPIO_PIN_MAP(33, 0), 239309375Sgonzo GPIO_PIN_MAP(30, 0), 240309375Sgonzo GPIO_PIN_MAP(31, 0), 241309375Sgonzo GPIO_PIN_MAP(32, 0), 242309375Sgonzo GPIO_PIN_MAP(34, 0), 243309375Sgonzo GPIO_PIN_MAP(36, 0), 244309375Sgonzo GPIO_PIN_MAP(35, 0), 245309375Sgonzo GPIO_PIN_MAP(38, 0), 246309375Sgonzo GPIO_PIN_MAP(37, 0), 247309375Sgonzo GPIO_PIN_MAP(18, 0), 248309375Sgonzo GPIO_PIN_MAP(7, 1), 249309375Sgonzo GPIO_PIN_MAP(11, 1), 250309375Sgonzo GPIO_PIN_MAP(20, 1), 251309375Sgonzo GPIO_PIN_MAP(17, 1), 252309375Sgonzo GPIO_PIN_MAP(1, 1), 253309375Sgonzo GPIO_PIN_MAP(8, 1), 254309375Sgonzo GPIO_PIN_MAP(10, 1), 255309375Sgonzo GPIO_PIN_MAP(19, 1), 256309375Sgonzo GPIO_PIN_MAP(12, 1), 257309375Sgonzo GPIO_PIN_MAP(0, 1), 258309375Sgonzo GPIO_PIN_MAP(2, 1), 259309375Sgonzo GPIO_PIN_MAP(23, 0), 260309375Sgonzo GPIO_PIN_MAP(39, 0), 261309375Sgonzo GPIO_PIN_MAP(28, 0), 262309375Sgonzo GPIO_PIN_MAP(27, 0), 263309375Sgonzo GPIO_PIN_MAP(22, 0), 264309375Sgonzo GPIO_PIN_MAP(21, 0), 265309375Sgonzo GPIO_PIN_MAP(24, 0), 266309375Sgonzo GPIO_PIN_MAP(25, 0), 267309375Sgonzo GPIO_PIN_MAP(26, 0), 268309375Sgonzo GPIO_PIN_MAP(51, 0), 269309375Sgonzo GPIO_PIN_MAP(56, 0), 270309375Sgonzo GPIO_PIN_MAP(54, 0), 271309375Sgonzo GPIO_PIN_MAP(49, 0), 272309375Sgonzo GPIO_PIN_MAP(55, 0), 273309375Sgonzo GPIO_PIN_MAP(48, 0), 274309375Sgonzo GPIO_PIN_MAP(57, 0), 275309375Sgonzo GPIO_PIN_MAP(50, 0), 276309375Sgonzo GPIO_PIN_MAP(58, 0), 277309375Sgonzo GPIO_PIN_MAP(52, 0), 278309375Sgonzo GPIO_PIN_MAP(53, 0), 279309375Sgonzo GPIO_PIN_MAP(59, 0), 280309375Sgonzo GPIO_PIN_MAP(40, 0) 281308295Sgonzo}; 282309375Sgonzo 283308295Sgonzo#define SUS_PINS nitems(bytgpio_sus_pins) 284308295Sgonzo 285309375Sgonzo#define BYGPIO_PIN_REGISTER(sc, pin, r) ((sc)->sc_pinpad_map[(pin)].reg * 16 + (r)) 286308295Sgonzo#define BYTGPIO_PCONF0 0x0000 287309375Sgonzo#define BYTGPIO_PCONF0_FUNC_MASK 7 288308295Sgonzo#define BYTGPIO_PAD_VAL 0x0008 289308295Sgonzo#define BYTGPIO_PAD_VAL_LEVEL (1 << 0) 290308295Sgonzo#define BYTGPIO_PAD_VAL_I_OUTPUT_ENABLED (1 << 1) 291308295Sgonzo#define BYTGPIO_PAD_VAL_I_INPUT_ENABLED (1 << 2) 292308295Sgonzo#define BYTGPIO_PAD_VAL_DIR_MASK (3 << 1) 293308295Sgonzo 294308295Sgonzostatic inline uint32_t 295308295Sgonzobytgpio_read_4(struct bytgpio_softc *sc, bus_size_t off) 296308295Sgonzo{ 297308295Sgonzo return (bus_read_4(sc->sc_mem_res, off)); 298308295Sgonzo} 299308295Sgonzo 300308295Sgonzostatic inline void 301308295Sgonzobytgpio_write_4(struct bytgpio_softc *sc, bus_size_t off, 302308295Sgonzo uint32_t val) 303308295Sgonzo{ 304308295Sgonzo bus_write_4(sc->sc_mem_res, off, val); 305308295Sgonzo} 306308295Sgonzo 307308295Sgonzostatic device_t 308308295Sgonzobytgpio_get_bus(device_t dev) 309308295Sgonzo{ 310308295Sgonzo struct bytgpio_softc *sc; 311308295Sgonzo 312308295Sgonzo sc = device_get_softc(dev); 313308295Sgonzo 314308295Sgonzo return (sc->sc_busdev); 315308295Sgonzo} 316308295Sgonzo 317308295Sgonzostatic int 318308295Sgonzobytgpio_pin_max(device_t dev, int *maxpin) 319308295Sgonzo{ 320308295Sgonzo struct bytgpio_softc *sc; 321308295Sgonzo 322308295Sgonzo sc = device_get_softc(dev); 323308295Sgonzo 324308295Sgonzo *maxpin = sc->sc_npins - 1; 325308295Sgonzo 326308295Sgonzo return (0); 327308295Sgonzo} 328308295Sgonzo 329308295Sgonzostatic int 330308295Sgonzobytgpio_valid_pin(struct bytgpio_softc *sc, int pin) 331308295Sgonzo{ 332308295Sgonzo 333308295Sgonzo if (pin >= sc->sc_npins || sc->sc_mem_res == NULL) 334308295Sgonzo return (EINVAL); 335308295Sgonzo 336308295Sgonzo return (0); 337308295Sgonzo} 338308295Sgonzo 339309375Sgonzo/* 340309375Sgonzo * Returns true if pad configured to be used as GPIO 341309375Sgonzo */ 342309375Sgonzostatic bool 343309375Sgonzobytgpio_pad_is_gpio(struct bytgpio_softc *sc, int pin) 344309375Sgonzo{ 345309375Sgonzo if ((sc->sc_pinpad_map[pin].pad_func == PADCONF_FUNC_ANY) || 346309375Sgonzo (sc->sc_pad_funcs[pin] == sc->sc_pinpad_map[pin].pad_func)) 347309375Sgonzo return (true); 348309375Sgonzo else 349309375Sgonzo return (false); 350309375Sgonzo} 351309375Sgonzo 352308295Sgonzostatic int 353308295Sgonzobytgpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 354308295Sgonzo{ 355308295Sgonzo struct bytgpio_softc *sc; 356308295Sgonzo 357308295Sgonzo sc = device_get_softc(dev); 358308295Sgonzo if (bytgpio_valid_pin(sc, pin) != 0) 359308295Sgonzo return (EINVAL); 360308295Sgonzo 361309375Sgonzo *caps = 0; 362309375Sgonzo if (bytgpio_pad_is_gpio(sc, pin)) 363309375Sgonzo *caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT; 364308295Sgonzo 365308295Sgonzo return (0); 366308295Sgonzo} 367308295Sgonzo 368308295Sgonzostatic int 369308295Sgonzobytgpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 370308295Sgonzo{ 371308295Sgonzo struct bytgpio_softc *sc; 372308295Sgonzo uint32_t reg, val; 373308295Sgonzo 374308295Sgonzo sc = device_get_softc(dev); 375308295Sgonzo if (bytgpio_valid_pin(sc, pin) != 0) 376308295Sgonzo return (EINVAL); 377308295Sgonzo 378309375Sgonzo *flags = 0; 379309375Sgonzo if (!bytgpio_pad_is_gpio(sc, pin)) 380309375Sgonzo return (0); 381309375Sgonzo 382308295Sgonzo /* Get the current pin state */ 383308295Sgonzo BYTGPIO_LOCK(sc); 384308295Sgonzo reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL); 385308295Sgonzo val = bytgpio_read_4(sc, reg); 386308295Sgonzo if ((val & BYTGPIO_PAD_VAL_I_OUTPUT_ENABLED) == 0) 387308295Sgonzo *flags |= GPIO_PIN_OUTPUT; 388308295Sgonzo /* 389308295Sgonzo * this bit can be cleared to read current output value 390308295Sgonzo * sou output bit takes precedense 391308295Sgonzo */ 392308295Sgonzo else if ((val & BYTGPIO_PAD_VAL_I_INPUT_ENABLED) == 0) 393308295Sgonzo *flags |= GPIO_PIN_INPUT; 394308295Sgonzo BYTGPIO_UNLOCK(sc); 395308295Sgonzo 396308295Sgonzo return (0); 397308295Sgonzo} 398308295Sgonzo 399308295Sgonzostatic int 400308295Sgonzobytgpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 401308295Sgonzo{ 402308295Sgonzo struct bytgpio_softc *sc; 403308295Sgonzo uint32_t reg, val; 404308295Sgonzo uint32_t allowed; 405308295Sgonzo 406308295Sgonzo sc = device_get_softc(dev); 407308295Sgonzo if (bytgpio_valid_pin(sc, pin) != 0) 408308295Sgonzo return (EINVAL); 409308295Sgonzo 410309375Sgonzo if (bytgpio_pad_is_gpio(sc, pin)) 411309375Sgonzo allowed = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT; 412309375Sgonzo else 413309375Sgonzo allowed = 0; 414308295Sgonzo 415308295Sgonzo /* 416308295Sgonzo * Only directtion flag allowed 417308295Sgonzo */ 418308295Sgonzo if (flags & ~allowed) 419308295Sgonzo return (EINVAL); 420308295Sgonzo 421308295Sgonzo /* 422308295Sgonzo * Not both directions simultaneously 423308295Sgonzo */ 424308295Sgonzo if ((flags & allowed) == allowed) 425308295Sgonzo return (EINVAL); 426308295Sgonzo 427308295Sgonzo /* Set the GPIO mode and state */ 428308295Sgonzo BYTGPIO_LOCK(sc); 429308295Sgonzo reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL); 430308295Sgonzo val = bytgpio_read_4(sc, reg); 431308295Sgonzo val = val | BYTGPIO_PAD_VAL_DIR_MASK; 432308295Sgonzo if (flags & GPIO_PIN_INPUT) 433308295Sgonzo val = val & ~BYTGPIO_PAD_VAL_I_INPUT_ENABLED; 434308295Sgonzo if (flags & GPIO_PIN_OUTPUT) 435308295Sgonzo val = val & ~BYTGPIO_PAD_VAL_I_OUTPUT_ENABLED; 436308295Sgonzo bytgpio_write_4(sc, reg, val); 437308295Sgonzo BYTGPIO_UNLOCK(sc); 438308295Sgonzo 439308295Sgonzo return (0); 440308295Sgonzo} 441308295Sgonzo 442308295Sgonzostatic int 443308295Sgonzobytgpio_pin_getname(device_t dev, uint32_t pin, char *name) 444308295Sgonzo{ 445308295Sgonzo struct bytgpio_softc *sc; 446308295Sgonzo 447308295Sgonzo sc = device_get_softc(dev); 448308295Sgonzo if (bytgpio_valid_pin(sc, pin) != 0) 449308295Sgonzo return (EINVAL); 450308295Sgonzo 451308295Sgonzo /* Set a very simple name */ 452308295Sgonzo snprintf(name, GPIOMAXNAME, "%s%u", sc->sc_bank_prefix, pin); 453308295Sgonzo name[GPIOMAXNAME - 1] = '\0'; 454308295Sgonzo 455308295Sgonzo return (0); 456308295Sgonzo} 457308295Sgonzo 458308295Sgonzostatic int 459308295Sgonzobytgpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 460308295Sgonzo{ 461308295Sgonzo struct bytgpio_softc *sc; 462308295Sgonzo uint32_t reg, val; 463308295Sgonzo 464308295Sgonzo sc = device_get_softc(dev); 465308295Sgonzo if (bytgpio_valid_pin(sc, pin) != 0) 466308295Sgonzo return (EINVAL); 467308295Sgonzo 468309375Sgonzo if (!bytgpio_pad_is_gpio(sc, pin)) 469309375Sgonzo return (EINVAL); 470309375Sgonzo 471308295Sgonzo BYTGPIO_LOCK(sc); 472308295Sgonzo reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL); 473308295Sgonzo val = bytgpio_read_4(sc, reg); 474308295Sgonzo if (value == GPIO_PIN_LOW) 475308295Sgonzo val = val & ~BYTGPIO_PAD_VAL_LEVEL; 476308295Sgonzo else 477308295Sgonzo val = val | BYTGPIO_PAD_VAL_LEVEL; 478308295Sgonzo bytgpio_write_4(sc, reg, val); 479308295Sgonzo BYTGPIO_UNLOCK(sc); 480308295Sgonzo 481308295Sgonzo return (0); 482308295Sgonzo} 483308295Sgonzo 484308295Sgonzostatic int 485308295Sgonzobytgpio_pin_get(device_t dev, uint32_t pin, unsigned int *value) 486308295Sgonzo{ 487308295Sgonzo struct bytgpio_softc *sc; 488308295Sgonzo uint32_t reg, val; 489308295Sgonzo 490308295Sgonzo sc = device_get_softc(dev); 491308295Sgonzo if (bytgpio_valid_pin(sc, pin) != 0) 492308295Sgonzo return (EINVAL); 493309375Sgonzo /* 494309375Sgonzo * Report non-GPIO pads as pin LOW 495309375Sgonzo */ 496309375Sgonzo if (!bytgpio_pad_is_gpio(sc, pin)) { 497309375Sgonzo *value = GPIO_PIN_LOW; 498309375Sgonzo return (0); 499309375Sgonzo } 500308295Sgonzo 501308295Sgonzo BYTGPIO_LOCK(sc); 502308295Sgonzo reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL); 503308295Sgonzo /* 504308295Sgonzo * And read actual value 505308295Sgonzo */ 506308295Sgonzo val = bytgpio_read_4(sc, reg); 507308295Sgonzo if (val & BYTGPIO_PAD_VAL_LEVEL) 508308295Sgonzo *value = GPIO_PIN_HIGH; 509308295Sgonzo else 510308295Sgonzo *value = GPIO_PIN_LOW; 511308295Sgonzo BYTGPIO_UNLOCK(sc); 512308295Sgonzo 513308295Sgonzo return (0); 514308295Sgonzo} 515308295Sgonzo 516308295Sgonzostatic int 517308295Sgonzobytgpio_pin_toggle(device_t dev, uint32_t pin) 518308295Sgonzo{ 519308295Sgonzo struct bytgpio_softc *sc; 520308295Sgonzo uint32_t reg, val; 521308295Sgonzo 522308295Sgonzo sc = device_get_softc(dev); 523308295Sgonzo if (bytgpio_valid_pin(sc, pin) != 0) 524308295Sgonzo return (EINVAL); 525308295Sgonzo 526309375Sgonzo if (!bytgpio_pad_is_gpio(sc, pin)) 527309375Sgonzo return (EINVAL); 528309375Sgonzo 529308295Sgonzo /* Toggle the pin */ 530308295Sgonzo BYTGPIO_LOCK(sc); 531308295Sgonzo reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL); 532308295Sgonzo val = bytgpio_read_4(sc, reg); 533308295Sgonzo val = val ^ BYTGPIO_PAD_VAL_LEVEL; 534308295Sgonzo bytgpio_write_4(sc, reg, val); 535308295Sgonzo BYTGPIO_UNLOCK(sc); 536308295Sgonzo 537308295Sgonzo return (0); 538308295Sgonzo} 539308295Sgonzo 540308295Sgonzostatic int 541308295Sgonzobytgpio_probe(device_t dev) 542308295Sgonzo{ 543308295Sgonzo static char *gpio_ids[] = { "INT33FC", NULL }; 544308295Sgonzo 545308295Sgonzo if (acpi_disabled("gpio") || 546308295Sgonzo ACPI_ID_PROBE(device_get_parent(dev), dev, gpio_ids) == NULL) 547308295Sgonzo return (ENXIO); 548308295Sgonzo 549308295Sgonzo device_set_desc(dev, "Intel Baytrail GPIO Controller"); 550308295Sgonzo return (0); 551308295Sgonzo} 552308295Sgonzo 553308295Sgonzostatic int 554308295Sgonzobytgpio_attach(device_t dev) 555308295Sgonzo{ 556308295Sgonzo struct bytgpio_softc *sc; 557308295Sgonzo ACPI_STATUS status; 558308295Sgonzo int uid; 559309375Sgonzo int pin; 560309375Sgonzo uint32_t reg, val; 561308295Sgonzo 562308295Sgonzo sc = device_get_softc(dev); 563308295Sgonzo sc->sc_dev = dev; 564308295Sgonzo sc->sc_handle = acpi_get_handle(dev); 565308295Sgonzo status = acpi_GetInteger(sc->sc_handle, "_UID", &uid); 566308295Sgonzo if (ACPI_FAILURE(status)) { 567308295Sgonzo device_printf(dev, "failed to read _UID\n"); 568308295Sgonzo return (ENXIO); 569308295Sgonzo } 570308295Sgonzo 571309375Sgonzo BYTGPIO_LOCK_INIT(sc); 572309375Sgonzo 573308295Sgonzo switch (uid) { 574308295Sgonzo case SCORE_UID: 575308295Sgonzo sc->sc_npins = SCORE_PINS; 576308295Sgonzo sc->sc_bank_prefix = SCORE_BANK_PREFIX; 577308295Sgonzo sc->sc_pinpad_map = bytgpio_score_pins; 578308295Sgonzo break; 579308295Sgonzo case NCORE_UID: 580308295Sgonzo sc->sc_npins = NCORE_PINS; 581308295Sgonzo sc->sc_bank_prefix = NCORE_BANK_PREFIX; 582308295Sgonzo sc->sc_pinpad_map = bytgpio_ncore_pins; 583308295Sgonzo break; 584308295Sgonzo case SUS_UID: 585308295Sgonzo sc->sc_npins = SUS_PINS; 586308295Sgonzo sc->sc_bank_prefix = SUS_BANK_PREFIX; 587308295Sgonzo sc->sc_pinpad_map = bytgpio_sus_pins; 588308295Sgonzo break; 589308295Sgonzo default: 590308295Sgonzo device_printf(dev, "invalid _UID value: %d\n", uid); 591309375Sgonzo goto error; 592308295Sgonzo } 593308295Sgonzo 594309375Sgonzo sc->sc_pad_funcs = malloc(sizeof(int)*sc->sc_npins, M_DEVBUF, 595309375Sgonzo M_WAITOK | M_ZERO); 596309375Sgonzo 597308295Sgonzo sc->sc_mem_rid = 0; 598308295Sgonzo sc->sc_mem_res = bus_alloc_resource_any(sc->sc_dev, 599308295Sgonzo SYS_RES_MEMORY, &sc->sc_mem_rid, RF_ACTIVE); 600308295Sgonzo if (sc->sc_mem_res == NULL) { 601308295Sgonzo device_printf(dev, "can't allocate resource\n"); 602308295Sgonzo goto error; 603308295Sgonzo } 604308295Sgonzo 605309375Sgonzo for (pin = 0; pin < sc->sc_npins; pin++) { 606309375Sgonzo reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PCONF0); 607309375Sgonzo val = bytgpio_read_4(sc, reg); 608309375Sgonzo sc->sc_pad_funcs[pin] = val & BYTGPIO_PCONF0_FUNC_MASK; 609309375Sgonzo } 610308295Sgonzo 611308295Sgonzo sc->sc_busdev = gpiobus_attach_bus(dev); 612308295Sgonzo if (sc->sc_busdev == NULL) { 613308295Sgonzo BYTGPIO_LOCK_DESTROY(sc); 614308295Sgonzo bus_release_resource(dev, SYS_RES_MEMORY, 615308295Sgonzo sc->sc_mem_rid, sc->sc_mem_res); 616308295Sgonzo return (ENXIO); 617308295Sgonzo } 618308295Sgonzo 619308295Sgonzo return (0); 620308295Sgonzo 621308295Sgonzoerror: 622309375Sgonzo BYTGPIO_LOCK_DESTROY(sc); 623309375Sgonzo 624308295Sgonzo return (ENXIO); 625308295Sgonzo} 626308295Sgonzo 627309375Sgonzo 628309375Sgonzostatic int 629309375Sgonzobytgpio_detach(device_t dev) 630309375Sgonzo{ 631309375Sgonzo struct bytgpio_softc *sc; 632309375Sgonzo 633309375Sgonzo sc = device_get_softc(dev); 634309375Sgonzo 635309375Sgonzo if (sc->sc_busdev) 636309375Sgonzo gpiobus_detach_bus(dev); 637309375Sgonzo 638309375Sgonzo BYTGPIO_LOCK_DESTROY(sc); 639309375Sgonzo 640309375Sgonzo if (sc->sc_pad_funcs) 641309375Sgonzo free(sc->sc_pad_funcs, M_DEVBUF); 642309375Sgonzo 643309375Sgonzo if (sc->sc_mem_res != NULL) 644309375Sgonzo bus_release_resource(dev, SYS_RES_MEMORY, 645309375Sgonzo sc->sc_mem_rid, sc->sc_mem_res); 646309375Sgonzo 647309375Sgonzo return (0); 648309375Sgonzo} 649309375Sgonzo 650308295Sgonzostatic device_method_t bytgpio_methods[] = { 651308295Sgonzo /* Device interface */ 652308295Sgonzo DEVMETHOD(device_probe, bytgpio_probe), 653308295Sgonzo DEVMETHOD(device_attach, bytgpio_attach), 654309375Sgonzo DEVMETHOD(device_detach, bytgpio_detach), 655308295Sgonzo 656308295Sgonzo /* GPIO protocol */ 657308295Sgonzo DEVMETHOD(gpio_get_bus, bytgpio_get_bus), 658308295Sgonzo DEVMETHOD(gpio_pin_max, bytgpio_pin_max), 659308295Sgonzo DEVMETHOD(gpio_pin_getname, bytgpio_pin_getname), 660308295Sgonzo DEVMETHOD(gpio_pin_getflags, bytgpio_pin_getflags), 661308295Sgonzo DEVMETHOD(gpio_pin_getcaps, bytgpio_pin_getcaps), 662308295Sgonzo DEVMETHOD(gpio_pin_setflags, bytgpio_pin_setflags), 663308295Sgonzo DEVMETHOD(gpio_pin_get, bytgpio_pin_get), 664308295Sgonzo DEVMETHOD(gpio_pin_set, bytgpio_pin_set), 665308295Sgonzo DEVMETHOD(gpio_pin_toggle, bytgpio_pin_toggle), 666308295Sgonzo 667308295Sgonzo DEVMETHOD_END 668308295Sgonzo}; 669308295Sgonzo 670308295Sgonzostatic driver_t bytgpio_driver = { 671308295Sgonzo "gpio", 672308295Sgonzo bytgpio_methods, 673308295Sgonzo sizeof(struct bytgpio_softc), 674308295Sgonzo}; 675308295Sgonzo 676308295Sgonzostatic devclass_t bytgpio_devclass; 677308295SgonzoDRIVER_MODULE(bytgpio, acpi, bytgpio_driver, bytgpio_devclass, 0, 0); 678308295SgonzoMODULE_DEPEND(bytgpio, acpi, 1, 1, 1); 679309375SgonzoMODULE_DEPEND(bytgpio, gpiobus, 1, 1, 1); 680