Home | History | Annotate | Line # | Download | only in samsung
exynos_gpio.c revision 1.13
      1  1.13    marty /*	$NetBSD: exynos_gpio.c,v 1.13 2015/12/11 04:03:44 marty Exp $ */
      2   1.9    skrll 
      3   1.1  reinoud /*-
      4   1.1  reinoud * Copyright (c) 2014 The NetBSD Foundation, Inc.
      5   1.1  reinoud * All rights reserved.
      6   1.1  reinoud *
      7   1.1  reinoud * This code is derived from software contributed to The NetBSD Foundation
      8   1.1  reinoud * by Reinoud Zandijk
      9   1.1  reinoud *
     10   1.1  reinoud * Redistribution and use in source and binary forms, with or without
     11   1.1  reinoud * modification, are permitted provided that the following conditions
     12   1.1  reinoud * are met:
     13   1.1  reinoud * 1. Redistributions of source code must retain the above copyright
     14   1.1  reinoud *    notice, this list of conditions and the following disclaimer.
     15   1.1  reinoud * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1  reinoud *    notice, this list of conditions and the following disclaimer in the
     17   1.1  reinoud *    documentation and/or other materials provided with the distribution.
     18   1.1  reinoud *
     19   1.1  reinoud * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.1  reinoud * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.1  reinoud * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.1  reinoud * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.1  reinoud * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.1  reinoud * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.1  reinoud * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.1  reinoud * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.1  reinoud * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.1  reinoud * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.1  reinoud * POSSIBILITY OF SUCH DAMAGE.
     30   1.1  reinoud */
     31   1.1  reinoud 
     32   1.1  reinoud #include "opt_exynos.h"
     33   1.1  reinoud #include "opt_arm_debug.h"
     34   1.1  reinoud #include "gpio.h"
     35   1.1  reinoud 
     36   1.1  reinoud #include <sys/cdefs.h>
     37  1.13    marty __KERNEL_RCSID(1, "$NetBSD: exynos_gpio.c,v 1.13 2015/12/11 04:03:44 marty Exp $");
     38   1.1  reinoud 
     39   1.1  reinoud #include <sys/param.h>
     40   1.1  reinoud #include <sys/bus.h>
     41   1.1  reinoud #include <sys/device.h>
     42   1.1  reinoud #include <sys/intr.h>
     43   1.1  reinoud #include <sys/systm.h>
     44   1.1  reinoud #include <sys/kmem.h>
     45  1.13    marty #include <sys/gpio.h>
     46  1.13    marty 
     47  1.13    marty #include <dev/gpio/gpiovar.h>
     48   1.1  reinoud 
     49   1.1  reinoud #include <arm/samsung/exynos_reg.h>
     50   1.1  reinoud #include <arm/samsung/exynos_io.h>
     51   1.1  reinoud #include <arm/samsung/exynos_intr.h>
     52   1.1  reinoud 
     53   1.1  reinoud struct exynos_gpio_pin_cfg {
     54   1.1  reinoud 	uint32_t cfg;
     55   1.1  reinoud 	uint32_t pud;
     56   1.1  reinoud 	uint32_t drv;
     57   1.1  reinoud 	uint32_t conpwd;
     58   1.1  reinoud 	uint32_t pudpwd;
     59   1.1  reinoud };
     60   1.1  reinoud 
     61  1.13    marty struct exynos_gpio_softc;
     62  1.13    marty 
     63  1.13    marty struct exynos_gpio_bank {
     64  1.13    marty 	const char		bank_name[6];
     65  1.13    marty 	struct exynos_gpio_softc *bank_sc;
     66  1.13    marty 	device_t		bank_dev;
     67  1.13    marty 	struct gpio_chipset_tag	bank_gc;
     68  1.13    marty 	gpio_pin_t		bank_pins[8];
     69  1.13    marty 
     70  1.13    marty 	const bus_addr_t	bank_core_offset;
     71  1.13    marty 	const uint8_t		bank_bits;
     72  1.13    marty 
     73  1.13    marty 	uint8_t			bank_pin_mask;
     74  1.13    marty 	uint8_t			bank_pin_inuse_mask;
     75  1.13    marty 	bus_space_handle_t	bank_bsh;
     76  1.13    marty 	struct exynos_gpio_pin_cfg bank_cfg;
     77   1.1  reinoud };
     78   1.1  reinoud 
     79  1.13    marty struct exynos_gpio_softc {
     80  1.13    marty 	device_t		sc_dev;
     81  1.13    marty 	bus_space_tag_t		sc_bst;
     82  1.13    marty 	bus_space_handle_t	sc_bsh;
     83   1.1  reinoud 
     84  1.13    marty 	struct exynos_gpio_bank *sc_banks;
     85  1.13    marty };
     86   1.1  reinoud 
     87  1.13    marty struct exynos_gpio_pin {
     88  1.13    marty 	struct exynos_gpio_softc *pin_sc;
     89  1.13    marty 	const struct exynos_gpio_bank  *pin_bank;
     90  1.13    marty 	int			  pin_no;
     91  1.13    marty 	u_int			  pin_flags;
     92   1.1  reinoud };
     93   1.1  reinoud 
     94  1.13    marty #define GPIO_REG(v,s,o) (EXYNOS##v##_GPIO_##s##_OFFSET + (o))
     95  1.13    marty #define GPIO_GRP(v, s, o, n, b)	\
     96  1.13    marty 	{ \
     97  1.13    marty 		.bank_name = #n, \
     98  1.13    marty 		.bank_core_offset = GPIO_REG(v,s,o), \
     99  1.13    marty 		.bank_bits = b, \
    100  1.13    marty 	}
    101  1.13    marty 
    102  1.13    marty static struct exynos_gpio_bank exynos5_banks[] = {
    103  1.13    marty 	GPIO_GRP(5, MUXA, 0x0000, gpy7, 8),
    104  1.13    marty 	GPIO_GRP(5, MUXA, 0x0C00, gpx0, 8),
    105  1.13    marty 	GPIO_GRP(5, MUXA, 0x0C20, gpx1, 8),
    106  1.13    marty 	GPIO_GRP(5, MUXA, 0x0C40, gpx2, 8),
    107  1.13    marty 	GPIO_GRP(5, MUXA, 0x0C60, gpx3, 8),
    108  1.13    marty 
    109  1.13    marty 	GPIO_GRP(5, MUXB, 0x0000, gpc0, 8),
    110  1.13    marty 	GPIO_GRP(5, MUXB, 0x0020, gpc1, 8),
    111  1.13    marty 	GPIO_GRP(5, MUXB, 0x0040, gpc2, 7),
    112  1.13    marty 	GPIO_GRP(5, MUXB, 0x0060, gpc3, 4),
    113  1.13    marty 	GPIO_GRP(5, MUXB, 0x0080, gpc4, 2),
    114  1.13    marty 	GPIO_GRP(5, MUXB, 0x00A0, gpd1, 8),
    115  1.13    marty 	GPIO_GRP(5, MUXB, 0x00C0, gpy0, 6),
    116  1.13    marty 	GPIO_GRP(5, MUXB, 0x00E0, gpy1, 4),
    117  1.13    marty 	GPIO_GRP(5, MUXB, 0x0100, gpy2, 6),
    118  1.13    marty 	GPIO_GRP(5, MUXB, 0x0120, gpy3, 8),
    119  1.13    marty 	GPIO_GRP(5, MUXB, 0x0140, gpy4, 8),
    120  1.13    marty 	GPIO_GRP(5, MUXB, 0x0160, gpy5, 8),
    121  1.13    marty 	GPIO_GRP(5, MUXB, 0x0180, gpy6, 8),
    122  1.13    marty 
    123  1.13    marty 	GPIO_GRP(5, MUXC, 0x0000, gpe0, 8),
    124  1.13    marty 	GPIO_GRP(5, MUXC, 0x0020, gpe1, 2),
    125  1.13    marty 	GPIO_GRP(5, MUXC, 0x0040, gpf0, 6),
    126  1.13    marty 	GPIO_GRP(5, MUXC, 0x0060, gpf1, 8),
    127  1.13    marty 	GPIO_GRP(5, MUXC, 0x0080, gpg0, 8),
    128  1.13    marty 	GPIO_GRP(5, MUXC, 0x00A0, gpg1, 8),
    129  1.13    marty 	GPIO_GRP(5, MUXC, 0x00C0, gpg2, 2),
    130  1.13    marty 	GPIO_GRP(5, MUXC, 0x00E0, gpj4, 4),
    131  1.13    marty 
    132  1.13    marty 	GPIO_GRP(5, MUXD, 0x0000, gpa0, 8),
    133  1.13    marty 	GPIO_GRP(5, MUXD, 0x0020, gpa1, 6),
    134  1.13    marty 	GPIO_GRP(5, MUXD, 0x0040, gpa2, 8),
    135  1.13    marty 	GPIO_GRP(5, MUXD, 0x0060, gpb0, 5),
    136  1.13    marty 	GPIO_GRP(5, MUXD, 0x0080, gpb1, 5),
    137  1.13    marty 	GPIO_GRP(5, MUXD, 0x00A0, gpb2, 4),
    138  1.13    marty 	GPIO_GRP(5, MUXD, 0x00C0, gpb3, 8),
    139  1.13    marty 	GPIO_GRP(5, MUXD, 0x00E0, gpb4, 2),
    140  1.13    marty 	GPIO_GRP(5, MUXD, 0x0100, gph0, 4),
    141   1.1  reinoud 
    142  1.13    marty //	GPIO_GRP(5, MUXE, 0x0000, gpz0,  7),
    143   1.1  reinoud };
    144   1.1  reinoud 
    145  1.13    marty static int exynos_gpio_match(device_t, cfdata_t, void *);
    146  1.13    marty static void exynos_gpio_attach(device_t, device_t, void *);
    147   1.1  reinoud 
    148  1.13    marty static int exynos_gpio_pin_read(void *, int);
    149  1.13    marty static void exynos_gpio_pin_write(void *, int, int);
    150  1.13    marty static void exynos_gpio_pin_ctl(void *, int, int);
    151  1.13    marty static int exynos_gpio_cfprint(void *, const char *);
    152  1.13    marty struct exynos_gpio_pin *exynos_gpio_acquire(const char *pinname, u_int flags);
    153   1.1  reinoud 
    154   1.1  reinoud /* force these structures in DATA segment */
    155  1.13    marty static struct exynos_gpio_bank *exynos_gpio_banks = NULL;
    156  1.13    marty static int exynos_n_gpio_banks = 0;
    157   1.1  reinoud 
    158   1.1  reinoud static struct exynos_gpio_softc exynos_gpio_sc = {};
    159   1.1  reinoud 
    160   1.1  reinoud CFATTACH_DECL_NEW(exynos_gpio, sizeof(struct exynos_gpio_softc),
    161   1.1  reinoud 	exynos_gpio_match, exynos_gpio_attach, NULL, NULL);
    162   1.1  reinoud 
    163   1.1  reinoud static int
    164   1.1  reinoud exynos_gpio_match(device_t parent, cfdata_t cf, void *aux)
    165   1.1  reinoud {
    166   1.8  reinoud #ifdef DIAGNOSTIC
    167   1.1  reinoud 	struct exyo_attach_args * const exyoaa = aux;
    168   1.1  reinoud 	struct exyo_locators *loc = &exyoaa->exyo_loc;
    169   1.8  reinoud #endif
    170   1.1  reinoud 
    171   1.1  reinoud 	/* no locators expected */
    172   1.1  reinoud 	KASSERT(loc->loc_offset == 0);
    173   1.1  reinoud 	KASSERT(loc->loc_size   == 0);
    174   1.1  reinoud 	KASSERT(loc->loc_port   == EXYOCF_PORT_DEFAULT);
    175   1.1  reinoud 
    176   1.1  reinoud 	/* there can only be one */
    177   1.1  reinoud 	if (exynos_gpio_sc.sc_dev != NULL)
    178   1.1  reinoud 		return 0;
    179   1.1  reinoud 	return 1;
    180   1.1  reinoud }
    181   1.1  reinoud 
    182   1.1  reinoud 
    183   1.1  reinoud #if NGPIO > 0
    184   1.1  reinoud static void
    185  1.13    marty exynos_gpio_attach_banks(device_t self)
    186   1.1  reinoud {
    187   1.1  reinoud 	struct exynos_gpio_softc * const sc = &exynos_gpio_sc;
    188  1.13    marty 	struct exynos_gpio_bank *bank;
    189   1.1  reinoud 	struct gpiobus_attach_args gba;
    190   1.1  reinoud 	size_t pin_count = 0;
    191   1.1  reinoud 	int i, bit, mask, pincaps, data;
    192   1.1  reinoud 
    193  1.13    marty 	if (exynos_n_gpio_banks == 0)
    194   1.4  reinoud 		return;
    195   1.4  reinoud 
    196   1.1  reinoud 	/* find out how many pins we can offer */
    197   1.1  reinoud 	pin_count = 0;
    198  1.13    marty 	for (i = 0; i < exynos_n_gpio_banks; i++) {
    199  1.13    marty 		pin_count += exynos_gpio_banks[i].bank_bits;
    200   1.1  reinoud 	}
    201   1.1  reinoud 
    202   1.1  reinoud 	/* if no pins available, don't proceed */
    203   1.1  reinoud 	if (pin_count == 0)
    204   1.1  reinoud 		return;
    205  1.12    skrll 
    206   1.1  reinoud 	/* allocate pin data */
    207  1.13    marty 	sc->sc_banks = exynos_gpio_banks;
    208  1.13    marty 	KASSERT(sc->sc_banks);
    209   1.1  reinoud 
    210   1.1  reinoud 	pincaps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |
    211   1.1  reinoud 		GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN;
    212   1.1  reinoud 
    213  1.13    marty 	for (i = 0; i < exynos_n_gpio_banks; i++) {
    214  1.13    marty 		bank = &sc->sc_banks[i];
    215  1.13    marty 		bank->bank_sc = sc;
    216  1.13    marty 		bank->bank_gc.gp_cookie = bank;
    217  1.13    marty 		bank->bank_gc.gp_pin_read = exynos_gpio_pin_read;
    218  1.13    marty 		bank->bank_gc.gp_pin_write = exynos_gpio_pin_write;
    219  1.13    marty 		bank->bank_gc.gp_pin_ctl = exynos_gpio_pin_ctl;
    220  1.13    marty 		mask = bank->bank_pin_mask & ~bank->bank_pin_inuse_mask;
    221   1.1  reinoud 		if (mask == 0)
    222   1.1  reinoud 			continue;
    223  1.13    marty 		data = bus_space_read_1(sc->sc_bst, bank->bank_bsh,
    224   1.1  reinoud 				EXYNOS_GPIO_DAT);
    225   1.1  reinoud 		for (bit = 0; mask != 0; mask >>= 1, data >>= 1, bit++) {
    226   1.1  reinoud 			if (mask & 1) {
    227  1.13    marty 				bank->bank_pins[bit].pin_num = bit + (i << 3);
    228  1.13    marty 				bank->bank_pins[bit].pin_caps = pincaps;
    229  1.13    marty 				bank->bank_pins[bit].pin_flags = pincaps;
    230  1.13    marty 				bank->bank_pins[bit].pin_state = (data & 1) != 0;
    231   1.1  reinoud 			}
    232   1.1  reinoud 		}
    233  1.13    marty 		memset(&gba, 0, sizeof(gba));
    234  1.13    marty 		gba.gba_gc = &bank->bank_gc;
    235  1.13    marty 		gba.gba_pins = bank->bank_pins;
    236  1.13    marty 		gba.gba_npins = bit; /* MJF? */
    237  1.13    marty 		bank->bank_dev = config_found_ia(self, "gpiobus", &gba,
    238  1.13    marty 						 exynos_gpio_cfprint);
    239   1.1  reinoud 	}
    240   1.1  reinoud }
    241   1.1  reinoud #endif
    242   1.1  reinoud 
    243  1.13    marty static int
    244  1.13    marty exynos_gpio_cfprint(void *priv, const char *pnp)
    245  1.13    marty {
    246  1.13    marty 	struct gpiobus_attach_args *gba = priv;
    247  1.13    marty 	struct exynos_gpio_bank *bank = gba->gba_gc->gp_cookie;
    248  1.13    marty 	const char *bankname = bank->bank_name;
    249  1.13    marty 
    250  1.13    marty 	if (pnp)
    251  1.13    marty 		aprint_normal("gpiobus at %s", pnp);
    252  1.13    marty 
    253  1.13    marty 	aprint_normal(" (%s)", bankname);
    254  1.13    marty 
    255  1.13    marty 	return UNCONF;
    256  1.13    marty }
    257   1.1  reinoud 
    258   1.1  reinoud static void
    259   1.1  reinoud exynos_gpio_attach(device_t parent, device_t self, void *aux)
    260   1.1  reinoud {
    261   1.1  reinoud 	struct exynos_gpio_softc * const sc = &exynos_gpio_sc;
    262   1.1  reinoud 	struct exyo_attach_args * const exyoaa = aux;
    263   1.1  reinoud 
    264   1.1  reinoud 	sc->sc_dev = self;
    265   1.1  reinoud 	sc->sc_bst = exyoaa->exyo_core_bst;
    266   1.1  reinoud 	sc->sc_bsh = exyoaa->exyo_core_bsh;
    267   1.1  reinoud 
    268   1.4  reinoud 	exynos_gpio_bootstrap();
    269  1.13    marty 	if (exynos_n_gpio_banks == 0) {
    270   1.4  reinoud 		printf(": disabled, no pins defined\n");
    271   1.4  reinoud 		return;
    272   1.4  reinoud 	}
    273   1.4  reinoud 
    274  1.13    marty 	KASSERT(exynos_gpio_banks);
    275  1.13    marty 	KASSERT(exynos_n_gpio_banks);
    276   1.4  reinoud 
    277   1.1  reinoud 	aprint_naive("\n");
    278   1.1  reinoud 	aprint_normal("\n");
    279   1.1  reinoud 
    280   1.1  reinoud #if NGPIO > 0
    281  1.13    marty 	exynos_gpio_attach_banks(self);
    282   1.1  reinoud #endif
    283   1.1  reinoud }
    284   1.1  reinoud 
    285   1.1  reinoud static void
    286   1.1  reinoud exynos_gpio_set_pin_func(struct exynos_gpio_pin_cfg *cfg,
    287   1.1  reinoud 	int pin, int func)
    288   1.1  reinoud {
    289   1.5  reinoud 	const u_int shift = (pin & 7) << 2;
    290   1.1  reinoud 
    291   1.1  reinoud 	cfg->cfg &= ~(0x0f << shift);
    292   1.1  reinoud 	cfg->cfg |= func << shift;
    293   1.1  reinoud }
    294   1.1  reinoud 
    295   1.1  reinoud 
    296   1.1  reinoud static void
    297   1.1  reinoud exynos_gpio_set_pin_pull(struct exynos_gpio_pin_cfg *cfg, int pin, int pull)
    298   1.1  reinoud {
    299   1.1  reinoud 	const u_int shift = (pin & 7) << 1;
    300   1.1  reinoud 
    301   1.1  reinoud 	cfg->pud &= ~(0x3 << shift);
    302   1.1  reinoud 	cfg->pud |= pull << shift;
    303   1.1  reinoud }
    304   1.1  reinoud 
    305   1.1  reinoud static int
    306   1.1  reinoud exynos_gpio_pin_read(void *cookie, int pin)
    307   1.1  reinoud {
    308  1.13    marty 	struct exynos_gpio_bank * const bank = cookie;
    309   1.1  reinoud 
    310  1.13    marty 	KASSERT(pin < bank->bank_bits);
    311  1.13    marty 	return (bus_space_read_1(exynos_gpio_sc.sc_bst, bank->bank_bsh,
    312   1.1  reinoud 		EXYNOS_GPIO_DAT) >> pin) & 1;
    313   1.1  reinoud }
    314   1.1  reinoud 
    315   1.1  reinoud static void
    316   1.1  reinoud exynos_gpio_pin_write(void *cookie, int pin, int value)
    317   1.1  reinoud {
    318  1.13    marty 	struct exynos_gpio_bank * const bank = cookie;
    319   1.1  reinoud 	int val;
    320   1.1  reinoud 
    321  1.13    marty 	KASSERT(pin < bank->bank_bits);
    322  1.13    marty 	val = bus_space_read_1(exynos_gpio_sc.sc_bst, bank->bank_bsh,
    323   1.1  reinoud 		EXYNOS_GPIO_DAT);
    324   1.1  reinoud 	val &= ~__BIT(pin);
    325   1.1  reinoud 	if (value)
    326   1.1  reinoud 		val |= __BIT(pin);
    327  1.13    marty 	bus_space_write_1(exynos_gpio_sc.sc_bst, bank->bank_bsh,
    328   1.1  reinoud 		EXYNOS_GPIO_DAT, val);
    329   1.1  reinoud }
    330   1.1  reinoud 
    331   1.1  reinoud static void
    332  1.13    marty exynos_gpio_update_cfg_regs(struct exynos_gpio_bank *bank,
    333   1.1  reinoud 	const struct exynos_gpio_pin_cfg *ncfg)
    334   1.1  reinoud {
    335   1.1  reinoud 	bus_space_tag_t bst = &exynos_bs_tag;
    336   1.1  reinoud 
    337  1.13    marty 	if (bank->bank_cfg.cfg != ncfg->cfg) {
    338  1.13    marty 		bus_space_write_4(bst, bank->bank_bsh,
    339   1.1  reinoud 			EXYNOS_GPIO_CON, ncfg->cfg);
    340  1.13    marty 		bank->bank_cfg.cfg = ncfg->cfg;
    341   1.1  reinoud 	}
    342  1.13    marty 	if (bank->bank_cfg.pud != ncfg->pud) {
    343  1.13    marty 		bus_space_write_4(bst, bank->bank_bsh,
    344   1.1  reinoud 			EXYNOS_GPIO_PUD, ncfg->pud);
    345  1.13    marty 		bank->bank_cfg.pud = ncfg->pud;
    346   1.1  reinoud 	}
    347   1.1  reinoud 
    348   1.1  reinoud 	/* the following attributes are not yet setable */
    349   1.1  reinoud #if 0
    350  1.13    marty 	if (bank->bank_cfg.drv != ncfg->drv) {
    351  1.13    marty 		bus_space_write_4(bst, bank->bank_bsh,
    352   1.1  reinoud 			EXYNOS_GPIO_DRV, ncfg->drv);
    353  1.13    marty 		bank->bank_cfg.drv = ncfg->drv;
    354   1.1  reinoud 	}
    355  1.13    marty 	if (bank->bank_cfg.conpwd != ncfg->conpwd) {
    356  1.13    marty 		bus_space_write_4(bst, bank->bank_bsh,
    357   1.1  reinoud 			EXYNOS_GPIO_CONPWD, ncfg->conpwd);
    358  1.13    marty 		bank->bank_cfg.conpwd = ncfg->conpwd;
    359   1.1  reinoud 	}
    360  1.13    marty 	if (bank->bank_cfg.pudpwd != ncfg->pudpwd) {
    361  1.13    marty 		bus_space_write_4(bst, bank->bank_bsh,
    362   1.1  reinoud 			EXYNOS_GPIO_PUDPWD, ncfg->pudpwd);
    363  1.13    marty 		bank->bank_cfg.pudpwd = ncfg->pudpwd;
    364   1.1  reinoud 	}
    365   1.1  reinoud #endif
    366   1.1  reinoud }
    367   1.1  reinoud 
    368   1.1  reinoud 
    369   1.1  reinoud static void
    370   1.1  reinoud exynos_gpio_pin_ctl(void *cookie, int pin, int flags)
    371   1.1  reinoud {
    372  1.13    marty 	struct exynos_gpio_bank * const bank = cookie;
    373  1.13    marty 	struct exynos_gpio_pin_cfg ncfg = bank->bank_cfg;
    374   1.1  reinoud 	int pull;
    375   1.1  reinoud 
    376   1.1  reinoud 	/* honour pullup requests */
    377   1.1  reinoud 	pull = EXYNOS_GPIO_PIN_FLOAT;
    378   1.1  reinoud 	if (flags & GPIO_PIN_PULLUP)
    379   1.1  reinoud 		pull = EXYNOS_GPIO_PIN_PULL_UP;
    380   1.1  reinoud 	if (flags & GPIO_PIN_PULLDOWN)
    381   1.1  reinoud 		pull = EXYNOS_GPIO_PIN_PULL_DOWN;
    382   1.1  reinoud 	exynos_gpio_set_pin_pull(&ncfg, pin, pull);
    383   1.1  reinoud 
    384   1.1  reinoud 	/* honour i/o */
    385   1.1  reinoud 	if (flags & GPIO_PIN_INPUT)
    386   1.1  reinoud 		exynos_gpio_set_pin_func(&ncfg, pin, EXYNOS_GPIO_FUNC_INPUT);
    387   1.1  reinoud 	if (flags & GPIO_PIN_OUTPUT)
    388   1.1  reinoud 		exynos_gpio_set_pin_func(&ncfg, pin, EXYNOS_GPIO_FUNC_OUTPUT);
    389   1.1  reinoud 
    390   1.1  reinoud 	/* update any config registers that changed */
    391  1.13    marty 	exynos_gpio_update_cfg_regs(bank, &ncfg);
    392   1.1  reinoud }
    393   1.1  reinoud 
    394   1.1  reinoud /* bootstrapping */
    395   1.1  reinoud void
    396   1.1  reinoud exynos_gpio_bootstrap(void)
    397   1.1  reinoud {
    398   1.1  reinoud 	bus_space_tag_t bst = &exynos_bs_tag;
    399  1.13    marty 	struct exynos_gpio_bank *bank;
    400   1.1  reinoud 	struct gpio_chipset_tag *gc_tag;
    401   1.5  reinoud 	int i;
    402   1.1  reinoud 
    403   1.1  reinoud 	/* determine what we're running on */
    404   1.1  reinoud 	if (IS_EXYNOS5_P()) {
    405  1.13    marty 		exynos_gpio_banks = exynos5_banks;
    406  1.13    marty 		exynos_n_gpio_banks = __arraycount(exynos5_banks);
    407   1.1  reinoud 	}
    408   1.1  reinoud 
    409  1.13    marty 	if (exynos_n_gpio_banks == 0)
    410   1.1  reinoud 		return;
    411   1.1  reinoud 
    412  1.13    marty 	/* init banks */
    413  1.13    marty 	for (i = 0; i < exynos_n_gpio_banks; i++) {
    414  1.13    marty 		bank = &exynos_gpio_banks[i];
    415  1.13    marty 		gc_tag = &bank->bank_gc;
    416   1.1  reinoud 
    417   1.1  reinoud 		bus_space_subregion(&exynos_bs_tag, exynos_core_bsh,
    418  1.13    marty 			bank->bank_core_offset, EXYNOS_GPIO_GRP_SIZE,
    419  1.13    marty 			&bank->bank_bsh);
    420  1.13    marty 		KASSERT(&bank->bank_bsh);
    421   1.4  reinoud 
    422  1.13    marty 		bank->bank_pin_mask = __BIT(bank->bank_bits) - 1;
    423  1.13    marty 		bank->bank_pin_inuse_mask = 0;
    424   1.1  reinoud 
    425  1.13    marty 		gc_tag->gp_cookie = bank;
    426   1.1  reinoud 		gc_tag->gp_pin_read  = exynos_gpio_pin_read;
    427   1.1  reinoud 		gc_tag->gp_pin_write = exynos_gpio_pin_write;
    428   1.1  reinoud 		gc_tag->gp_pin_ctl   = exynos_gpio_pin_ctl;
    429   1.1  reinoud 
    430   1.1  reinoud 		/* read in our initial settings */
    431  1.13    marty 		bank->bank_cfg.cfg = bus_space_read_4(bst, bank->bank_bsh,
    432   1.1  reinoud 			EXYNOS_GPIO_CON);
    433  1.13    marty 		bank->bank_cfg.pud = bus_space_read_4(bst, bank->bank_bsh,
    434   1.1  reinoud 			EXYNOS_GPIO_PUD);
    435  1.13    marty 		bank->bank_cfg.drv = bus_space_read_4(bst, bank->bank_bsh,
    436   1.1  reinoud 			EXYNOS_GPIO_DRV);
    437  1.13    marty 		bank->bank_cfg.conpwd = bus_space_read_4(bst, bank->bank_bsh,
    438   1.1  reinoud 			EXYNOS_GPIO_CONPWD);
    439  1.13    marty 		bank->bank_cfg.pudpwd = bus_space_read_4(bst, bank->bank_bsh,
    440   1.1  reinoud 			EXYNOS_GPIO_PUDPWD);
    441  1.13    marty 	}
    442  1.13    marty 
    443  1.13    marty }
    444   1.1  reinoud 
    445  1.13    marty /*
    446  1.13    marty  * pinmame = gpLD-N
    447  1.13    marty  *     L = 'a' - 'z' -+
    448  1.13    marty  *     D = '0' - '8' -+ ===== bank name
    449  1.13    marty  *     N = '0' - '8'    ===== pin number
    450  1.13    marty  */
    451  1.13    marty 
    452  1.13    marty static const struct exynos_gpio_bank *
    453  1.13    marty exynos_gpio_pin_lookup(const char *pinname, int *ppin)
    454  1.13    marty {
    455  1.13    marty 	char bankname[5];
    456  1.13    marty 	u_int n;
    457  1.13    marty 	int pin;
    458  1.13    marty 
    459  1.13    marty 	KASSERT(strlen(pinname) == 2 || strlen(pinname) == 3);
    460  1.13    marty 
    461  1.13    marty 	memset(bankname, 0, sizeof(bankname));
    462  1.13    marty 	bankname[0] = pinname[0]; /* 'g' */
    463  1.13    marty 	bankname[1] = pinname[1]; /* 'p' */
    464  1.13    marty 	bankname[2] = pinname[2]; /*  L  */
    465  1.13    marty 	bankname[3] = pinname[3]; /*  D  */
    466  1.13    marty 	pin = pinname[5] - '0';	  /* skip the '-' */
    467  1.13    marty 
    468  1.13    marty 	for (n = 0; n < __arraycount(exynos_gpio_banks); n++) {
    469  1.13    marty 		const struct exynos_gpio_bank *pb =
    470  1.13    marty 		    &exynos_gpio_banks[n];
    471  1.13    marty 		if (strcmp(pb->bank_name, bankname) == 0) {
    472  1.13    marty 			*ppin = pin;
    473  1.13    marty 			return pb;
    474   1.1  reinoud 		}
    475   1.1  reinoud 	}
    476  1.13    marty 
    477  1.13    marty 	return NULL;
    478   1.1  reinoud }
    479   1.1  reinoud 
    480  1.13    marty struct exynos_gpio_pin *
    481  1.13    marty exynos_gpio_acquire(const char *pinname, u_int flags)
    482  1.13    marty {
    483  1.13    marty 	const struct exynos_gpio_bank *bank;
    484  1.13    marty 	struct exynos_gpio_pin *gpin;
    485  1.13    marty 	int pin;
    486  1.13    marty 
    487  1.13    marty 	bank = exynos_gpio_pin_lookup(pinname, &pin);
    488  1.13    marty 	if (bank == NULL)
    489  1.13    marty 		return NULL;
    490  1.13    marty 
    491  1.13    marty 	gpin = kmem_alloc(sizeof(*gpin), KM_SLEEP);
    492  1.13    marty 	gpin->pin_sc = bank->bank_sc;
    493  1.13    marty 	gpin->pin_bank = bank;
    494  1.13    marty 	gpin->pin_no = pin;
    495  1.13    marty 	gpin->pin_flags = flags;
    496  1.13    marty 
    497  1.13    marty 	exynos_gpio_pin_ctl(&gpin->pin_bank, gpin->pin_no, gpin->pin_flags);
    498  1.13    marty 
    499  1.13    marty 	return gpin;
    500  1.13    marty }
    501