lpc_gpio.c revision 260326
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 260326 2014-01-05 18:40:06Z ian $"); 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{ 163239278Sgonzo if (!ofw_bus_is_compatible(dev, "lpc,gpio")) 164239278Sgonzo return (ENXIO); 165239278Sgonzo 166239278Sgonzo device_set_desc(dev, "LPC32x0 GPIO"); 167239278Sgonzo return (BUS_PROBE_DEFAULT); 168239278Sgonzo} 169239278Sgonzo 170239278Sgonzostatic int 171239278Sgonzolpc_gpio_attach(device_t dev) 172239278Sgonzo{ 173239278Sgonzo struct lpc_gpio_softc *sc = device_get_softc(dev); 174239278Sgonzo int rid; 175239278Sgonzo 176239278Sgonzo sc->lg_dev = dev; 177239278Sgonzo 178239278Sgonzo rid = 0; 179239278Sgonzo sc->lg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 180239278Sgonzo RF_ACTIVE); 181239278Sgonzo if (!sc->lg_res) { 182239278Sgonzo device_printf(dev, "cannot allocate memory window\n"); 183239278Sgonzo return (ENXIO); 184239278Sgonzo } 185239278Sgonzo 186239278Sgonzo sc->lg_bst = rman_get_bustag(sc->lg_res); 187239278Sgonzo sc->lg_bsh = rman_get_bushandle(sc->lg_res); 188239278Sgonzo 189239278Sgonzo lpc_gpio_sc = sc; 190239278Sgonzo 191239278Sgonzo device_add_child(dev, "gpioc", device_get_unit(dev)); 192239278Sgonzo device_add_child(dev, "gpiobus", device_get_unit(dev)); 193239278Sgonzo 194239278Sgonzo return (bus_generic_attach(dev)); 195239278Sgonzo} 196239278Sgonzo 197239278Sgonzostatic int 198239278Sgonzolpc_gpio_detach(device_t dev) 199239278Sgonzo{ 200239278Sgonzo return (EBUSY); 201239278Sgonzo} 202239278Sgonzo 203239278Sgonzostatic int 204239278Sgonzolpc_gpio_pin_max(device_t dev, int *npins) 205239278Sgonzo{ 206239278Sgonzo *npins = LPC_GPIO_NPINS - 1; 207239278Sgonzo return (0); 208239278Sgonzo} 209239278Sgonzo 210239278Sgonzostatic int 211239278Sgonzolpc_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 212239278Sgonzo{ 213239278Sgonzo const struct lpc_gpio_pinmap *map; 214239278Sgonzo 215239278Sgonzo if (pin > LPC_GPIO_NPINS) 216239278Sgonzo return (ENODEV); 217239278Sgonzo 218239278Sgonzo map = lpc_gpio_get_pinmap(pin); 219239278Sgonzo 220239278Sgonzo *caps = map->lp_flags; 221239278Sgonzo return (0); 222239278Sgonzo} 223239278Sgonzo 224239278Sgonzostatic int 225239278Sgonzolpc_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 226239278Sgonzo{ 227239278Sgonzo struct lpc_gpio_softc *sc = device_get_softc(dev); 228239278Sgonzo const struct lpc_gpio_pinmap *map; 229239278Sgonzo uint32_t state; 230239278Sgonzo int dir; 231239278Sgonzo 232239278Sgonzo if (pin > LPC_GPIO_NPINS) 233239278Sgonzo return (ENODEV); 234239278Sgonzo 235239278Sgonzo map = lpc_gpio_get_pinmap(pin); 236239278Sgonzo 237239278Sgonzo /* Check whether it's bidirectional pin */ 238239278Sgonzo if ((map->lp_flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) != 239239278Sgonzo (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) { 240239278Sgonzo *flags = map->lp_flags; 241239278Sgonzo return (0); 242239278Sgonzo } 243239278Sgonzo 244239278Sgonzo switch (map->lp_port) { 245239278Sgonzo case 0: 246239278Sgonzo state = lpc_gpio_read_4(sc, LPC_GPIO_P0_DIR_STATE); 247239278Sgonzo dir = (state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 248239278Sgonzo break; 249239278Sgonzo case 1: 250239278Sgonzo state = lpc_gpio_read_4(sc, LPC_GPIO_P1_DIR_STATE); 251239278Sgonzo dir = (state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 252239278Sgonzo break; 253239278Sgonzo case 2: 254239278Sgonzo state = lpc_gpio_read_4(sc, LPC_GPIO_P2_DIR_STATE); 255239278Sgonzo dir = (state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 256239278Sgonzo break; 257239278Sgonzo case 3: 258239278Sgonzo state = lpc_gpio_read_4(sc, LPC_GPIO_P2_DIR_STATE); 259239278Sgonzo dir = (state & (1 << (25 + LPC_GPIO_PIN_IDX(map, pin)))); 260239278Sgonzo break; 261239278Sgonzo default: 262239278Sgonzo panic("unknown GPIO port"); 263239278Sgonzo } 264239278Sgonzo 265239278Sgonzo *flags = dir ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT; 266239278Sgonzo 267239278Sgonzo return (0); 268239278Sgonzo} 269239278Sgonzo 270239278Sgonzostatic int 271239278Sgonzolpc_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 272239278Sgonzo{ 273239278Sgonzo struct lpc_gpio_softc *sc = device_get_softc(dev); 274239278Sgonzo const struct lpc_gpio_pinmap *map; 275239278Sgonzo uint32_t dir, state; 276239278Sgonzo 277239278Sgonzo if (pin > LPC_GPIO_NPINS) 278239278Sgonzo return (ENODEV); 279239278Sgonzo 280239278Sgonzo map = lpc_gpio_get_pinmap(pin); 281239278Sgonzo 282239278Sgonzo /* Check whether it's bidirectional pin */ 283239278Sgonzo if ((map->lp_flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) != 284239278Sgonzo (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) 285239278Sgonzo return (ENOTSUP); 286239278Sgonzo 287239278Sgonzo if (flags & GPIO_PIN_INPUT) 288239278Sgonzo dir = 0; 289239278Sgonzo 290239278Sgonzo if (flags & GPIO_PIN_OUTPUT) 291239278Sgonzo dir = 1; 292239278Sgonzo 293239278Sgonzo switch (map->lp_port) { 294239278Sgonzo case 0: 295239278Sgonzo state = (1 << LPC_GPIO_PIN_IDX(map, pin)); 296239278Sgonzo lpc_gpio_set_4(sc, dir, LPC_GPIO_P0_DIR_SET, 297239278Sgonzo LPC_GPIO_P0_DIR_CLR, state); 298239278Sgonzo break; 299239278Sgonzo case 1: 300239278Sgonzo state = (1 << LPC_GPIO_PIN_IDX(map, pin)); 301239278Sgonzo lpc_gpio_set_4(sc, dir, LPC_GPIO_P1_DIR_SET, 302239278Sgonzo LPC_GPIO_P0_DIR_CLR, state); 303239278Sgonzo break; 304239278Sgonzo case 2: 305239278Sgonzo state = (1 << LPC_GPIO_PIN_IDX(map, pin)); 306239278Sgonzo lpc_gpio_set_4(sc, dir, LPC_GPIO_P2_DIR_SET, 307239278Sgonzo LPC_GPIO_P0_DIR_CLR, state); 308239278Sgonzo break; 309239278Sgonzo case 3: 310239278Sgonzo state = (1 << (25 + (pin - map->lp_start_idx))); 311239278Sgonzo lpc_gpio_set_4(sc, dir, LPC_GPIO_P2_DIR_SET, 312239278Sgonzo LPC_GPIO_P0_DIR_CLR, state); 313239278Sgonzo break; 314239278Sgonzo } 315239278Sgonzo 316239278Sgonzo return (0); 317239278Sgonzo} 318239278Sgonzo 319239278Sgonzostatic int 320239278Sgonzolpc_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 321239278Sgonzo{ 322239278Sgonzo const struct lpc_gpio_pinmap *map; 323239278Sgonzo int idx; 324239278Sgonzo 325239278Sgonzo map = lpc_gpio_get_pinmap(pin); 326239278Sgonzo idx = LPC_GPIO_PIN_IDX(map, pin); 327239278Sgonzo 328239278Sgonzo switch (map->lp_port) { 329239278Sgonzo case 0: 330239278Sgonzo case 1: 331239278Sgonzo case 2: 332239278Sgonzo snprintf(name, GPIOMAXNAME - 1, "P%d.%d", map->lp_port, 333239278Sgonzo map->lp_start_bit + LPC_GPIO_PIN_IDX(map, pin)); 334239278Sgonzo break; 335239278Sgonzo case 3: 336239278Sgonzo if (map->lp_start_bit == -1) { 337239278Sgonzo snprintf(name, GPIOMAXNAME - 1, "GPIO_%02d", idx); 338239278Sgonzo break; 339239278Sgonzo } 340239278Sgonzo 341239278Sgonzo snprintf(name, GPIOMAXNAME - 1, "GP%c_%02d", 342239278Sgonzo (map->lp_flags & GPIO_PIN_INPUT) ? 'I' : 'O', 343239278Sgonzo map->lp_start_bit + idx); 344239278Sgonzo break; 345239278Sgonzo } 346239278Sgonzo 347239278Sgonzo return (0); 348239278Sgonzo} 349239278Sgonzo 350239278Sgonzostatic int 351239278Sgonzolpc_gpio_pin_get(device_t dev, uint32_t pin, uint32_t *value) 352239278Sgonzo{ 353239278Sgonzo struct lpc_gpio_softc *sc = device_get_softc(dev); 354239278Sgonzo const struct lpc_gpio_pinmap *map; 355239278Sgonzo uint32_t state, flags; 356239278Sgonzo int dir; 357239278Sgonzo 358239278Sgonzo map = lpc_gpio_get_pinmap(pin); 359239278Sgonzo 360239278Sgonzo if (lpc_gpio_pin_getflags(dev, pin, &flags)) 361239278Sgonzo return (ENXIO); 362239278Sgonzo 363239278Sgonzo if (flags & GPIO_PIN_OUTPUT) 364239278Sgonzo dir = 1; 365239278Sgonzo 366239278Sgonzo if (flags & GPIO_PIN_INPUT) 367239278Sgonzo dir = 0; 368239278Sgonzo 369239278Sgonzo switch (map->lp_port) { 370239278Sgonzo case 0: 371239278Sgonzo state = lpc_gpio_get_4(sc, dir, LPC_GPIO_P0_OUTP_STATE, 372239278Sgonzo LPC_GPIO_P0_INP_STATE); 373239278Sgonzo *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 374239278Sgonzo case 1: 375239278Sgonzo state = lpc_gpio_get_4(sc, dir, LPC_GPIO_P1_OUTP_STATE, 376239278Sgonzo LPC_GPIO_P1_INP_STATE); 377239278Sgonzo *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 378239278Sgonzo case 2: 379239278Sgonzo state = lpc_gpio_read_4(sc, LPC_GPIO_P2_INP_STATE); 380239278Sgonzo *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 381239278Sgonzo case 3: 382239278Sgonzo state = lpc_gpio_get_4(sc, dir, LPC_GPIO_P3_OUTP_STATE, 383239278Sgonzo LPC_GPIO_P3_INP_STATE); 384239278Sgonzo if (map->lp_start_bit == -1) { 385239278Sgonzo if (dir) 386239278Sgonzo *value = !!(state & (1 << (25 + 387239278Sgonzo LPC_GPIO_PIN_IDX(map, pin)))); 388239278Sgonzo else 389239278Sgonzo *value = !!(state & (1 << (10 + 390239278Sgonzo LPC_GPIO_PIN_IDX(map, pin)))); 391239278Sgonzo } 392239278Sgonzo 393239278Sgonzo *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin))); 394239278Sgonzo } 395239278Sgonzo 396239278Sgonzo return (0); 397239278Sgonzo} 398239278Sgonzo 399239278Sgonzostatic int 400239278Sgonzolpc_gpio_pin_set(device_t dev, uint32_t pin, uint32_t value) 401239278Sgonzo{ 402239278Sgonzo struct lpc_gpio_softc *sc = device_get_softc(dev); 403239278Sgonzo const struct lpc_gpio_pinmap *map; 404239278Sgonzo uint32_t state, flags; 405239278Sgonzo 406239278Sgonzo map = lpc_gpio_get_pinmap(pin); 407239278Sgonzo 408239278Sgonzo if (lpc_gpio_pin_getflags(dev, pin, &flags)) 409239278Sgonzo return (ENXIO); 410239278Sgonzo 411239278Sgonzo if ((flags & GPIO_PIN_OUTPUT) == 0) 412239278Sgonzo return (EINVAL); 413239278Sgonzo 414239278Sgonzo state = (1 << LPC_GPIO_PIN_BIT(map, pin)); 415239278Sgonzo 416239278Sgonzo switch (map->lp_port) { 417239278Sgonzo case 0: 418239278Sgonzo lpc_gpio_set_4(sc, value, LPC_GPIO_P0_OUTP_SET, 419239278Sgonzo LPC_GPIO_P0_OUTP_CLR, state); 420239278Sgonzo break; 421239278Sgonzo case 1: 422239278Sgonzo lpc_gpio_set_4(sc, value, LPC_GPIO_P1_OUTP_SET, 423239278Sgonzo LPC_GPIO_P1_OUTP_CLR, state); 424239278Sgonzo break; 425239278Sgonzo case 2: 426239278Sgonzo lpc_gpio_set_4(sc, value, LPC_GPIO_P2_OUTP_SET, 427239278Sgonzo LPC_GPIO_P2_OUTP_CLR, state); 428239278Sgonzo break; 429239278Sgonzo case 3: 430239278Sgonzo if (map->lp_start_bit == -1) 431239278Sgonzo state = (1 << (25 + LPC_GPIO_PIN_IDX(map, pin))); 432239278Sgonzo 433239278Sgonzo lpc_gpio_set_4(sc, value, LPC_GPIO_P3_OUTP_SET, 434239278Sgonzo LPC_GPIO_P3_OUTP_CLR, state); 435239278Sgonzo break; 436239278Sgonzo } 437239278Sgonzo 438239278Sgonzo return (0); 439239278Sgonzo} 440239278Sgonzo 441239278Sgonzostatic int 442239278Sgonzolpc_gpio_pin_toggle(device_t dev, uint32_t pin) 443239278Sgonzo{ 444239278Sgonzo const struct lpc_gpio_pinmap *map; 445239278Sgonzo uint32_t flags; 446239278Sgonzo 447239278Sgonzo map = lpc_gpio_get_pinmap(pin); 448239278Sgonzo 449239278Sgonzo if (lpc_gpio_pin_getflags(dev, pin, &flags)) 450239278Sgonzo return (ENXIO); 451239278Sgonzo 452239278Sgonzo if ((flags & GPIO_PIN_OUTPUT) == 0) 453239278Sgonzo return (EINVAL); 454239278Sgonzo 455239278Sgonzo panic("not implemented yet"); 456239278Sgonzo 457239278Sgonzo return (0); 458239278Sgonzo 459239278Sgonzo} 460239278Sgonzo 461239278Sgonzostatic const struct lpc_gpio_pinmap * 462239278Sgonzolpc_gpio_get_pinmap(int pin) 463239278Sgonzo{ 464239278Sgonzo const struct lpc_gpio_pinmap *map; 465239278Sgonzo 466239278Sgonzo for (map = &lpc_gpio_pins[0]; map->lp_start_idx != -1; map++) { 467239278Sgonzo if (pin >= map->lp_start_idx && 468239278Sgonzo pin < map->lp_start_idx + map->lp_pin_count) 469239278Sgonzo return map; 470239278Sgonzo } 471239278Sgonzo 472239278Sgonzo panic("pin number %d out of range", pin); 473239278Sgonzo} 474239278Sgonzo 475239278Sgonzoint 476239278Sgonzolpc_gpio_set_flags(device_t dev, int pin, int flags) 477239278Sgonzo{ 478239278Sgonzo if (lpc_gpio_sc == NULL) 479239278Sgonzo return (ENXIO); 480239278Sgonzo 481239278Sgonzo return lpc_gpio_pin_setflags(lpc_gpio_sc->lg_dev, pin, flags); 482239278Sgonzo} 483239278Sgonzo 484239278Sgonzoint 485239278Sgonzolpc_gpio_set_state(device_t dev, int pin, int state) 486239278Sgonzo{ 487239278Sgonzo if (lpc_gpio_sc == NULL) 488239278Sgonzo return (ENXIO); 489239278Sgonzo 490239278Sgonzo return lpc_gpio_pin_set(lpc_gpio_sc->lg_dev, pin, state); 491239278Sgonzo} 492239278Sgonzo 493239278Sgonzoint 494239278Sgonzolpc_gpio_get_state(device_t dev, int pin, int *state) 495239278Sgonzo{ 496239278Sgonzo if (lpc_gpio_sc == NULL) 497239278Sgonzo return (ENXIO); 498239278Sgonzo 499239278Sgonzo return lpc_gpio_pin_get(lpc_gpio_sc->lg_dev, pin, state); 500239278Sgonzo} 501239278Sgonzo 502239278Sgonzovoid 503239278Sgonzoplatform_gpio_init() 504239278Sgonzo{ 505260326Sian bus_space_tag_t bst; 506260326Sian bus_space_handle_t bsh; 507260326Sian 508260326Sian bst = fdtbus_bs_tag; 509260326Sian 510239278Sgonzo /* Preset SPI devices CS pins to one */ 511260326Sian bus_space_map(bst, LPC_GPIO_PHYS_BASE, LPC_GPIO_SIZE, 0, &bsh); 512260326Sian bus_space_write_4(bst, bsh, LPC_GPIO_P3_OUTP_SET, 513239278Sgonzo 1 << (SSD1289_CS_PIN - LPC_GPIO_GPO_00(0)) | 514239278Sgonzo 1 << (SSD1289_DC_PIN - LPC_GPIO_GPO_00(0)) | 515239278Sgonzo 1 << (ADS7846_CS_PIN - LPC_GPIO_GPO_00(0))); 516260326Sian bus_space_unmap(bst, bsh, LPC_GPIO_SIZE); 517239278Sgonzo} 518239278Sgonzo 519239278Sgonzostatic device_method_t lpc_gpio_methods[] = { 520239278Sgonzo /* Device interface */ 521239278Sgonzo DEVMETHOD(device_probe, lpc_gpio_probe), 522239278Sgonzo DEVMETHOD(device_attach, lpc_gpio_attach), 523239278Sgonzo DEVMETHOD(device_detach, lpc_gpio_detach), 524239278Sgonzo 525239278Sgonzo /* GPIO interface */ 526239278Sgonzo DEVMETHOD(gpio_pin_max, lpc_gpio_pin_max), 527239278Sgonzo DEVMETHOD(gpio_pin_getcaps, lpc_gpio_pin_getcaps), 528239278Sgonzo DEVMETHOD(gpio_pin_getflags, lpc_gpio_pin_getflags), 529239278Sgonzo DEVMETHOD(gpio_pin_setflags, lpc_gpio_pin_setflags), 530239278Sgonzo DEVMETHOD(gpio_pin_getname, lpc_gpio_pin_getname), 531239278Sgonzo DEVMETHOD(gpio_pin_set, lpc_gpio_pin_set), 532239278Sgonzo DEVMETHOD(gpio_pin_get, lpc_gpio_pin_get), 533239278Sgonzo DEVMETHOD(gpio_pin_toggle, lpc_gpio_pin_toggle), 534239278Sgonzo 535239278Sgonzo { 0, 0 } 536239278Sgonzo}; 537239278Sgonzo 538239278Sgonzostatic devclass_t lpc_gpio_devclass; 539239278Sgonzo 540239278Sgonzostatic driver_t lpc_gpio_driver = { 541239278Sgonzo "lpcgpio", 542239278Sgonzo lpc_gpio_methods, 543239278Sgonzo sizeof(struct lpc_gpio_softc), 544239278Sgonzo}; 545239278Sgonzo 546239278Sgonzoextern devclass_t gpiobus_devclass, gpioc_devclass; 547239278Sgonzoextern driver_t gpiobus_driver, gpioc_driver; 548239278Sgonzo 549239278SgonzoDRIVER_MODULE(lpcgpio, simplebus, lpc_gpio_driver, lpc_gpio_devclass, 0, 0); 550239278SgonzoDRIVER_MODULE(gpiobus, lpcgpio, gpiobus_driver, gpiobus_devclass, 0, 0); 551239278SgonzoDRIVER_MODULE(gpioc, lpcgpio, gpioc_driver, gpioc_devclass, 0, 0); 552239278SgonzoMODULE_VERSION(lpcgpio, 1); 553