Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch Implement gpio framework for the Samsung Exynos ser...



details:   https://anonhg.NetBSD.org/src/rev/bc1e59adb2b4
branches:  trunk
changeset: 329124:bc1e59adb2b4
user:      reinoud <reinoud%NetBSD.org@localhost>
date:      Fri May 09 21:49:43 2014 +0000

description:
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.

diffstat:

 sys/arch/arm/samsung/exynos4_loc.c      |    1 +
 sys/arch/arm/samsung/exynos_gpio.c      |  791 ++++++++++++++++++++++++++++++++
 sys/arch/arm/samsung/exynos_soc.c       |    7 +-
 sys/arch/arm/samsung/exynos_var.h       |   37 +-
 sys/arch/arm/samsung/files.exynos       |    9 +-
 sys/arch/evbarm/conf/ODROID-U           |    6 +-
 sys/arch/evbarm/odroid/odroid_machdep.c |   94 +++-
 7 files changed, 934 insertions(+), 11 deletions(-)

diffs (truncated from 1076 to 300 lines):

diff -r 980ca32e6922 -r bc1e59adb2b4 sys/arch/arm/samsung/exynos4_loc.c
--- a/sys/arch/arm/samsung/exynos4_loc.c        Fri May 09 20:10:49 2014 +0000
+++ b/sys/arch/arm/samsung/exynos4_loc.c        Fri May 09 21:49:43 2014 +0000
@@ -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 },
diff -r 980ca32e6922 -r bc1e59adb2b4 sys/arch/arm/samsung/exynos_gpio.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/samsung/exynos_gpio.c        Fri May 09 21:49:43 2014 +0000
@@ -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;



Home | Main Index | Thread Index | Old Index