Implement gpio framework for the Samsung Exynos series.
Note that only the Exynos4 gpio registers are defined now and provision is taken to allow for seamlessness adding of Exynos5 values.
This commit is contained in:
parent
aaace33d0e
commit
5ad8bd1845
@ -264,6 +264,7 @@
|
||||
EXYNOS4##p##_##n##_OFFSET, 0x10000
|
||||
|
||||
static const struct exyo_locators exynos4_locators[] = {
|
||||
{ "exyogpio", 0, 0, NOPORT, NOINTR, 0 },
|
||||
{ "mct", OFFANDSIZE(,MCT), NOPORT, IRQ_G0_IRQ, 0 },
|
||||
{ "exyowdt", OFFANDSIZE(,WDT), NOPORT, IRQ_WDT, 0 },
|
||||
{ "sscom", OFFANDSIZE(,UART0), 0, IRQ_UART0, 0 },
|
||||
|
791
sys/arch/arm/samsung/exynos_gpio.c
Normal file
791
sys/arch/arm/samsung/exynos_gpio.c
Normal file
@ -0,0 +1,791 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Reinoud Zandijk
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opt_exynos.h"
|
||||
#include "opt_arm_debug.h"
|
||||
#include "gpio.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(1, "$NetBSD: exynos_gpio.c,v 1.1 2014/05/09 21:49:43 reinoud Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/intr.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kmem.h>
|
||||
|
||||
#include <arm/samsung/exynos_reg.h>
|
||||
#include <arm/samsung/exynos_io.h>
|
||||
#include <arm/samsung/exynos_intr.h>
|
||||
|
||||
#include <sys/gpio.h>
|
||||
#include <dev/gpio/gpiovar.h>
|
||||
|
||||
static int exynos_gpio_match(device_t, cfdata_t, void *);
|
||||
static void exynos_gpio_attach(device_t, device_t, void *);
|
||||
|
||||
static int exynos_gpio_pin_read(void *, int);
|
||||
static void exynos_gpio_pin_write(void *, int, int);
|
||||
static void exynos_gpio_pin_ctl(void *, int, int);
|
||||
|
||||
struct exynos_gpio_pin_cfg {
|
||||
uint32_t cfg;
|
||||
uint32_t pud;
|
||||
uint32_t drv;
|
||||
uint32_t conpwd;
|
||||
uint32_t pudpwd;
|
||||
};
|
||||
|
||||
struct exynos_gpio_pin_group {
|
||||
const char grp_name[6];
|
||||
const bus_addr_t grp_core_offset;
|
||||
const uint8_t grp_bits;
|
||||
|
||||
uint8_t grp_pin_mask;
|
||||
uint8_t grp_pin_inuse_mask;
|
||||
bus_space_handle_t grp_bsh;
|
||||
struct exynos_gpio_pin_cfg grp_cfg;
|
||||
struct gpio_chipset_tag grp_gc_tag;
|
||||
};
|
||||
|
||||
|
||||
#define GPIO_OFFSET(v,s,o) (EXYNOS##v##_GPIO_##s##_OFFSET + (o))
|
||||
#define GPIO_GRP(v, s, o, n, b) \
|
||||
{ \
|
||||
.grp_name = #n, \
|
||||
.grp_core_offset = GPIO_OFFSET(v,s,o), \
|
||||
.grp_bits = b,\
|
||||
}
|
||||
|
||||
#ifdef EXYNOS4
|
||||
/*
|
||||
* Exynos 4412 contains 304 multi-functional input/output port pins and 164
|
||||
* memory port pins. There are 37 general port groups and two memory port
|
||||
* groups. They are:
|
||||
*
|
||||
* GPA0, GPA1: 14 in/out ports-3xUART with flow control, UART without flow
|
||||
* control, and/or 2xI2C
|
||||
*
|
||||
* GPB: 8 in/out ports-2xSPI and/or 2xI2C and/ or IEM
|
||||
*
|
||||
* GPC0, GPC1: 10 in/out ports-2xI2S, and/or 2xPCM, and/or AC97, SPDIF, I2C,
|
||||
* and/or SPI
|
||||
*
|
||||
* GPD0, GPD1: 8 in/out ports-PWM, 2xI2C, and/ or LCD I/F, MIPI
|
||||
*
|
||||
* GPM0, GPM1, GPM2, GPM3, GPM4: 35 in/out ports-CAM I/F, and/ or TS I/F,
|
||||
* HSI, and/ or Trace I/F
|
||||
*
|
||||
* GPF0, GPF1, GPF2, GPF3: 30 in/out ports-LCD I/F
|
||||
*
|
||||
* GPJ0, GPJ1: 13 in/out ports-CAM I/F
|
||||
*
|
||||
* GPK0, GPK1, GPK2, GPK3: 28 in/out ports-4xMMC (4-bit MMC), and/or 2xMMC
|
||||
* (8-bit MMC)), and/or GPS debugging I/F
|
||||
*
|
||||
* GPL0, GPL1: 11 in/out ports-GPS I/F
|
||||
*
|
||||
* GPL2: 8 in/out ports-GPS debugging I/F or Key pad I/F
|
||||
*
|
||||
* GPX0, GPX1, GPX2, GPX3: 32 in/out ports-External wake-up, and/or Key pad
|
||||
* I/F
|
||||
*
|
||||
* GPZ: 7 in/out ports-low Power I2S and/or PCM
|
||||
*
|
||||
* GPY0, GPY1, GPY2: 16 in/out ports-Control signals of EBI (SROM, NF, One
|
||||
* NAND)
|
||||
*
|
||||
* GPY3, GPY4, GPY5, GPY6: 32 in/out memory ports-EBI (For more information
|
||||
* about EBI configuration, refer to Chapter 5, and 6)
|
||||
*
|
||||
* MP1_0-MP1_9: 78 DRAM1 ports. NOTE: GPIO registers does not control these
|
||||
* ports.
|
||||
*
|
||||
* MP2_0-MP2_9: 78 DRAM2 ports. NOTE: GPIO registers does not control these
|
||||
* ports.
|
||||
*
|
||||
* ETC0, ETC1, ETC6: 18 in/out ETC ports-JTAG, SLIMBUS, RESET, CLOCK
|
||||
*
|
||||
* ETC7, ETC8 : 4 clock port for C2C
|
||||
*
|
||||
*/
|
||||
|
||||
static struct exynos_gpio_pin_group exynos4_pin_groups[] = {
|
||||
GPIO_GRP(4, LEFT, 0x0000, GPA0, 8),
|
||||
GPIO_GRP(4, LEFT, 0x0020, GPA1, 6),
|
||||
GPIO_GRP(4, LEFT, 0x0040, GPB, 8),
|
||||
GPIO_GRP(4, LEFT, 0x0060, GPC0, 5),
|
||||
GPIO_GRP(4, LEFT, 0x0080, GPC1, 5),
|
||||
GPIO_GRP(4, LEFT, 0x00A0, GPD0, 4),
|
||||
GPIO_GRP(4, LEFT, 0x00C0, GPD1, 4),
|
||||
GPIO_GRP(4, LEFT, 0x0180, GPF0, 8),
|
||||
GPIO_GRP(4, LEFT, 0x01A0, GPF1, 8),
|
||||
GPIO_GRP(4, LEFT, 0x01C0, GPF2, 8),
|
||||
GPIO_GRP(4, LEFT, 0x01E0, GPF3, 8),
|
||||
GPIO_GRP(4, LEFT, 0x0240, GPJ0, 8),
|
||||
GPIO_GRP(4, LEFT, 0x0260, GPJ1, 5),
|
||||
/* EXTINT skipped */
|
||||
|
||||
GPIO_GRP(4, RIGHT, 0x0040, GPK0, 8),
|
||||
GPIO_GRP(4, RIGHT, 0x0060, GPK1, 8),
|
||||
GPIO_GRP(4, RIGHT, 0x0080, GPK2, 7),
|
||||
GPIO_GRP(4, RIGHT, 0x00A0, GPK3, 7),
|
||||
GPIO_GRP(4, RIGHT, 0x00C0, GPL0, 7),
|
||||
GPIO_GRP(4, RIGHT, 0x00E0, GPL1, 2),
|
||||
GPIO_GRP(4, RIGHT, 0x0100, GPL2, 8),
|
||||
GPIO_GRP(4, RIGHT, 0x0120, GPY0, 6),
|
||||
GPIO_GRP(4, RIGHT, 0x0140, GPY1, 4),
|
||||
GPIO_GRP(4, RIGHT, 0x0160, GPY2, 6),
|
||||
GPIO_GRP(4, RIGHT, 0x0180, GPY3, 8),
|
||||
GPIO_GRP(4, RIGHT, 0x01A0, GPY4, 8),
|
||||
GPIO_GRP(4, RIGHT, 0x01C0, GPY5, 8),
|
||||
GPIO_GRP(4, RIGHT, 0x01E0, GPY6, 8),
|
||||
/* ETC0, ETC6 skipped */
|
||||
GPIO_GRP(4, RIGHT, 0x0260, GPM0, 8),
|
||||
GPIO_GRP(4, RIGHT, 0x0280, GPM1, 7),
|
||||
GPIO_GRP(4, RIGHT, 0x02A0, GPM2, 5),
|
||||
GPIO_GRP(4, RIGHT, 0x02C0, GPM3, 8),
|
||||
GPIO_GRP(4, RIGHT, 0x02E0, GPM4, 8),
|
||||
/* EXTINT skipped */
|
||||
GPIO_GRP(4, RIGHT, 0x0C00, GPX0, 8),
|
||||
GPIO_GRP(4, RIGHT, 0x0C20, GPX1, 8),
|
||||
GPIO_GRP(4, RIGHT, 0x0C40, GPX2, 8),
|
||||
GPIO_GRP(4, RIGHT, 0x0C60, GPX3, 8),
|
||||
/* EXTINT skipped */
|
||||
|
||||
GPIO_GRP(4, I2C0, 0x0000, GPZ, 8),
|
||||
/* EXTINT skipped */
|
||||
|
||||
GPIO_GRP(4, C2C, 0x0000, GPV0, 8),
|
||||
GPIO_GRP(4, C2C, 0x0020, GPV1, 8),
|
||||
/* ETC7 skipped */
|
||||
GPIO_GRP(4, C2C, 0x0060, GPV2, 8),
|
||||
GPIO_GRP(4, C2C, 0x0080, GPV3, 8),
|
||||
/* ETC8 skipped */
|
||||
GPIO_GRP(4, C2C, 0x00C0, GPV4, 2),
|
||||
/* EXTINT skipped */
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef EXYNOS5
|
||||
static struct exynos_gpio_pin_group exynos5_pin_groups[] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
struct exynos_gpio_softc {
|
||||
device_t sc_dev;
|
||||
bus_space_tag_t sc_bst;
|
||||
bus_space_handle_t sc_bsh;
|
||||
};
|
||||
|
||||
|
||||
/* force these structures in DATA segment */
|
||||
static struct exynos_gpio_pin_group *exynos_pin_groups = NULL;
|
||||
static int exynos_n_pin_groups = 0;
|
||||
|
||||
static struct exynos_gpio_softc exynos_gpio_sc = {};
|
||||
|
||||
|
||||
CFATTACH_DECL_NEW(exynos_gpio, sizeof(struct exynos_gpio_softc),
|
||||
exynos_gpio_match, exynos_gpio_attach, NULL, NULL);
|
||||
|
||||
|
||||
static int
|
||||
exynos_gpio_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
struct exyo_attach_args * const exyoaa = aux;
|
||||
struct exyo_locators *loc = &exyoaa->exyo_loc;
|
||||
|
||||
/* no locators expected */
|
||||
KASSERT(loc->loc_offset == 0);
|
||||
KASSERT(loc->loc_size == 0);
|
||||
KASSERT(loc->loc_port == EXYOCF_PORT_DEFAULT);
|
||||
|
||||
/* there can only be one */
|
||||
if (exynos_gpio_sc.sc_dev != NULL)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#if NGPIO > 0
|
||||
static void
|
||||
exynos_gpio_config_pins(device_t self)
|
||||
{
|
||||
struct exynos_gpio_softc * const sc = &exynos_gpio_sc;
|
||||
struct exynos_gpio_pin_group *grp;
|
||||
struct gpiobus_attach_args gba;
|
||||
gpio_pin_t *pin, *pins;
|
||||
size_t pin_count = 0;
|
||||
int i, bit, mask, pincaps, data;
|
||||
|
||||
/* find out how many pins we can offer */
|
||||
pin_count = 0;
|
||||
for (i = 0; i < exynos_n_pin_groups; i++) {
|
||||
grp = &exynos_pin_groups[i];
|
||||
mask = grp->grp_pin_mask & ~grp->grp_pin_inuse_mask;
|
||||
pin_count += popcount32(mask);
|
||||
}
|
||||
|
||||
/* if no pins available, don't proceed */
|
||||
if (pin_count == 0)
|
||||
return;
|
||||
|
||||
/* allocate pin data */
|
||||
pins = kmem_zalloc(sizeof(gpio_pin_t) * pin_count, KM_SLEEP);
|
||||
KASSERT(pins);
|
||||
|
||||
pincaps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |
|
||||
GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN;
|
||||
|
||||
/* add all pins */
|
||||
pin = pins;
|
||||
for (i = 0; i < exynos_n_pin_groups; i++) {
|
||||
grp = &exynos_pin_groups[i];
|
||||
mask = grp->grp_pin_mask & ~grp->grp_pin_inuse_mask;
|
||||
if (mask == 0)
|
||||
continue;
|
||||
gba.gba_gc = &grp->grp_gc_tag;
|
||||
gba.gba_pins = pin;
|
||||
data = bus_space_read_1(sc->sc_bst, grp->grp_bsh,
|
||||
EXYNOS_GPIO_DAT);
|
||||
for (bit = 0; mask != 0; mask >>= 1, data >>= 1, bit++) {
|
||||
if (mask & 1) {
|
||||
pin->pin_num = bit + (i << 3);
|
||||
pin->pin_caps = pincaps;
|
||||
pin->pin_flags = pincaps;
|
||||
pin->pin_state = (data & 1) != 0;
|
||||
pin++;
|
||||
}
|
||||
}
|
||||
gba.gba_npins = pin - gba.gba_pins;
|
||||
config_found_ia(self, "gpiobus", &gba, gpiobus_print);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
exynos_gpio_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct exynos_gpio_softc * const sc = &exynos_gpio_sc;
|
||||
struct exyo_attach_args * const exyoaa = aux;
|
||||
struct exynos_gpio_pin_group *grp;
|
||||
prop_dictionary_t dict = device_properties(self);
|
||||
uint32_t nc;
|
||||
char scrap[16];
|
||||
int i;
|
||||
|
||||
KASSERT(exynos_pin_groups);
|
||||
KASSERT(exynos_n_pin_groups);
|
||||
|
||||
/* construct softc */
|
||||
sc->sc_dev = self;
|
||||
|
||||
/* we use the core bushandle here */
|
||||
sc->sc_bst = exyoaa->exyo_core_bst;
|
||||
sc->sc_bsh = exyoaa->exyo_core_bsh;
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal("\n");
|
||||
|
||||
/* go trough all pin groups */
|
||||
for (i = 0; i < exynos_n_pin_groups; i++) {
|
||||
grp = &exynos_pin_groups[i];
|
||||
snprintf(scrap, sizeof(scrap), "nc-%s", grp->grp_name);
|
||||
if (prop_dictionary_get_uint32(dict, scrap, &nc)) {
|
||||
KASSERT((~grp->grp_pin_mask & nc) == 0);
|
||||
KASSERT((grp->grp_pin_inuse_mask & ~nc) == 0);
|
||||
grp->grp_pin_mask &= ~nc;
|
||||
}
|
||||
}
|
||||
|
||||
#if NGPIO > 0
|
||||
config_defer(self, exynos_gpio_config_pins);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* pin access functions */
|
||||
static u_int
|
||||
exynos_gpio_get_pin_func(const struct exynos_gpio_pin_cfg *cfg, int pin)
|
||||
{
|
||||
const u_int shift = (pin & 7) << 4;
|
||||
|
||||
return (cfg->cfg >> shift) & 0x0f;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
exynos_gpio_set_pin_func(struct exynos_gpio_pin_cfg *cfg,
|
||||
int pin, int func)
|
||||
{
|
||||
const u_int shift = (pin & 7) << 4;
|
||||
|
||||
cfg->cfg &= ~(0x0f << shift);
|
||||
cfg->cfg |= func << shift;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
exynos_gpio_set_pin_pull(struct exynos_gpio_pin_cfg *cfg, int pin, int pull)
|
||||
{
|
||||
const u_int shift = (pin & 7) << 1;
|
||||
|
||||
cfg->pud &= ~(0x3 << shift);
|
||||
cfg->pud |= pull << shift;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
exynos_gpio_pin_read(void *cookie, int pin)
|
||||
{
|
||||
struct exynos_gpio_pin_group * const grp = cookie;
|
||||
|
||||
KASSERT(pin < grp->grp_bits);
|
||||
return (bus_space_read_1(exynos_gpio_sc.sc_bst, grp->grp_bsh,
|
||||
EXYNOS_GPIO_DAT) >> pin) & 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
exynos_gpio_pin_write(void *cookie, int pin, int value)
|
||||
{
|
||||
struct exynos_gpio_pin_group * const grp = cookie;
|
||||
int val;
|
||||
|
||||
KASSERT(pin < grp->grp_bits);
|
||||
val = bus_space_read_1(exynos_gpio_sc.sc_bst, grp->grp_bsh,
|
||||
EXYNOS_GPIO_DAT);
|
||||
val &= ~__BIT(pin);
|
||||
if (value)
|
||||
val |= __BIT(pin);
|
||||
bus_space_write_1(exynos_gpio_sc.sc_bst, grp->grp_bsh,
|
||||
EXYNOS_GPIO_DAT, val);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
exynos_gpio_update_cfg_regs(struct exynos_gpio_pin_group *grp,
|
||||
const struct exynos_gpio_pin_cfg *ncfg)
|
||||
{
|
||||
bus_space_tag_t bst = &exynos_bs_tag;
|
||||
|
||||
if (grp->grp_cfg.cfg != ncfg->cfg) {
|
||||
bus_space_write_4(bst, grp->grp_bsh,
|
||||
EXYNOS_GPIO_CON, ncfg->cfg);
|
||||
grp->grp_cfg.cfg = ncfg->cfg;
|
||||
}
|
||||
if (grp->grp_cfg.pud != ncfg->pud) {
|
||||
bus_space_write_4(bst, grp->grp_bsh,
|
||||
EXYNOS_GPIO_PUD, ncfg->pud);
|
||||
grp->grp_cfg.pud = ncfg->pud;
|
||||
}
|
||||
|
||||
/* the following attributes are not yet setable */
|
||||
#if 0
|
||||
if (grp->grp_cfg.drv != ncfg->drv) {
|
||||
bus_space_write_4(bst, grp->grp_bsh,
|
||||
EXYNOS_GPIO_DRV, ncfg->drv);
|
||||
grp->grp_cfg.drv = ncfg->drv;
|
||||
}
|
||||
if (grp->grp_cfg.conpwd != ncfg->conpwd) {
|
||||
bus_space_write_4(bst, grp->grp_bsh,
|
||||
EXYNOS_GPIO_CONPWD, ncfg->conpwd);
|
||||
grp->grp_cfg.conpwd = ncfg->conpwd;
|
||||
}
|
||||
if (grp->grp_cfg.pudpwd != ncfg->pudpwd) {
|
||||
bus_space_write_4(bst, grp->grp_bsh,
|
||||
EXYNOS_GPIO_PUDPWD, ncfg->pudpwd);
|
||||
grp->grp_cfg.pudpwd = ncfg->pudpwd;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
exynos_gpio_pin_ctl(void *cookie, int pin, int flags)
|
||||
{
|
||||
struct exynos_gpio_pin_group * const grp = cookie;
|
||||
struct exynos_gpio_pin_cfg ncfg = grp->grp_cfg;
|
||||
int pull;
|
||||
|
||||
/* honour pullup requests */
|
||||
pull = EXYNOS_GPIO_PIN_FLOAT;
|
||||
if (flags & GPIO_PIN_PULLUP)
|
||||
pull = EXYNOS_GPIO_PIN_PULL_UP;
|
||||
if (flags & GPIO_PIN_PULLDOWN)
|
||||
pull = EXYNOS_GPIO_PIN_PULL_DOWN;
|
||||
exynos_gpio_set_pin_pull(&ncfg, pin, pull);
|
||||
|
||||
/* honour i/o */
|
||||
if (flags & GPIO_PIN_INPUT)
|
||||
exynos_gpio_set_pin_func(&ncfg, pin, EXYNOS_GPIO_FUNC_INPUT);
|
||||
if (flags & GPIO_PIN_OUTPUT)
|
||||
exynos_gpio_set_pin_func(&ncfg, pin, EXYNOS_GPIO_FUNC_OUTPUT);
|
||||
|
||||
/* update any config registers that changed */
|
||||
exynos_gpio_update_cfg_regs(grp, &ncfg);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
exynos_gpio_pinset_available(const struct exynos_gpio_pinset *req)
|
||||
{
|
||||
struct exynos_gpio_pin_group *grp;
|
||||
int i, n, inuse;
|
||||
|
||||
KASSERT(req);
|
||||
|
||||
/* we need a pinset group */
|
||||
if (strlen(req->pinset_group) == 0)
|
||||
return false;
|
||||
|
||||
/* determine which group is requested */
|
||||
grp = NULL;
|
||||
for (i = 0; i < exynos_n_pin_groups; i++) {
|
||||
grp = &exynos_pin_groups[i];
|
||||
if (strcmp(req->pinset_group, grp->grp_name) == 0)
|
||||
break;
|
||||
}
|
||||
/* found? */
|
||||
if (i == exynos_n_pin_groups)
|
||||
return false;
|
||||
KASSERT(grp);
|
||||
|
||||
/* fail unconnected pins */
|
||||
if (req->pinset_mask & ~grp->grp_pin_mask)
|
||||
return false;
|
||||
|
||||
/* if none in use, they are available */
|
||||
if (req->pinset_mask & ~grp->grp_pin_inuse_mask)
|
||||
return true;
|
||||
|
||||
/* OK, so some are in use; now see if the request is compatible */
|
||||
inuse = req->pinset_mask & grp->grp_pin_inuse_mask;
|
||||
for (i = 0; inuse; i++, inuse >>= 1) {
|
||||
/* try to be smart by skipping zero's */
|
||||
n = ffs(inuse) -1;
|
||||
i += n;
|
||||
inuse >>= n;
|
||||
/* this pin is in use, check its usage */
|
||||
if (exynos_gpio_get_pin_func(&grp->grp_cfg, i) != req->pinset_func)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* seems to be OK */
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
exynos_gpio_pinset_acquire(const struct exynos_gpio_pinset *req)
|
||||
{
|
||||
struct exynos_gpio_pin_group *grp;
|
||||
struct exynos_gpio_pin_cfg ncfg;
|
||||
int i, n, todo;
|
||||
|
||||
KASSERT(req);
|
||||
KASSERT(exynos_gpio_pinset_available(req));
|
||||
|
||||
/* determine which group is requested */
|
||||
grp = NULL;
|
||||
for (i = 0; i < exynos_n_pin_groups; i++) {
|
||||
grp = &exynos_pin_groups[i];
|
||||
if (strcmp(req->pinset_group, grp->grp_name) == 0)
|
||||
break;
|
||||
}
|
||||
KASSERT(grp);
|
||||
|
||||
/* check if all the pins have the right function */
|
||||
if ((req->pinset_mask & ~grp->grp_pin_inuse_mask) == 0)
|
||||
return;
|
||||
|
||||
/* copy current config for update routine */
|
||||
ncfg = grp->grp_cfg;
|
||||
|
||||
/* update the function of each pin that is not in use */
|
||||
todo = req->pinset_mask & grp->grp_pin_inuse_mask;
|
||||
for (i = 0; todo; i++, todo >>= 1) {
|
||||
/* try to be smart by skipping zero's */
|
||||
n = ffs(todo) -1;
|
||||
i += n;
|
||||
todo >>= n;
|
||||
/* change the function of this pin */
|
||||
exynos_gpio_set_pin_func(&ncfg, i, req->pinset_func);
|
||||
}
|
||||
|
||||
/* update config registers */
|
||||
exynos_gpio_update_cfg_regs(grp, &ncfg);
|
||||
|
||||
/* mark pins in use */
|
||||
grp->grp_pin_inuse_mask |= req->pinset_mask;
|
||||
}
|
||||
|
||||
|
||||
/* XXXRPZ This release doesn't grock multiple usages! */
|
||||
void
|
||||
exynos_gpio_pinset_release(const struct exynos_gpio_pinset *req)
|
||||
{
|
||||
struct exynos_gpio_pin_group *grp;
|
||||
int i;
|
||||
|
||||
KASSERT(!exynos_gpio_pinset_available(req));
|
||||
|
||||
/* determine which group is requested */
|
||||
grp = NULL;
|
||||
for (i = 0; i < exynos_n_pin_groups; i++) {
|
||||
grp = &exynos_pin_groups[i];
|
||||
if (strcmp(req->pinset_group, grp->grp_name) == 0)
|
||||
break;
|
||||
}
|
||||
KASSERT(grp);
|
||||
|
||||
/* bluntly mark as not being in use */
|
||||
grp->grp_pin_inuse_mask &= ~req->pinset_mask;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* name convention :
|
||||
* pin = <func><groupname><pinnr>[<pud>]
|
||||
* func = '<' | '>'
|
||||
* pinnr = '['['0'-'7']']'
|
||||
* pud = 'F' | 'U' | 'D'
|
||||
*
|
||||
* example "<GPC1[0]", ">GPB[0]"
|
||||
*/
|
||||
|
||||
bool
|
||||
exynos_gpio_pin_reserve(const char *name, struct exynos_gpio_pindata *pd)
|
||||
{
|
||||
struct exynos_gpio_softc * const sc = &exynos_gpio_sc;
|
||||
struct exynos_gpio_pin_group *grp;
|
||||
struct exynos_gpio_pin_cfg ncfg;
|
||||
prop_dictionary_t dict = device_properties(sc->sc_dev);
|
||||
const char *pin_data;
|
||||
char grp_name[15], *pos;
|
||||
int func, pud, pinnr;
|
||||
int pi, i;
|
||||
|
||||
/* do we have a named pin description? */
|
||||
if (!prop_dictionary_get_cstring_nocopy(dict, name, &pin_data))
|
||||
return false;
|
||||
|
||||
KASSERT(strlen(pin_data) < 10);
|
||||
if (!(pin_data[0] == '>' || pin_data[1] == '<')) {
|
||||
printf("%s: malformed pin data in '%s', missing direction\n",
|
||||
__func__, pin_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
func = (pin_data[0] == '<') ?
|
||||
EXYNOS_GPIO_FUNC_INPUT : EXYNOS_GPIO_FUNC_OUTPUT;
|
||||
|
||||
/* find groupname */
|
||||
pi = 1; pos = grp_name;
|
||||
while (pin_data[pi] && pin_data[pi] != '[') {
|
||||
*pos++ = pin_data[pi++];
|
||||
}
|
||||
if (pin_data[pi] != '[') {
|
||||
printf("%s: malformed pin data in '%s', missing '['\n",
|
||||
__func__, pin_data);
|
||||
return false;
|
||||
}
|
||||
*pos++ = (char) 0;
|
||||
|
||||
/* skip '[' */
|
||||
pi++;
|
||||
if (!(pin_data[pi] >= '0' && pin_data[pi] <= '7')) {
|
||||
printf("%s: malformed pin data in '%s', bad pin number\n",
|
||||
__func__, pin_data);
|
||||
return false;
|
||||
}
|
||||
pinnr = pin_data[pi] - '0';
|
||||
|
||||
/* skip digit */
|
||||
pi++;
|
||||
if ((pin_data[pi] != ']')) {
|
||||
printf("%s: malformed pin data in '%s', missing end ']'\n",
|
||||
__func__, pin_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* skip ']' */
|
||||
pi++;
|
||||
pud = EXYNOS_GPIO_PIN_FLOAT;
|
||||
switch (tolower(pin_data[pi])) {
|
||||
case (char) 0:
|
||||
break;
|
||||
case 'f':
|
||||
pud = EXYNOS_GPIO_PIN_FLOAT;
|
||||
break;
|
||||
case 'u':
|
||||
pud = EXYNOS_GPIO_PIN_PULL_UP;
|
||||
break;
|
||||
case 'd':
|
||||
pud = EXYNOS_GPIO_PIN_PULL_DOWN;
|
||||
break;
|
||||
default:
|
||||
printf("%s: malformed pin data in '%s', expecting "
|
||||
"optional pull up/down or float argument\n",
|
||||
__func__, pin_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* determine which group is requested */
|
||||
grp = NULL;
|
||||
for (i = 0; i < exynos_n_pin_groups; i++) {
|
||||
grp = &exynos_pin_groups[i];
|
||||
if (strcmp(grp_name, grp->grp_name) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* found? */
|
||||
if (i >= exynos_n_pin_groups) {
|
||||
printf("%s: malformed pin data in '%s', "
|
||||
"no such pin group name\n",
|
||||
__func__, grp_name);
|
||||
return false;
|
||||
}
|
||||
KASSERT(grp);
|
||||
|
||||
KASSERT(pinnr < grp->grp_bits);
|
||||
KASSERT(grp->grp_pin_mask & __BIT(pinnr));
|
||||
KASSERT((grp->grp_pin_inuse_mask & __BIT(pinnr)) == 0);
|
||||
|
||||
/* update our pin configuration */
|
||||
ncfg = grp->grp_cfg;
|
||||
exynos_gpio_set_pin_func(&ncfg, pinnr, func);
|
||||
exynos_gpio_set_pin_pull(&ncfg, pinnr, pud);
|
||||
exynos_gpio_update_cfg_regs(grp, &ncfg);
|
||||
|
||||
grp->grp_pin_inuse_mask &= ~__BIT(pinnr);
|
||||
|
||||
pd->pd_gc = &grp->grp_gc_tag;
|
||||
pd->pd_pin = pinnr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* bootstrapping */
|
||||
void
|
||||
exynos_gpio_bootstrap(void)
|
||||
{
|
||||
bus_space_tag_t bst = &exynos_bs_tag;
|
||||
struct exynos_gpio_pin_group *grp;
|
||||
struct gpio_chipset_tag *gc_tag;
|
||||
int i, j, func, mask;
|
||||
|
||||
/* determine what we're running on */
|
||||
#ifdef EXYNOS4
|
||||
if (IS_EXYNOS4_P()) {
|
||||
exynos_pin_groups = exynos4_pin_groups;
|
||||
exynos_n_pin_groups = __arraycount(exynos4_pin_groups);
|
||||
}
|
||||
#endif
|
||||
#ifdef EXYNOS5
|
||||
if (IS_EXYNOS5_P()) {
|
||||
exynos_pin_groups = exynos5_pin_groups;
|
||||
exynos_n_pin_groups = __arraycount(exynos5_pin_groups);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VERBOSE_INIT_ARM
|
||||
printf("gpio");
|
||||
#endif
|
||||
if (exynos_n_pin_groups == 0) {
|
||||
#ifdef VERBOSE_INIT_ARM
|
||||
printf(" (disabled)\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef VERBOSE_INIT_ARM
|
||||
printf(" free");
|
||||
#endif
|
||||
/* init groups */
|
||||
for (i = 0; i < exynos_n_pin_groups; i++) {
|
||||
grp = &exynos_pin_groups[i];
|
||||
gc_tag = &grp->grp_gc_tag;
|
||||
|
||||
bus_space_subregion(&exynos_bs_tag, exynos_core_bsh,
|
||||
grp->grp_core_offset, EXYNOS_GPIO_GRP_SIZE,
|
||||
&grp->grp_bsh);
|
||||
grp->grp_pin_mask = __BIT(grp->grp_bits) - 1;
|
||||
grp->grp_pin_inuse_mask = 0;
|
||||
|
||||
gc_tag->gp_cookie = grp;
|
||||
gc_tag->gp_pin_read = exynos_gpio_pin_read;
|
||||
gc_tag->gp_pin_write = exynos_gpio_pin_write;
|
||||
gc_tag->gp_pin_ctl = exynos_gpio_pin_ctl;
|
||||
|
||||
/* read in our initial settings */
|
||||
grp->grp_cfg.cfg = bus_space_read_4(bst, grp->grp_bsh,
|
||||
EXYNOS_GPIO_CON);
|
||||
grp->grp_cfg.pud = bus_space_read_4(bst, grp->grp_bsh,
|
||||
EXYNOS_GPIO_PUD);
|
||||
grp->grp_cfg.drv = bus_space_read_4(bst, grp->grp_bsh,
|
||||
EXYNOS_GPIO_DRV);
|
||||
grp->grp_cfg.conpwd = bus_space_read_4(bst, grp->grp_bsh,
|
||||
EXYNOS_GPIO_CONPWD);
|
||||
grp->grp_cfg.pudpwd = bus_space_read_4(bst, grp->grp_bsh,
|
||||
EXYNOS_GPIO_PUDPWD);
|
||||
|
||||
/* count number of busy pins */
|
||||
for (j = 0, mask = 1;
|
||||
(mask & grp->grp_pin_mask) != 0;
|
||||
j++, mask <<= 1) {
|
||||
func = exynos_gpio_get_pin_func(&grp->grp_cfg, j);
|
||||
if (func > EXYNOS_GPIO_FUNC_INPUT) {
|
||||
grp->grp_pin_inuse_mask |= mask;
|
||||
}
|
||||
}
|
||||
#ifdef VERBOSE_INIT_ARM
|
||||
printf(" P%s = %d", grp->grp_name,
|
||||
popcount32(grp->grp_pin_mask & ~grp->grp_pin_inuse_mask));
|
||||
#endif
|
||||
}
|
||||
#ifdef VERBOSE_INIT_ARM
|
||||
printf("\n");
|
||||
#if 0
|
||||
/* enable this for default NC pins list generation */
|
||||
for (i = 0; i < exynos_n_pin_groups; i++) {
|
||||
grp = &exynos_pin_groups[i];
|
||||
printf("prop_dictionary_set_uint32(dict, \"nc-%s\", 0x%02x - 0x00);\n",
|
||||
grp->grp_name, grp->grp_pin_mask);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: exynos_soc.c,v 1.7 2014/04/29 16:47:10 reinoud Exp $ */
|
||||
/* $NetBSD: exynos_soc.c,v 1.8 2014/05/09 21:49:43 reinoud Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2014 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
@ -33,7 +33,7 @@
|
||||
#define _ARM32_BUS_DMA_PRIVATE
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(1, "$NetBSD: exynos_soc.c,v 1.7 2014/04/29 16:47:10 reinoud Exp $");
|
||||
__KERNEL_RCSID(1, "$NetBSD: exynos_soc.c,v 1.8 2014/05/09 21:49:43 reinoud Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
@ -234,6 +234,9 @@ exynos_bootstrap(vaddr_t iobase, vaddr_t uartbase)
|
||||
|
||||
/* init bus dma tags */
|
||||
exynos_dma_bootstrap(physmem * PAGE_SIZE);
|
||||
|
||||
/* init gpio structures */
|
||||
exynos_gpio_bootstrap();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: exynos_var.h,v 1.4 2014/04/29 16:47:10 reinoud Exp $ */
|
||||
/* $NetBSD: exynos_var.h,v 1.5 2014/05/09 21:49:43 reinoud Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2013, 2014 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
@ -37,10 +37,9 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/gpio.h>
|
||||
#include <dev/gpio/gpiovar.h>
|
||||
#include <arm/samsung/exynos_reg.h>
|
||||
|
||||
//#include <dev/gpio/gpiovar.h>
|
||||
|
||||
extern uint32_t exynos_soc_id;
|
||||
extern uint32_t exynos_pop_id;
|
||||
|
||||
@ -95,6 +94,17 @@ struct exyo_attach_args {
|
||||
bus_dma_tag_t exyo_coherent_dmat;
|
||||
};
|
||||
|
||||
struct exynos_gpio_pinset {
|
||||
char pinset_group[10];
|
||||
uint8_t pinset_func;
|
||||
uint32_t pinset_mask;
|
||||
};
|
||||
|
||||
struct exynos_gpio_pindata {
|
||||
gpio_chipset_tag_t pd_gc;
|
||||
int pd_pin;
|
||||
};
|
||||
|
||||
|
||||
extern struct bus_space exynos_bs_tag;
|
||||
extern struct bus_space exynos_a4x_bs_tag;
|
||||
@ -104,10 +114,29 @@ extern struct arm32_bus_dma_tag exynos_coherent_bus_dma_tag;
|
||||
extern bus_space_handle_t exynos_core_bsh;
|
||||
|
||||
extern void exynos_bootstrap(vaddr_t, vaddr_t);
|
||||
extern void exynos_dma_bootstrap(psize_t memsize);
|
||||
extern void exynos_gpio_bootstrap(void);
|
||||
|
||||
extern void exynos_device_register(device_t self, void *aux);
|
||||
extern void exyo_device_register(device_t self, void *aux);
|
||||
extern void exynos_wdt_reset(void);
|
||||
extern void exynos_dma_bootstrap(psize_t memsize);
|
||||
|
||||
extern bool exynos_gpio_pinset_available(const struct exynos_gpio_pinset *);
|
||||
extern void exynos_gpio_pinset_acquire(const struct exynos_gpio_pinset *);
|
||||
extern void exynos_gpio_pinset_release(const struct exynos_gpio_pinset *);
|
||||
extern bool exynos_gpio_pin_reserve(const char *, struct exynos_gpio_pindata *);
|
||||
|
||||
static inline void
|
||||
exynos_gpio_pindata_write(const struct exynos_gpio_pindata *pd, int value)
|
||||
{
|
||||
gpiobus_pin_write(pd->pd_gc, pd->pd_pin, value);
|
||||
}
|
||||
|
||||
static inline int
|
||||
exynos_gpio_pindata_read(const struct exynos_gpio_pindata *pd)
|
||||
{
|
||||
return gpiobus_pin_read(pd->pd_gc, pd->pd_pin);
|
||||
}
|
||||
|
||||
|
||||
#ifdef ARM_TRUSTZONE_FIRMWARE
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: files.exynos,v 1.5 2014/05/05 20:31:03 reinoud Exp $
|
||||
# $NetBSD: files.exynos,v 1.6 2014/05/09 21:49:43 reinoud Exp $
|
||||
#
|
||||
# Configuration info for Samsung Exynos SoC ARM Peripherals
|
||||
#
|
||||
@ -45,7 +45,7 @@ defflag opt_exynos.h EXYNOS5440: EXYNOS5
|
||||
defflag opt_exynos.h EXYNOS5422: EXYNOS5
|
||||
|
||||
# SoC I/O attach point
|
||||
device exyo { [port=-1] } : bus_space_generic
|
||||
device exyo { [port=-1], [intr=-1] } : bus_space_generic
|
||||
attach exyo at mainbus with exyo_io
|
||||
file arch/arm/samsung/exynos_io.c exyo_io
|
||||
file arch/arm/samsung/exynos4_loc.c exyo_io & exynos4
|
||||
@ -69,6 +69,11 @@ file arch/arm/samsung/exynos_sscom.c exynos_sscom
|
||||
defflag opt_sscom.h SSCOM0CONSOLE SSCOM1CONSOLE
|
||||
defparam opt_sscom.h SSCOM_FREQ
|
||||
|
||||
# GPIO
|
||||
device exyogpio : gpiobus
|
||||
attach exyogpio at exyo with exynos_gpio
|
||||
file arch/arm/samsung/exynos_gpio.c exynos_gpio | exyo_io needs-flag
|
||||
|
||||
# USB2 Host Controller (EHCI/OHCI)
|
||||
device exyousb { }
|
||||
attach exyousb at exyo with exyo_usb
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# $NetBSD: ODROID-U,v 1.4 2014/05/05 20:31:03 reinoud Exp $
|
||||
# $NetBSD: ODROID-U,v 1.5 2014/05/09 21:49:43 reinoud Exp $
|
||||
#
|
||||
# ODROID-U -- ODROID-U series Exynos Kernel
|
||||
#
|
||||
@ -192,6 +192,10 @@ sscom1 at exyo0 port 1 # UART1
|
||||
# Exynos Watchdog Timer
|
||||
exyowdt0 at exyo0 flags 1 # watchdog
|
||||
|
||||
# GPIO
|
||||
exyogpio0 at exyo0
|
||||
gpio* at exyogpio?
|
||||
|
||||
# On-board USB
|
||||
exyousb* at exyo0
|
||||
ohci* at exyousb?
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: odroid_machdep.c,v 1.8 2014/04/19 19:47:55 matt Exp $ */
|
||||
/* $NetBSD: odroid_machdep.c,v 1.9 2014/05/09 21:49:43 reinoud Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014 The NetBSD Foundation, Inc.
|
||||
@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: odroid_machdep.c,v 1.8 2014/04/19 19:47:55 matt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: odroid_machdep.c,v 1.9 2014/05/09 21:49:43 reinoud Exp $");
|
||||
|
||||
#include "opt_evbarm_boardtype.h"
|
||||
#include "opt_exynos.h"
|
||||
@ -469,6 +469,75 @@ consinit(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef EXYNOS4
|
||||
static void
|
||||
odroid_exynos4_gpio_ncs(device_t self, prop_dictionary_t dict) {
|
||||
/*
|
||||
* These pins have no connections; the 1st is a raw values that is
|
||||
* generated by the gpio bootstrap and the values substracted are
|
||||
* explicitly allowed
|
||||
*/
|
||||
prop_dictionary_set_uint32(dict, "nc-GPA0", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPA1", 0x3f - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPB", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPC0", 0x1f - 0x00);
|
||||
/* blue led at bit 0 : */
|
||||
prop_dictionary_set_uint32(dict, "nc-GPC1", 0x1f - 0x01);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPD0", 0x0f - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPD1", 0x0f - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPF0", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPF1", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPF2", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPF3", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPJ0", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPJ1", 0x1f - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPK0", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPK1", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPK2", 0x7f - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPK3", 0x7f - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPL0", 0x7f - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPL1", 0x03 - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPL2", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPY0", 0x3f - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPY1", 0x0f - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPY2", 0x3f - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPY3", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPY4", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPY5", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPY6", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPM0", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPM1", 0x7f - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPM2", 0x1f - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPM3", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPM4", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPX0", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPX1", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPX2", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPX3", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPZ", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPV0", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPV1", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPV2", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPV3", 0xff - 0x00);
|
||||
prop_dictionary_set_uint32(dict, "nc-GPV4", 0x03 - 0x00);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef EXYNOS5
|
||||
static void
|
||||
odroid_exynos5_gpio_ncs(device_t self, prop_dictionary_t dict) {
|
||||
/*
|
||||
* These pins have no connections; the 1st is a raw values that is
|
||||
* generated by the gpio bootstrap and the values substracted are
|
||||
* explicitly allowed
|
||||
*/
|
||||
/* TBD: generate these values, see exynos_gpio.c boostrap */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
odroid_device_register(device_t self, void *aux)
|
||||
{
|
||||
@ -480,5 +549,26 @@ odroid_device_register(device_t self, void *aux)
|
||||
if (use_fb_console)
|
||||
prop_dictionary_set_bool(dict, "is_console", false);
|
||||
}
|
||||
|
||||
if (device_is_a(self, "mct"))
|
||||
prop_dictionary_set_cstring(dict, "blinkled", "led0");
|
||||
|
||||
if (device_is_a(self, "exyogpio")) {
|
||||
#ifdef EXYNOS4
|
||||
if (IS_EXYNOS4_P()) {
|
||||
/* unused bits */
|
||||
odroid_exynos4_gpio_ncs(self, dict);
|
||||
/* explicit pin settings */
|
||||
prop_dictionary_set_cstring(dict, "led0", ">GPC1[0]");
|
||||
}
|
||||
#endif
|
||||
#ifdef EXYNOS5
|
||||
if (IS_EXYNOS5_P()) {
|
||||
/* unused bits */
|
||||
odroid_exynos5_gpio_ncs(self, dict);
|
||||
/* explicit pin settings */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user