lpc_gpio.c revision 265858
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: head/sys/arm/lpc/lpc_gpio.c 265858 2014-05-10 21:30:19Z andrew $"); 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 82239278Sgonzo#include <dev/ofw/ofw_bus.h> 83239278Sgonzo#include <dev/ofw/ofw_bus_subr.h> 84239278Sgonzo 85239278Sgonzo#include <arm/lpc/lpcreg.h> 86239278Sgonzo#include <arm/lpc/lpcvar.h> 87239278Sgonzo 88239278Sgonzo#include "gpio_if.h" 89239278Sgonzo 90239278Sgonzostruct lpc_gpio_softc 91239278Sgonzo{ 92239278Sgonzo device_t lg_dev; 93239278Sgonzo struct resource * lg_res; 94239278Sgonzo bus_space_tag_t lg_bst; 95239278Sgonzo bus_space_handle_t lg_bsh; 96239278Sgonzo}; 97239278Sgonzo 98239278Sgonzostruct lpc_gpio_pinmap 99239278Sgonzo{ 100239278Sgonzo int lp_start_idx; 101239278Sgonzo int lp_pin_count; 102239278Sgonzo int lp_port; 103239278Sgonzo int lp_start_bit; 104239278Sgonzo int lp_flags; 105239278Sgonzo}; 106239278Sgonzo 107239278Sgonzostatic const struct lpc_gpio_pinmap lpc_gpio_pins[] = { 108239278Sgonzo { 0, 10, 3, 0, GPIO_PIN_INPUT }, 109239278Sgonzo { 10, 9, 3, 15, GPIO_PIN_INPUT }, 110239278Sgonzo { 19, 1, 3, 25, GPIO_PIN_INPUT }, 111239278Sgonzo { 20, 2, 3, 27, GPIO_PIN_INPUT }, 112239278Sgonzo { 22, 24, 3, 0, GPIO_PIN_OUTPUT }, 113239278Sgonzo /* 114239278Sgonzo * -1 below is to mark special case for Port3 GPIO pins, as they 115239278Sgonzo * have other bits in Port 3 registers as inputs and as outputs 116239278Sgonzo */ 117239278Sgonzo { 46, 6, 3, -1, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT }, 118239278Sgonzo { 52, 13, 2, 0, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT }, 119239278Sgonzo { 65, 24, 1, 0, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT }, 120239278Sgonzo { 89, 8, 0, 0, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT }, 121239278Sgonzo { -1, -1, -1, -1, -1 }, 122239278Sgonzo}; 123239278Sgonzo 124239278Sgonzo#define LPC_GPIO_NPINS \ 125239278Sgonzo (LPC_GPIO_P0_COUNT + LPC_GPIO_P1_COUNT + \ 126239278Sgonzo LPC_GPIO_P2_COUNT + LPC_GPIO_P3_COUNT) 127239278Sgonzo 128239278Sgonzo#define LPC_GPIO_PIN_IDX(_map, _idx) \ 129239278Sgonzo (_idx - _map->lp_start_idx) 130239278Sgonzo 131239278Sgonzo#define LPC_GPIO_PIN_BIT(_map, _idx) \ 132239278Sgonzo (_map->lp_start_bit + LPC_GPIO_PIN_IDX(_map, _idx)) 133239278Sgonzo 134239278Sgonzostatic int lpc_gpio_probe(device_t); 135239278Sgonzostatic int lpc_gpio_attach(device_t); 136239278Sgonzostatic int lpc_gpio_detach(device_t); 137239278Sgonzo 138239278Sgonzostatic int lpc_gpio_pin_max(device_t, int *); 139239278Sgonzostatic int lpc_gpio_pin_getcaps(device_t, uint32_t, uint32_t *); 140239278Sgonzostatic int lpc_gpio_pin_getflags(device_t, uint32_t, uint32_t *); 141239278Sgonzostatic int lpc_gpio_pin_setflags(device_t, uint32_t, uint32_t); 142239278Sgonzostatic int lpc_gpio_pin_getname(device_t, uint32_t, char *); 143239278Sgonzostatic int lpc_gpio_pin_get(device_t, uint32_t, uint32_t *); 144239278Sgonzostatic int lpc_gpio_pin_set(device_t, uint32_t, uint32_t); 145239278Sgonzostatic int lpc_gpio_pin_toggle(device_t, uint32_t); 146239278Sgonzo 147239278Sgonzostatic const struct lpc_gpio_pinmap *lpc_gpio_get_pinmap(int); 148239278Sgonzo 149239278Sgonzostatic struct lpc_gpio_softc *lpc_gpio_sc = NULL; 150239278Sgonzo 151239278Sgonzo#define lpc_gpio_read_4(_sc, _reg) \ 152239278Sgonzo bus_space_read_4(_sc->lg_bst, _sc->lg_bsh, _reg) 153239278Sgonzo#define lpc_gpio_write_4(_sc, _reg, _val) \ 154239278Sgonzo bus_space_write_4(_sc->lg_bst, _sc->lg_bsh, _reg, _val) 155239278Sgonzo#define lpc_gpio_get_4(_sc, _test, _reg1, _reg2) \ 156239278Sgonzo lpc_gpio_read_4(_sc, ((_test) ? _reg1 : _reg2)) 157239278Sgonzo#define lpc_gpio_set_4(_sc, _test, _reg1, _reg2, _val) \ 158239278Sgonzo lpc_gpio_write_4(_sc, ((_test) ? _reg1 : _reg2), _val) 159239278Sgonzo 160239278Sgonzostatic int 161239278Sgonzolpc_gpio_probe(device_t dev) 162239278Sgonzo{ 163261410Sian 164261410Sian if (!ofw_bus_status_okay(dev)) 165261410Sian return (ENXIO); 166261410Sian 167239278Sgonzo if (!ofw_bus_is_compatible(dev, "lpc,gpio")) 168239278Sgonzo return (ENXIO); 169239278Sgonzo 170239278Sgonzo device_set_desc(dev, "LPC32x0 GPIO"); 171239278Sgonzo return (BUS_PROBE_DEFAULT); 172239278Sgonzo} 173239278Sgonzo 174239278Sgonzostatic int 175239278Sgonzolpc_gpio_attach(device_t dev) 176239278Sgonzo{ 177239278Sgonzo struct lpc_gpio_softc *sc = device_get_softc(dev); 178239278Sgonzo int rid; 179239278Sgonzo 180239278Sgonzo sc->lg_dev = dev; 181239278Sgonzo 182239278Sgonzo rid = 0; 183239278Sgonzo sc->lg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 184239278Sgonzo RF_ACTIVE); 185239278Sgonzo if (!sc->lg_res) { 186239278Sgonzo device_printf(dev, "cannot allocate memory window\n"); 187239278Sgonzo return (ENXIO); 188239278Sgonzo } 189239278Sgonzo 190239278Sgonzo sc->lg_bst = rman_get_bustag(sc->lg_res); 191239278Sgonzo sc->lg_bsh = rman_get_bushandle(sc->lg_res); 192239278Sgonzo 193239278Sgonzo lpc_gpio_sc = sc; 194239278Sgonzo 195239278Sgonzo device_add_child(dev, "gpioc", device_get_unit(dev)); 196239278Sgonzo device_add_child(dev, "gpiobus", device_get_unit(dev)); 197239278Sgonzo 198239278Sgonzo return (bus_generic_attach(dev)); 199239278Sgonzo} 200239278Sgonzo 201239278Sgonzostatic int 202239278Sgonzolpc_gpio_detach(device_t dev) 203239278Sgonzo{ 204239278Sgonzo return (EBUSY); 205239278Sgonzo} 206239278Sgonzo 207239278Sgonzostatic int 208239278Sgonzolpc_gpio_pin_max(device_t dev, int *npins) 209239278Sgonzo{ 210239278Sgonzo *npins = LPC_GPIO_NPINS - 1; 211239278Sgonzo return (0); 212239278Sgonzo} 213239278Sgonzo 214239278Sgonzostatic int 215239278Sgonzolpc_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 216239278Sgonzo{ 217239278Sgonzo const struct lpc_gpio_pinmap *map; 218239278Sgonzo 219239278Sgonzo if (pin > LPC_GPIO_NPINS) 220239278Sgonzo return (ENODEV); 221239278Sgonzo 222239278Sgonzo map = lpc_gpio_get_pinmap(pin); 223239278Sgonzo 224239278Sgonzo *caps = map->lp_flags; 225239278Sgonzo return (0); 226239278Sgonzo} 227239278Sgonzo 228239278Sgonzostatic int 229239278Sgonzolpc_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 230239278Sgonzo{ 231239278Sgonzo struct lpc_gpio_softc *sc = device_get_softc(dev); 232239278Sgonzo const struct lpc_gpio_pinmap *map; 233239278Sgonzo uint32_t state; 234239278Sgonzo int dir; 235239278Sgonzo 236239278Sgonzo if (pin > LPC_GPIO_NPINS) 237239278Sgonzo return (ENODEV); 238239278Sgonzo 239239278Sgonzo map = lpc_gpio_get_pinmap(pin); 240239278Sgonzo 241239278Sgonzo /* Check whether it's bidirectional pin */ 242239278Sgonzo if ((map->lp_flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) != 243239278Sgonzo (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) { 244239278Sgonzo *flags = map->lp_flags; 245239278Sgonzo return (0); 246239278Sgonzo } 247239278Sgonzo 248239278Sgonzo switch (map->lp_port) { 249239278Sgonzo case 0: 250239278Sgonzo state = lpc_gpio_read_4(sc, LPC_GPIO_P0_DIR_STATE); 251239278Sgonzo dir = (state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 252239278Sgonzo break; 253239278Sgonzo case 1: 254239278Sgonzo state = lpc_gpio_read_4(sc, LPC_GPIO_P1_DIR_STATE); 255239278Sgonzo dir = (state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 256239278Sgonzo break; 257239278Sgonzo case 2: 258239278Sgonzo state = lpc_gpio_read_4(sc, LPC_GPIO_P2_DIR_STATE); 259239278Sgonzo dir = (state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 260239278Sgonzo break; 261239278Sgonzo case 3: 262239278Sgonzo state = lpc_gpio_read_4(sc, LPC_GPIO_P2_DIR_STATE); 263239278Sgonzo dir = (state & (1 << (25 + LPC_GPIO_PIN_IDX(map, pin)))); 264239278Sgonzo break; 265239278Sgonzo default: 266239278Sgonzo panic("unknown GPIO port"); 267239278Sgonzo } 268239278Sgonzo 269239278Sgonzo *flags = dir ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT; 270239278Sgonzo 271239278Sgonzo return (0); 272239278Sgonzo} 273239278Sgonzo 274239278Sgonzostatic int 275239278Sgonzolpc_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 276239278Sgonzo{ 277239278Sgonzo struct lpc_gpio_softc *sc = device_get_softc(dev); 278239278Sgonzo const struct lpc_gpio_pinmap *map; 279239278Sgonzo uint32_t dir, state; 280239278Sgonzo 281239278Sgonzo if (pin > LPC_GPIO_NPINS) 282239278Sgonzo return (ENODEV); 283239278Sgonzo 284239278Sgonzo map = lpc_gpio_get_pinmap(pin); 285239278Sgonzo 286239278Sgonzo /* Check whether it's bidirectional pin */ 287239278Sgonzo if ((map->lp_flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) != 288239278Sgonzo (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) 289239278Sgonzo return (ENOTSUP); 290239278Sgonzo 291239278Sgonzo if (flags & GPIO_PIN_INPUT) 292239278Sgonzo dir = 0; 293239278Sgonzo 294239278Sgonzo if (flags & GPIO_PIN_OUTPUT) 295239278Sgonzo dir = 1; 296239278Sgonzo 297239278Sgonzo switch (map->lp_port) { 298239278Sgonzo case 0: 299239278Sgonzo state = (1 << LPC_GPIO_PIN_IDX(map, pin)); 300239278Sgonzo lpc_gpio_set_4(sc, dir, LPC_GPIO_P0_DIR_SET, 301239278Sgonzo LPC_GPIO_P0_DIR_CLR, state); 302239278Sgonzo break; 303239278Sgonzo case 1: 304239278Sgonzo state = (1 << LPC_GPIO_PIN_IDX(map, pin)); 305239278Sgonzo lpc_gpio_set_4(sc, dir, LPC_GPIO_P1_DIR_SET, 306239278Sgonzo LPC_GPIO_P0_DIR_CLR, state); 307239278Sgonzo break; 308239278Sgonzo case 2: 309239278Sgonzo state = (1 << LPC_GPIO_PIN_IDX(map, pin)); 310239278Sgonzo lpc_gpio_set_4(sc, dir, LPC_GPIO_P2_DIR_SET, 311239278Sgonzo LPC_GPIO_P0_DIR_CLR, state); 312239278Sgonzo break; 313239278Sgonzo case 3: 314239278Sgonzo state = (1 << (25 + (pin - map->lp_start_idx))); 315239278Sgonzo lpc_gpio_set_4(sc, dir, LPC_GPIO_P2_DIR_SET, 316239278Sgonzo LPC_GPIO_P0_DIR_CLR, state); 317239278Sgonzo break; 318239278Sgonzo } 319239278Sgonzo 320239278Sgonzo return (0); 321239278Sgonzo} 322239278Sgonzo 323239278Sgonzostatic int 324239278Sgonzolpc_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 325239278Sgonzo{ 326239278Sgonzo const struct lpc_gpio_pinmap *map; 327239278Sgonzo int idx; 328239278Sgonzo 329239278Sgonzo map = lpc_gpio_get_pinmap(pin); 330239278Sgonzo idx = LPC_GPIO_PIN_IDX(map, pin); 331239278Sgonzo 332239278Sgonzo switch (map->lp_port) { 333239278Sgonzo case 0: 334239278Sgonzo case 1: 335239278Sgonzo case 2: 336239278Sgonzo snprintf(name, GPIOMAXNAME - 1, "P%d.%d", map->lp_port, 337239278Sgonzo map->lp_start_bit + LPC_GPIO_PIN_IDX(map, pin)); 338239278Sgonzo break; 339239278Sgonzo case 3: 340239278Sgonzo if (map->lp_start_bit == -1) { 341239278Sgonzo snprintf(name, GPIOMAXNAME - 1, "GPIO_%02d", idx); 342239278Sgonzo break; 343239278Sgonzo } 344239278Sgonzo 345239278Sgonzo snprintf(name, GPIOMAXNAME - 1, "GP%c_%02d", 346239278Sgonzo (map->lp_flags & GPIO_PIN_INPUT) ? 'I' : 'O', 347239278Sgonzo map->lp_start_bit + idx); 348239278Sgonzo break; 349239278Sgonzo } 350239278Sgonzo 351239278Sgonzo return (0); 352239278Sgonzo} 353239278Sgonzo 354239278Sgonzostatic int 355239278Sgonzolpc_gpio_pin_get(device_t dev, uint32_t pin, uint32_t *value) 356239278Sgonzo{ 357239278Sgonzo struct lpc_gpio_softc *sc = device_get_softc(dev); 358239278Sgonzo const struct lpc_gpio_pinmap *map; 359239278Sgonzo uint32_t state, flags; 360239278Sgonzo int dir; 361239278Sgonzo 362239278Sgonzo map = lpc_gpio_get_pinmap(pin); 363239278Sgonzo 364239278Sgonzo if (lpc_gpio_pin_getflags(dev, pin, &flags)) 365239278Sgonzo return (ENXIO); 366239278Sgonzo 367239278Sgonzo if (flags & GPIO_PIN_OUTPUT) 368239278Sgonzo dir = 1; 369239278Sgonzo 370239278Sgonzo if (flags & GPIO_PIN_INPUT) 371239278Sgonzo dir = 0; 372239278Sgonzo 373239278Sgonzo switch (map->lp_port) { 374239278Sgonzo case 0: 375239278Sgonzo state = lpc_gpio_get_4(sc, dir, LPC_GPIO_P0_OUTP_STATE, 376239278Sgonzo LPC_GPIO_P0_INP_STATE); 377239278Sgonzo *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 378239278Sgonzo case 1: 379239278Sgonzo state = lpc_gpio_get_4(sc, dir, LPC_GPIO_P1_OUTP_STATE, 380239278Sgonzo LPC_GPIO_P1_INP_STATE); 381239278Sgonzo *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 382239278Sgonzo case 2: 383239278Sgonzo state = lpc_gpio_read_4(sc, LPC_GPIO_P2_INP_STATE); 384239278Sgonzo *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 385239278Sgonzo case 3: 386239278Sgonzo state = lpc_gpio_get_4(sc, dir, LPC_GPIO_P3_OUTP_STATE, 387239278Sgonzo LPC_GPIO_P3_INP_STATE); 388239278Sgonzo if (map->lp_start_bit == -1) { 389239278Sgonzo if (dir) 390239278Sgonzo *value = !!(state & (1 << (25 + 391239278Sgonzo LPC_GPIO_PIN_IDX(map, pin)))); 392239278Sgonzo else 393239278Sgonzo *value = !!(state & (1 << (10 + 394239278Sgonzo LPC_GPIO_PIN_IDX(map, pin)))); 395239278Sgonzo } 396239278Sgonzo 397239278Sgonzo *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 398239278Sgonzo } 399239278Sgonzo 400239278Sgonzo return (0); 401239278Sgonzo} 402239278Sgonzo 403239278Sgonzostatic int 404239278Sgonzolpc_gpio_pin_set(device_t dev, uint32_t pin, uint32_t value) 405239278Sgonzo{ 406239278Sgonzo struct lpc_gpio_softc *sc = device_get_softc(dev); 407239278Sgonzo const struct lpc_gpio_pinmap *map; 408239278Sgonzo uint32_t state, flags; 409239278Sgonzo 410239278Sgonzo map = lpc_gpio_get_pinmap(pin); 411239278Sgonzo 412239278Sgonzo if (lpc_gpio_pin_getflags(dev, pin, &flags)) 413239278Sgonzo return (ENXIO); 414239278Sgonzo 415239278Sgonzo if ((flags & GPIO_PIN_OUTPUT) == 0) 416239278Sgonzo return (EINVAL); 417239278Sgonzo 418239278Sgonzo state = (1 << LPC_GPIO_PIN_BIT(map, pin)); 419239278Sgonzo 420239278Sgonzo switch (map->lp_port) { 421239278Sgonzo case 0: 422239278Sgonzo lpc_gpio_set_4(sc, value, LPC_GPIO_P0_OUTP_SET, 423239278Sgonzo LPC_GPIO_P0_OUTP_CLR, state); 424239278Sgonzo break; 425239278Sgonzo case 1: 426239278Sgonzo lpc_gpio_set_4(sc, value, LPC_GPIO_P1_OUTP_SET, 427239278Sgonzo LPC_GPIO_P1_OUTP_CLR, state); 428239278Sgonzo break; 429239278Sgonzo case 2: 430239278Sgonzo lpc_gpio_set_4(sc, value, LPC_GPIO_P2_OUTP_SET, 431239278Sgonzo LPC_GPIO_P2_OUTP_CLR, state); 432239278Sgonzo break; 433239278Sgonzo case 3: 434239278Sgonzo if (map->lp_start_bit == -1) 435239278Sgonzo state = (1 << (25 + LPC_GPIO_PIN_IDX(map, pin))); 436239278Sgonzo 437239278Sgonzo lpc_gpio_set_4(sc, value, LPC_GPIO_P3_OUTP_SET, 438239278Sgonzo LPC_GPIO_P3_OUTP_CLR, state); 439239278Sgonzo break; 440239278Sgonzo } 441239278Sgonzo 442239278Sgonzo return (0); 443239278Sgonzo} 444239278Sgonzo 445239278Sgonzostatic int 446239278Sgonzolpc_gpio_pin_toggle(device_t dev, uint32_t pin) 447239278Sgonzo{ 448239278Sgonzo const struct lpc_gpio_pinmap *map; 449239278Sgonzo uint32_t flags; 450239278Sgonzo 451239278Sgonzo map = lpc_gpio_get_pinmap(pin); 452239278Sgonzo 453239278Sgonzo if (lpc_gpio_pin_getflags(dev, pin, &flags)) 454239278Sgonzo return (ENXIO); 455239278Sgonzo 456239278Sgonzo if ((flags & GPIO_PIN_OUTPUT) == 0) 457239278Sgonzo return (EINVAL); 458239278Sgonzo 459239278Sgonzo panic("not implemented yet"); 460239278Sgonzo 461239278Sgonzo return (0); 462239278Sgonzo 463239278Sgonzo} 464239278Sgonzo 465239278Sgonzostatic const struct lpc_gpio_pinmap * 466239278Sgonzolpc_gpio_get_pinmap(int pin) 467239278Sgonzo{ 468239278Sgonzo const struct lpc_gpio_pinmap *map; 469239278Sgonzo 470239278Sgonzo for (map = &lpc_gpio_pins[0]; map->lp_start_idx != -1; map++) { 471239278Sgonzo if (pin >= map->lp_start_idx && 472239278Sgonzo pin < map->lp_start_idx + map->lp_pin_count) 473239278Sgonzo return map; 474239278Sgonzo } 475239278Sgonzo 476239278Sgonzo panic("pin number %d out of range", pin); 477239278Sgonzo} 478239278Sgonzo 479239278Sgonzoint 480239278Sgonzolpc_gpio_set_flags(device_t dev, int pin, int flags) 481239278Sgonzo{ 482239278Sgonzo if (lpc_gpio_sc == NULL) 483239278Sgonzo return (ENXIO); 484239278Sgonzo 485239278Sgonzo return lpc_gpio_pin_setflags(lpc_gpio_sc->lg_dev, pin, flags); 486239278Sgonzo} 487239278Sgonzo 488239278Sgonzoint 489239278Sgonzolpc_gpio_set_state(device_t dev, int pin, int state) 490239278Sgonzo{ 491239278Sgonzo if (lpc_gpio_sc == NULL) 492239278Sgonzo return (ENXIO); 493239278Sgonzo 494239278Sgonzo return lpc_gpio_pin_set(lpc_gpio_sc->lg_dev, pin, state); 495239278Sgonzo} 496239278Sgonzo 497239278Sgonzoint 498239278Sgonzolpc_gpio_get_state(device_t dev, int pin, int *state) 499239278Sgonzo{ 500239278Sgonzo if (lpc_gpio_sc == NULL) 501239278Sgonzo return (ENXIO); 502239278Sgonzo 503239278Sgonzo return lpc_gpio_pin_get(lpc_gpio_sc->lg_dev, pin, state); 504239278Sgonzo} 505239278Sgonzo 506239278Sgonzovoid 507265858Sandrewlpc_gpio_init() 508239278Sgonzo{ 509260326Sian bus_space_tag_t bst; 510260326Sian bus_space_handle_t bsh; 511260326Sian 512260326Sian bst = fdtbus_bs_tag; 513260326Sian 514239278Sgonzo /* Preset SPI devices CS pins to one */ 515260326Sian bus_space_map(bst, LPC_GPIO_PHYS_BASE, LPC_GPIO_SIZE, 0, &bsh); 516260326Sian bus_space_write_4(bst, bsh, LPC_GPIO_P3_OUTP_SET, 517239278Sgonzo 1 << (SSD1289_CS_PIN - LPC_GPIO_GPO_00(0)) | 518239278Sgonzo 1 << (SSD1289_DC_PIN - LPC_GPIO_GPO_00(0)) | 519239278Sgonzo 1 << (ADS7846_CS_PIN - LPC_GPIO_GPO_00(0))); 520260326Sian bus_space_unmap(bst, bsh, LPC_GPIO_SIZE); 521239278Sgonzo} 522239278Sgonzo 523239278Sgonzostatic device_method_t lpc_gpio_methods[] = { 524239278Sgonzo /* Device interface */ 525239278Sgonzo DEVMETHOD(device_probe, lpc_gpio_probe), 526239278Sgonzo DEVMETHOD(device_attach, lpc_gpio_attach), 527239278Sgonzo DEVMETHOD(device_detach, lpc_gpio_detach), 528239278Sgonzo 529239278Sgonzo /* GPIO interface */ 530239278Sgonzo DEVMETHOD(gpio_pin_max, lpc_gpio_pin_max), 531239278Sgonzo DEVMETHOD(gpio_pin_getcaps, lpc_gpio_pin_getcaps), 532239278Sgonzo DEVMETHOD(gpio_pin_getflags, lpc_gpio_pin_getflags), 533239278Sgonzo DEVMETHOD(gpio_pin_setflags, lpc_gpio_pin_setflags), 534239278Sgonzo DEVMETHOD(gpio_pin_getname, lpc_gpio_pin_getname), 535239278Sgonzo DEVMETHOD(gpio_pin_set, lpc_gpio_pin_set), 536239278Sgonzo DEVMETHOD(gpio_pin_get, lpc_gpio_pin_get), 537239278Sgonzo DEVMETHOD(gpio_pin_toggle, lpc_gpio_pin_toggle), 538239278Sgonzo 539239278Sgonzo { 0, 0 } 540239278Sgonzo}; 541239278Sgonzo 542239278Sgonzostatic devclass_t lpc_gpio_devclass; 543239278Sgonzo 544239278Sgonzostatic driver_t lpc_gpio_driver = { 545239278Sgonzo "lpcgpio", 546239278Sgonzo lpc_gpio_methods, 547239278Sgonzo sizeof(struct lpc_gpio_softc), 548239278Sgonzo}; 549239278Sgonzo 550239278Sgonzoextern devclass_t gpiobus_devclass, gpioc_devclass; 551239278Sgonzoextern driver_t gpiobus_driver, gpioc_driver; 552239278Sgonzo 553239278SgonzoDRIVER_MODULE(lpcgpio, simplebus, lpc_gpio_driver, lpc_gpio_devclass, 0, 0); 554239278SgonzoDRIVER_MODULE(gpiobus, lpcgpio, gpiobus_driver, gpiobus_devclass, 0, 0); 555239278SgonzoDRIVER_MODULE(gpioc, lpcgpio, gpioc_driver, gpioc_devclass, 0, 0); 556239278SgonzoMODULE_VERSION(lpcgpio, 1); 557