1239278Sgonzo/*- 2239278Sgonzo * Copyright (c) 2011 Jakub Wojciech Klama <jceel@FreeBSD.org> 3239278Sgonzo * All rights reserved. 4239278Sgonzo * 5239278Sgonzo * Redistribution and use in source and binary forms, with or without 6239278Sgonzo * modification, are permitted provided that the following conditions 7239278Sgonzo * are met: 8239278Sgonzo * 1. Redistributions of source code must retain the above copyright 9239278Sgonzo * notice, this list of conditions and the following disclaimer. 10239278Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 11239278Sgonzo * notice, this list of conditions and the following disclaimer in the 12239278Sgonzo * documentation and/or other materials provided with the distribution. 13239278Sgonzo * 14239278Sgonzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15239278Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16239278Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17239278Sgonzo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18239278Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19239278Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20239278Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21239278Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22239278Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23239278Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24239278Sgonzo * SUCH DAMAGE. 25239278Sgonzo * 26239278Sgonzo */ 27239278Sgonzo 28239278Sgonzo/* 29239278Sgonzo * GPIO on LPC32x0 consist of 4 ports: 30239278Sgonzo * - Port0 with 8 input/output pins 31239278Sgonzo * - Port1 with 24 input/output pins 32239278Sgonzo * - Port2 with 13 input/output pins 33239278Sgonzo * - Port3 with: 34239278Sgonzo * - 26 input pins (GPI_00..GPI_09 + GPI_15..GPI_23 + GPI_25 + GPI_27..GPI_28) 35239278Sgonzo * - 24 output pins (GPO_00..GPO_23) 36242692Skevlo * - 6 input/output pins (GPIO_00..GPIO_05) 37239278Sgonzo * 38239278Sgonzo * Pins are mapped to logical pin number as follows: 39239278Sgonzo * [0..9] -> GPI_00..GPI_09 (port 3) 40239278Sgonzo * [10..18] -> GPI_15..GPI_23 (port 3) 41239278Sgonzo * [19] -> GPI_25 (port 3) 42239278Sgonzo * [20..21] -> GPI_27..GPI_28 (port 3) 43239278Sgonzo * [22..45] -> GPO_00..GPO_23 (port 3) 44239278Sgonzo * [46..51] -> GPIO_00..GPIO_05 (port 3) 45239278Sgonzo * [52..64] -> P2.0..P2.12 (port 2) 46239278Sgonzo * [65..88] -> P1.0..P1.23 (port 1) 47239278Sgonzo * [89..96] -> P0.0..P0.7 (port 0) 48239278Sgonzo * 49239278Sgonzo */ 50239278Sgonzo 51239278Sgonzo 52239278Sgonzo#include <sys/cdefs.h> 53239278Sgonzo__FBSDID("$FreeBSD: releng/11.0/sys/arm/lpc/lpc_gpio.c 277996 2015-01-31 19:32:14Z loos $"); 54239278Sgonzo 55239278Sgonzo#include <sys/param.h> 56239278Sgonzo#include <sys/systm.h> 57239278Sgonzo#include <sys/bio.h> 58239278Sgonzo#include <sys/bus.h> 59239278Sgonzo#include <sys/conf.h> 60239278Sgonzo#include <sys/endian.h> 61239278Sgonzo#include <sys/kernel.h> 62239278Sgonzo#include <sys/kthread.h> 63239278Sgonzo#include <sys/lock.h> 64239278Sgonzo#include <sys/malloc.h> 65239278Sgonzo#include <sys/module.h> 66239278Sgonzo#include <sys/mutex.h> 67239278Sgonzo#include <sys/queue.h> 68239278Sgonzo#include <sys/resource.h> 69239278Sgonzo#include <sys/rman.h> 70239278Sgonzo#include <sys/time.h> 71239278Sgonzo#include <sys/timetc.h> 72239278Sgonzo#include <sys/watchdog.h> 73239278Sgonzo#include <sys/gpio.h> 74239278Sgonzo 75239278Sgonzo#include <machine/bus.h> 76239278Sgonzo#include <machine/cpu.h> 77239278Sgonzo#include <machine/cpufunc.h> 78239278Sgonzo#include <machine/resource.h> 79239278Sgonzo#include <machine/intr.h> 80239278Sgonzo#include <machine/fdt.h> 81239278Sgonzo 82277996Sloos#include <dev/gpio/gpiobusvar.h> 83239278Sgonzo#include <dev/ofw/ofw_bus.h> 84239278Sgonzo#include <dev/ofw/ofw_bus_subr.h> 85239278Sgonzo 86239278Sgonzo#include <arm/lpc/lpcreg.h> 87239278Sgonzo#include <arm/lpc/lpcvar.h> 88239278Sgonzo 89239278Sgonzo#include "gpio_if.h" 90239278Sgonzo 91239278Sgonzostruct lpc_gpio_softc 92239278Sgonzo{ 93239278Sgonzo device_t lg_dev; 94277996Sloos device_t lg_busdev; 95239278Sgonzo struct resource * lg_res; 96239278Sgonzo bus_space_tag_t lg_bst; 97239278Sgonzo bus_space_handle_t lg_bsh; 98239278Sgonzo}; 99239278Sgonzo 100239278Sgonzostruct lpc_gpio_pinmap 101239278Sgonzo{ 102239278Sgonzo int lp_start_idx; 103239278Sgonzo int lp_pin_count; 104239278Sgonzo int lp_port; 105239278Sgonzo int lp_start_bit; 106239278Sgonzo int lp_flags; 107239278Sgonzo}; 108239278Sgonzo 109239278Sgonzostatic const struct lpc_gpio_pinmap lpc_gpio_pins[] = { 110239278Sgonzo { 0, 10, 3, 0, GPIO_PIN_INPUT }, 111239278Sgonzo { 10, 9, 3, 15, GPIO_PIN_INPUT }, 112239278Sgonzo { 19, 1, 3, 25, GPIO_PIN_INPUT }, 113239278Sgonzo { 20, 2, 3, 27, GPIO_PIN_INPUT }, 114239278Sgonzo { 22, 24, 3, 0, GPIO_PIN_OUTPUT }, 115239278Sgonzo /* 116239278Sgonzo * -1 below is to mark special case for Port3 GPIO pins, as they 117239278Sgonzo * have other bits in Port 3 registers as inputs and as outputs 118239278Sgonzo */ 119239278Sgonzo { 46, 6, 3, -1, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT }, 120239278Sgonzo { 52, 13, 2, 0, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT }, 121239278Sgonzo { 65, 24, 1, 0, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT }, 122239278Sgonzo { 89, 8, 0, 0, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT }, 123239278Sgonzo { -1, -1, -1, -1, -1 }, 124239278Sgonzo}; 125239278Sgonzo 126239278Sgonzo#define LPC_GPIO_NPINS \ 127239278Sgonzo (LPC_GPIO_P0_COUNT + LPC_GPIO_P1_COUNT + \ 128239278Sgonzo LPC_GPIO_P2_COUNT + LPC_GPIO_P3_COUNT) 129239278Sgonzo 130239278Sgonzo#define LPC_GPIO_PIN_IDX(_map, _idx) \ 131239278Sgonzo (_idx - _map->lp_start_idx) 132239278Sgonzo 133239278Sgonzo#define LPC_GPIO_PIN_BIT(_map, _idx) \ 134239278Sgonzo (_map->lp_start_bit + LPC_GPIO_PIN_IDX(_map, _idx)) 135239278Sgonzo 136239278Sgonzostatic int lpc_gpio_probe(device_t); 137239278Sgonzostatic int lpc_gpio_attach(device_t); 138239278Sgonzostatic int lpc_gpio_detach(device_t); 139239278Sgonzo 140277996Sloosstatic device_t lpc_gpio_get_bus(device_t); 141239278Sgonzostatic int lpc_gpio_pin_max(device_t, int *); 142239278Sgonzostatic int lpc_gpio_pin_getcaps(device_t, uint32_t, uint32_t *); 143239278Sgonzostatic int lpc_gpio_pin_getflags(device_t, uint32_t, uint32_t *); 144239278Sgonzostatic int lpc_gpio_pin_setflags(device_t, uint32_t, uint32_t); 145239278Sgonzostatic int lpc_gpio_pin_getname(device_t, uint32_t, char *); 146239278Sgonzostatic int lpc_gpio_pin_get(device_t, uint32_t, uint32_t *); 147239278Sgonzostatic int lpc_gpio_pin_set(device_t, uint32_t, uint32_t); 148239278Sgonzostatic int lpc_gpio_pin_toggle(device_t, uint32_t); 149239278Sgonzo 150239278Sgonzostatic const struct lpc_gpio_pinmap *lpc_gpio_get_pinmap(int); 151239278Sgonzo 152239278Sgonzostatic struct lpc_gpio_softc *lpc_gpio_sc = NULL; 153239278Sgonzo 154239278Sgonzo#define lpc_gpio_read_4(_sc, _reg) \ 155239278Sgonzo bus_space_read_4(_sc->lg_bst, _sc->lg_bsh, _reg) 156239278Sgonzo#define lpc_gpio_write_4(_sc, _reg, _val) \ 157239278Sgonzo bus_space_write_4(_sc->lg_bst, _sc->lg_bsh, _reg, _val) 158239278Sgonzo#define lpc_gpio_get_4(_sc, _test, _reg1, _reg2) \ 159239278Sgonzo lpc_gpio_read_4(_sc, ((_test) ? _reg1 : _reg2)) 160239278Sgonzo#define lpc_gpio_set_4(_sc, _test, _reg1, _reg2, _val) \ 161239278Sgonzo lpc_gpio_write_4(_sc, ((_test) ? _reg1 : _reg2), _val) 162239278Sgonzo 163239278Sgonzostatic int 164239278Sgonzolpc_gpio_probe(device_t dev) 165239278Sgonzo{ 166261410Sian 167261410Sian if (!ofw_bus_status_okay(dev)) 168261410Sian return (ENXIO); 169261410Sian 170239278Sgonzo if (!ofw_bus_is_compatible(dev, "lpc,gpio")) 171239278Sgonzo return (ENXIO); 172239278Sgonzo 173239278Sgonzo device_set_desc(dev, "LPC32x0 GPIO"); 174239278Sgonzo return (BUS_PROBE_DEFAULT); 175239278Sgonzo} 176239278Sgonzo 177239278Sgonzostatic int 178239278Sgonzolpc_gpio_attach(device_t dev) 179239278Sgonzo{ 180239278Sgonzo struct lpc_gpio_softc *sc = device_get_softc(dev); 181239278Sgonzo int rid; 182239278Sgonzo 183239278Sgonzo sc->lg_dev = dev; 184239278Sgonzo 185239278Sgonzo rid = 0; 186239278Sgonzo sc->lg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 187239278Sgonzo RF_ACTIVE); 188239278Sgonzo if (!sc->lg_res) { 189239278Sgonzo device_printf(dev, "cannot allocate memory window\n"); 190239278Sgonzo return (ENXIO); 191239278Sgonzo } 192239278Sgonzo 193239278Sgonzo sc->lg_bst = rman_get_bustag(sc->lg_res); 194239278Sgonzo sc->lg_bsh = rman_get_bushandle(sc->lg_res); 195239278Sgonzo 196239278Sgonzo lpc_gpio_sc = sc; 197239278Sgonzo 198277996Sloos sc->lg_busdev = gpiobus_attach_bus(dev); 199277996Sloos if (sc->lg_busdev == NULL) { 200277996Sloos bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->lg_res); 201277996Sloos return (ENXIO); 202277996Sloos } 203239278Sgonzo 204277996Sloos return (0); 205239278Sgonzo} 206239278Sgonzo 207239278Sgonzostatic int 208239278Sgonzolpc_gpio_detach(device_t dev) 209239278Sgonzo{ 210239278Sgonzo return (EBUSY); 211239278Sgonzo} 212239278Sgonzo 213277996Sloosstatic device_t 214277996Slooslpc_gpio_get_bus(device_t dev) 215277996Sloos{ 216277996Sloos struct lpc_gpio_softc *sc; 217277996Sloos 218277996Sloos sc = device_get_softc(dev); 219277996Sloos 220277996Sloos return (sc->lg_busdev); 221277996Sloos} 222277996Sloos 223239278Sgonzostatic int 224239278Sgonzolpc_gpio_pin_max(device_t dev, int *npins) 225239278Sgonzo{ 226239278Sgonzo *npins = LPC_GPIO_NPINS - 1; 227239278Sgonzo return (0); 228239278Sgonzo} 229239278Sgonzo 230239278Sgonzostatic int 231239278Sgonzolpc_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 232239278Sgonzo{ 233239278Sgonzo const struct lpc_gpio_pinmap *map; 234239278Sgonzo 235239278Sgonzo if (pin > LPC_GPIO_NPINS) 236239278Sgonzo return (ENODEV); 237239278Sgonzo 238239278Sgonzo map = lpc_gpio_get_pinmap(pin); 239239278Sgonzo 240239278Sgonzo *caps = map->lp_flags; 241239278Sgonzo return (0); 242239278Sgonzo} 243239278Sgonzo 244239278Sgonzostatic int 245239278Sgonzolpc_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 246239278Sgonzo{ 247239278Sgonzo struct lpc_gpio_softc *sc = device_get_softc(dev); 248239278Sgonzo const struct lpc_gpio_pinmap *map; 249239278Sgonzo uint32_t state; 250239278Sgonzo int dir; 251239278Sgonzo 252239278Sgonzo if (pin > LPC_GPIO_NPINS) 253239278Sgonzo return (ENODEV); 254239278Sgonzo 255239278Sgonzo map = lpc_gpio_get_pinmap(pin); 256239278Sgonzo 257239278Sgonzo /* Check whether it's bidirectional pin */ 258239278Sgonzo if ((map->lp_flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) != 259239278Sgonzo (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) { 260239278Sgonzo *flags = map->lp_flags; 261239278Sgonzo return (0); 262239278Sgonzo } 263239278Sgonzo 264239278Sgonzo switch (map->lp_port) { 265239278Sgonzo case 0: 266239278Sgonzo state = lpc_gpio_read_4(sc, LPC_GPIO_P0_DIR_STATE); 267239278Sgonzo dir = (state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 268239278Sgonzo break; 269239278Sgonzo case 1: 270239278Sgonzo state = lpc_gpio_read_4(sc, LPC_GPIO_P1_DIR_STATE); 271239278Sgonzo dir = (state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 272239278Sgonzo break; 273239278Sgonzo case 2: 274239278Sgonzo state = lpc_gpio_read_4(sc, LPC_GPIO_P2_DIR_STATE); 275239278Sgonzo dir = (state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 276239278Sgonzo break; 277239278Sgonzo case 3: 278239278Sgonzo state = lpc_gpio_read_4(sc, LPC_GPIO_P2_DIR_STATE); 279239278Sgonzo dir = (state & (1 << (25 + LPC_GPIO_PIN_IDX(map, pin)))); 280239278Sgonzo break; 281239278Sgonzo default: 282239278Sgonzo panic("unknown GPIO port"); 283239278Sgonzo } 284239278Sgonzo 285239278Sgonzo *flags = dir ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT; 286239278Sgonzo 287239278Sgonzo return (0); 288239278Sgonzo} 289239278Sgonzo 290239278Sgonzostatic int 291239278Sgonzolpc_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 292239278Sgonzo{ 293239278Sgonzo struct lpc_gpio_softc *sc = device_get_softc(dev); 294239278Sgonzo const struct lpc_gpio_pinmap *map; 295239278Sgonzo uint32_t dir, state; 296239278Sgonzo 297239278Sgonzo if (pin > LPC_GPIO_NPINS) 298239278Sgonzo return (ENODEV); 299239278Sgonzo 300239278Sgonzo map = lpc_gpio_get_pinmap(pin); 301239278Sgonzo 302239278Sgonzo /* Check whether it's bidirectional pin */ 303239278Sgonzo if ((map->lp_flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) != 304239278Sgonzo (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) 305239278Sgonzo return (ENOTSUP); 306239278Sgonzo 307239278Sgonzo if (flags & GPIO_PIN_INPUT) 308239278Sgonzo dir = 0; 309239278Sgonzo 310239278Sgonzo if (flags & GPIO_PIN_OUTPUT) 311239278Sgonzo dir = 1; 312239278Sgonzo 313239278Sgonzo switch (map->lp_port) { 314239278Sgonzo case 0: 315239278Sgonzo state = (1 << LPC_GPIO_PIN_IDX(map, pin)); 316239278Sgonzo lpc_gpio_set_4(sc, dir, LPC_GPIO_P0_DIR_SET, 317239278Sgonzo LPC_GPIO_P0_DIR_CLR, state); 318239278Sgonzo break; 319239278Sgonzo case 1: 320239278Sgonzo state = (1 << LPC_GPIO_PIN_IDX(map, pin)); 321239278Sgonzo lpc_gpio_set_4(sc, dir, LPC_GPIO_P1_DIR_SET, 322239278Sgonzo LPC_GPIO_P0_DIR_CLR, state); 323239278Sgonzo break; 324239278Sgonzo case 2: 325239278Sgonzo state = (1 << LPC_GPIO_PIN_IDX(map, pin)); 326239278Sgonzo lpc_gpio_set_4(sc, dir, LPC_GPIO_P2_DIR_SET, 327239278Sgonzo LPC_GPIO_P0_DIR_CLR, state); 328239278Sgonzo break; 329239278Sgonzo case 3: 330239278Sgonzo state = (1 << (25 + (pin - map->lp_start_idx))); 331239278Sgonzo lpc_gpio_set_4(sc, dir, LPC_GPIO_P2_DIR_SET, 332239278Sgonzo LPC_GPIO_P0_DIR_CLR, state); 333239278Sgonzo break; 334239278Sgonzo } 335239278Sgonzo 336239278Sgonzo return (0); 337239278Sgonzo} 338239278Sgonzo 339239278Sgonzostatic int 340239278Sgonzolpc_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 341239278Sgonzo{ 342239278Sgonzo const struct lpc_gpio_pinmap *map; 343239278Sgonzo int idx; 344239278Sgonzo 345239278Sgonzo map = lpc_gpio_get_pinmap(pin); 346239278Sgonzo idx = LPC_GPIO_PIN_IDX(map, pin); 347239278Sgonzo 348239278Sgonzo switch (map->lp_port) { 349239278Sgonzo case 0: 350239278Sgonzo case 1: 351239278Sgonzo case 2: 352239278Sgonzo snprintf(name, GPIOMAXNAME - 1, "P%d.%d", map->lp_port, 353239278Sgonzo map->lp_start_bit + LPC_GPIO_PIN_IDX(map, pin)); 354239278Sgonzo break; 355239278Sgonzo case 3: 356239278Sgonzo if (map->lp_start_bit == -1) { 357239278Sgonzo snprintf(name, GPIOMAXNAME - 1, "GPIO_%02d", idx); 358239278Sgonzo break; 359239278Sgonzo } 360239278Sgonzo 361239278Sgonzo snprintf(name, GPIOMAXNAME - 1, "GP%c_%02d", 362239278Sgonzo (map->lp_flags & GPIO_PIN_INPUT) ? 'I' : 'O', 363239278Sgonzo map->lp_start_bit + idx); 364239278Sgonzo break; 365239278Sgonzo } 366239278Sgonzo 367239278Sgonzo return (0); 368239278Sgonzo} 369239278Sgonzo 370239278Sgonzostatic int 371239278Sgonzolpc_gpio_pin_get(device_t dev, uint32_t pin, uint32_t *value) 372239278Sgonzo{ 373239278Sgonzo struct lpc_gpio_softc *sc = device_get_softc(dev); 374239278Sgonzo const struct lpc_gpio_pinmap *map; 375239278Sgonzo uint32_t state, flags; 376239278Sgonzo int dir; 377239278Sgonzo 378239278Sgonzo map = lpc_gpio_get_pinmap(pin); 379239278Sgonzo 380239278Sgonzo if (lpc_gpio_pin_getflags(dev, pin, &flags)) 381239278Sgonzo return (ENXIO); 382239278Sgonzo 383239278Sgonzo if (flags & GPIO_PIN_OUTPUT) 384239278Sgonzo dir = 1; 385239278Sgonzo 386239278Sgonzo if (flags & GPIO_PIN_INPUT) 387239278Sgonzo dir = 0; 388239278Sgonzo 389239278Sgonzo switch (map->lp_port) { 390239278Sgonzo case 0: 391239278Sgonzo state = lpc_gpio_get_4(sc, dir, LPC_GPIO_P0_OUTP_STATE, 392239278Sgonzo LPC_GPIO_P0_INP_STATE); 393239278Sgonzo *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 394239278Sgonzo case 1: 395239278Sgonzo state = lpc_gpio_get_4(sc, dir, LPC_GPIO_P1_OUTP_STATE, 396239278Sgonzo LPC_GPIO_P1_INP_STATE); 397239278Sgonzo *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 398239278Sgonzo case 2: 399239278Sgonzo state = lpc_gpio_read_4(sc, LPC_GPIO_P2_INP_STATE); 400239278Sgonzo *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 401239278Sgonzo case 3: 402239278Sgonzo state = lpc_gpio_get_4(sc, dir, LPC_GPIO_P3_OUTP_STATE, 403239278Sgonzo LPC_GPIO_P3_INP_STATE); 404239278Sgonzo if (map->lp_start_bit == -1) { 405239278Sgonzo if (dir) 406239278Sgonzo *value = !!(state & (1 << (25 + 407239278Sgonzo LPC_GPIO_PIN_IDX(map, pin)))); 408239278Sgonzo else 409239278Sgonzo *value = !!(state & (1 << (10 + 410239278Sgonzo LPC_GPIO_PIN_IDX(map, pin)))); 411239278Sgonzo } 412239278Sgonzo 413239278Sgonzo *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 414239278Sgonzo } 415239278Sgonzo 416239278Sgonzo return (0); 417239278Sgonzo} 418239278Sgonzo 419239278Sgonzostatic int 420239278Sgonzolpc_gpio_pin_set(device_t dev, uint32_t pin, uint32_t value) 421239278Sgonzo{ 422239278Sgonzo struct lpc_gpio_softc *sc = device_get_softc(dev); 423239278Sgonzo const struct lpc_gpio_pinmap *map; 424239278Sgonzo uint32_t state, flags; 425239278Sgonzo 426239278Sgonzo map = lpc_gpio_get_pinmap(pin); 427239278Sgonzo 428239278Sgonzo if (lpc_gpio_pin_getflags(dev, pin, &flags)) 429239278Sgonzo return (ENXIO); 430239278Sgonzo 431239278Sgonzo if ((flags & GPIO_PIN_OUTPUT) == 0) 432239278Sgonzo return (EINVAL); 433239278Sgonzo 434239278Sgonzo state = (1 << LPC_GPIO_PIN_BIT(map, pin)); 435239278Sgonzo 436239278Sgonzo switch (map->lp_port) { 437239278Sgonzo case 0: 438239278Sgonzo lpc_gpio_set_4(sc, value, LPC_GPIO_P0_OUTP_SET, 439239278Sgonzo LPC_GPIO_P0_OUTP_CLR, state); 440239278Sgonzo break; 441239278Sgonzo case 1: 442239278Sgonzo lpc_gpio_set_4(sc, value, LPC_GPIO_P1_OUTP_SET, 443239278Sgonzo LPC_GPIO_P1_OUTP_CLR, state); 444239278Sgonzo break; 445239278Sgonzo case 2: 446239278Sgonzo lpc_gpio_set_4(sc, value, LPC_GPIO_P2_OUTP_SET, 447239278Sgonzo LPC_GPIO_P2_OUTP_CLR, state); 448239278Sgonzo break; 449239278Sgonzo case 3: 450239278Sgonzo if (map->lp_start_bit == -1) 451239278Sgonzo state = (1 << (25 + LPC_GPIO_PIN_IDX(map, pin))); 452239278Sgonzo 453239278Sgonzo lpc_gpio_set_4(sc, value, LPC_GPIO_P3_OUTP_SET, 454239278Sgonzo LPC_GPIO_P3_OUTP_CLR, state); 455239278Sgonzo break; 456239278Sgonzo } 457239278Sgonzo 458239278Sgonzo return (0); 459239278Sgonzo} 460239278Sgonzo 461239278Sgonzostatic int 462239278Sgonzolpc_gpio_pin_toggle(device_t dev, uint32_t pin) 463239278Sgonzo{ 464239278Sgonzo const struct lpc_gpio_pinmap *map; 465239278Sgonzo uint32_t flags; 466239278Sgonzo 467239278Sgonzo map = lpc_gpio_get_pinmap(pin); 468239278Sgonzo 469239278Sgonzo if (lpc_gpio_pin_getflags(dev, pin, &flags)) 470239278Sgonzo return (ENXIO); 471239278Sgonzo 472239278Sgonzo if ((flags & GPIO_PIN_OUTPUT) == 0) 473239278Sgonzo return (EINVAL); 474239278Sgonzo 475239278Sgonzo panic("not implemented yet"); 476239278Sgonzo 477239278Sgonzo return (0); 478239278Sgonzo 479239278Sgonzo} 480239278Sgonzo 481239278Sgonzostatic const struct lpc_gpio_pinmap * 482239278Sgonzolpc_gpio_get_pinmap(int pin) 483239278Sgonzo{ 484239278Sgonzo const struct lpc_gpio_pinmap *map; 485239278Sgonzo 486239278Sgonzo for (map = &lpc_gpio_pins[0]; map->lp_start_idx != -1; map++) { 487239278Sgonzo if (pin >= map->lp_start_idx && 488239278Sgonzo pin < map->lp_start_idx + map->lp_pin_count) 489239278Sgonzo return map; 490239278Sgonzo } 491239278Sgonzo 492239278Sgonzo panic("pin number %d out of range", pin); 493239278Sgonzo} 494239278Sgonzo 495239278Sgonzoint 496239278Sgonzolpc_gpio_set_flags(device_t dev, int pin, int flags) 497239278Sgonzo{ 498239278Sgonzo if (lpc_gpio_sc == NULL) 499239278Sgonzo return (ENXIO); 500239278Sgonzo 501239278Sgonzo return lpc_gpio_pin_setflags(lpc_gpio_sc->lg_dev, pin, flags); 502239278Sgonzo} 503239278Sgonzo 504239278Sgonzoint 505239278Sgonzolpc_gpio_set_state(device_t dev, int pin, int state) 506239278Sgonzo{ 507239278Sgonzo if (lpc_gpio_sc == NULL) 508239278Sgonzo return (ENXIO); 509239278Sgonzo 510239278Sgonzo return lpc_gpio_pin_set(lpc_gpio_sc->lg_dev, pin, state); 511239278Sgonzo} 512239278Sgonzo 513239278Sgonzoint 514239278Sgonzolpc_gpio_get_state(device_t dev, int pin, int *state) 515239278Sgonzo{ 516239278Sgonzo if (lpc_gpio_sc == NULL) 517239278Sgonzo return (ENXIO); 518239278Sgonzo 519239278Sgonzo return lpc_gpio_pin_get(lpc_gpio_sc->lg_dev, pin, state); 520239278Sgonzo} 521239278Sgonzo 522239278Sgonzovoid 523265858Sandrewlpc_gpio_init() 524239278Sgonzo{ 525260326Sian bus_space_tag_t bst; 526260326Sian bus_space_handle_t bsh; 527260326Sian 528260326Sian bst = fdtbus_bs_tag; 529260326Sian 530239278Sgonzo /* Preset SPI devices CS pins to one */ 531260326Sian bus_space_map(bst, LPC_GPIO_PHYS_BASE, LPC_GPIO_SIZE, 0, &bsh); 532260326Sian bus_space_write_4(bst, bsh, LPC_GPIO_P3_OUTP_SET, 533239278Sgonzo 1 << (SSD1289_CS_PIN - LPC_GPIO_GPO_00(0)) | 534239278Sgonzo 1 << (SSD1289_DC_PIN - LPC_GPIO_GPO_00(0)) | 535239278Sgonzo 1 << (ADS7846_CS_PIN - LPC_GPIO_GPO_00(0))); 536260326Sian bus_space_unmap(bst, bsh, LPC_GPIO_SIZE); 537239278Sgonzo} 538239278Sgonzo 539239278Sgonzostatic device_method_t lpc_gpio_methods[] = { 540239278Sgonzo /* Device interface */ 541239278Sgonzo DEVMETHOD(device_probe, lpc_gpio_probe), 542239278Sgonzo DEVMETHOD(device_attach, lpc_gpio_attach), 543239278Sgonzo DEVMETHOD(device_detach, lpc_gpio_detach), 544239278Sgonzo 545239278Sgonzo /* GPIO interface */ 546277996Sloos DEVMETHOD(gpio_get_bus, lpc_gpio_get_bus), 547239278Sgonzo DEVMETHOD(gpio_pin_max, lpc_gpio_pin_max), 548239278Sgonzo DEVMETHOD(gpio_pin_getcaps, lpc_gpio_pin_getcaps), 549239278Sgonzo DEVMETHOD(gpio_pin_getflags, lpc_gpio_pin_getflags), 550239278Sgonzo DEVMETHOD(gpio_pin_setflags, lpc_gpio_pin_setflags), 551239278Sgonzo DEVMETHOD(gpio_pin_getname, lpc_gpio_pin_getname), 552239278Sgonzo DEVMETHOD(gpio_pin_set, lpc_gpio_pin_set), 553239278Sgonzo DEVMETHOD(gpio_pin_get, lpc_gpio_pin_get), 554239278Sgonzo DEVMETHOD(gpio_pin_toggle, lpc_gpio_pin_toggle), 555239278Sgonzo 556239278Sgonzo { 0, 0 } 557239278Sgonzo}; 558239278Sgonzo 559239278Sgonzostatic devclass_t lpc_gpio_devclass; 560239278Sgonzo 561239278Sgonzostatic driver_t lpc_gpio_driver = { 562239278Sgonzo "lpcgpio", 563239278Sgonzo lpc_gpio_methods, 564239278Sgonzo sizeof(struct lpc_gpio_softc), 565239278Sgonzo}; 566239278Sgonzo 567239278Sgonzoextern devclass_t gpiobus_devclass, gpioc_devclass; 568239278Sgonzoextern driver_t gpiobus_driver, gpioc_driver; 569239278Sgonzo 570239278SgonzoDRIVER_MODULE(lpcgpio, simplebus, lpc_gpio_driver, lpc_gpio_devclass, 0, 0); 571239278SgonzoDRIVER_MODULE(gpiobus, lpcgpio, gpiobus_driver, gpiobus_devclass, 0, 0); 572239278SgonzoDRIVER_MODULE(gpioc, lpcgpio, gpioc_driver, gpioc_devclass, 0, 0); 573239278SgonzoMODULE_VERSION(lpcgpio, 1); 574