Module Name: src Committed By: marty Date: Wed Dec 30 04:30:27 UTC 2015
Modified Files: src/sys/arch/arm/samsung: exynos_combiner.c exynos_gpio.c exynos_i2c.c exynos_pinctrl.c exynos_var.h Log Message: XU4 i2c, gpio & pinctrl changes modify exynos_gpio.c to support the new pinctrl model. set up the new pinctrl model in exynos_pinctrl.c Flesh out exynos_i2c.c and set it up to use the new pinctrl model. NOTE: exynos_i2c.c is still incomplete. I need to figure out what to set the prescaler and scaler to. To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/samsung/exynos_combiner.c cvs rdiff -u -r1.21 -r1.22 src/sys/arch/arm/samsung/exynos_gpio.c cvs rdiff -u -r1.8 -r1.9 src/sys/arch/arm/samsung/exynos_i2c.c cvs rdiff -u -r1.7 -r1.8 src/sys/arch/arm/samsung/exynos_pinctrl.c cvs rdiff -u -r1.22 -r1.23 src/sys/arch/arm/samsung/exynos_var.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/samsung/exynos_combiner.c diff -u src/sys/arch/arm/samsung/exynos_combiner.c:1.3 src/sys/arch/arm/samsung/exynos_combiner.c:1.4 --- src/sys/arch/arm/samsung/exynos_combiner.c:1.3 Thu Dec 24 21:20:17 2015 +++ src/sys/arch/arm/samsung/exynos_combiner.c Wed Dec 30 04:30:27 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: exynos_combiner.c,v 1.3 2015/12/24 21:20:17 marty Exp $ */ +/* $NetBSD: exynos_combiner.c,v 1.4 2015/12/30 04:30:27 marty Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ #include "gpio.h" #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: exynos_combiner.c,v 1.3 2015/12/24 21:20:17 marty Exp $"); +__KERNEL_RCSID(1, "$NetBSD: exynos_combiner.c,v 1.4 2015/12/30 04:30:27 marty Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -197,7 +197,7 @@ exynos_combiner_intrstr(device_t dev, in kmem_free(interrupts, len); - snprintf(buf, buflen, "LIC irq %d", irq); + snprintf(buf, buflen, "combiner irq %d", irq); return true; } Index: src/sys/arch/arm/samsung/exynos_gpio.c diff -u src/sys/arch/arm/samsung/exynos_gpio.c:1.21 src/sys/arch/arm/samsung/exynos_gpio.c:1.22 --- src/sys/arch/arm/samsung/exynos_gpio.c:1.21 Sun Dec 27 12:42:14 2015 +++ src/sys/arch/arm/samsung/exynos_gpio.c Wed Dec 30 04:30:27 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: exynos_gpio.c,v 1.21 2015/12/27 12:42:14 jmcneill Exp $ */ +/* $NetBSD: exynos_gpio.c,v 1.22 2015/12/30 04:30:27 marty Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ #include "gpio.h" #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: exynos_gpio.c,v 1.21 2015/12/27 12:42:14 jmcneill Exp $"); +__KERNEL_RCSID(1, "$NetBSD: exynos_gpio.c,v 1.22 2015/12/30 04:30:27 marty Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -53,16 +53,6 @@ __KERNEL_RCSID(1, "$NetBSD: exynos_gpio. #include <dev/fdt/fdtvar.h> -struct exynos_gpio_pin_cfg { - uint32_t cfg; - uint32_t pud; - uint32_t drv; - uint32_t conpwd; - uint32_t pudpwd; -}; - -struct exynos_gpio_softc; - struct exynos_gpio_bank { const char bank_name[6]; device_t bank_dev; @@ -80,12 +70,6 @@ struct exynos_gpio_bank { struct exynos_gpio_bank * bank_next; }; -struct exynos_gpio_softc { - device_t sc_dev; - bus_space_tag_t sc_bst; - bus_space_handle_t sc_bsh; -}; - struct exynos_gpio_pin { struct exynos_gpio_softc *pin_sc; int pin_no; @@ -144,7 +128,7 @@ static struct exynos_gpio_bank exynos5_b GPIO_GRP(5, MUXD, 0x00E0, gpb4, 2), GPIO_GRP(5, MUXD, 0x0100, gph0, 4), - GPIO_GRP(5, MUXE, 0x0000, gpz0, 7), + GPIO_GRP(5, MUXE, 0x0000, gpz, 7), }; @@ -159,7 +143,6 @@ static void exynos_gpio_fdt_release(devi static int exynos_gpio_fdt_read(device_t, void *, bool); static void exynos_gpio_fdt_write(device_t, void *, int, bool); -static struct exynos_gpio_bank *exynos_gpio_bank_lookup(const char *); static int exynos_gpio_cfprint(void *, const char *); struct fdtbus_gpio_controller_func exynos_gpio_funcs = { @@ -279,7 +262,27 @@ exynos_gpio_pin_ctl(void *cookie, int pi exynos_gpio_update_cfg_regs(bank, &ncfg); } -void +void exynos_gpio_pin_ctl_read(const struct exynos_gpio_bank *bank, + struct exynos_gpio_pin_cfg *cfg) +{ + cfg->cfg = GPIO_READ(bank, EXYNOS_GPIO_CON); + cfg->pud = GPIO_READ(bank, EXYNOS_GPIO_PUD); + cfg->drv = GPIO_READ(bank, EXYNOS_GPIO_DRV); + cfg->conpwd = GPIO_READ(bank, EXYNOS_GPIO_CONPWD); + cfg->pudpwd = GPIO_READ(bank, EXYNOS_GPIO_PUDPWD); +} + +void exynos_gpio_pin_ctl_write(const struct exynos_gpio_bank *bank, + const struct exynos_gpio_pin_cfg *cfg) +{ + GPIO_WRITE(bank, EXYNOS_GPIO_CON, cfg->cfg); + GPIO_WRITE(bank, EXYNOS_GPIO_PUD, cfg->pud); + GPIO_WRITE(bank, EXYNOS_GPIO_DRV, cfg->drv); + GPIO_WRITE(bank, EXYNOS_GPIO_CONPWD, cfg->conpwd); + GPIO_WRITE(bank, EXYNOS_GPIO_PUDPWD, cfg->pudpwd); +} + +struct exynos_gpio_softc * exynos_gpio_bank_config(struct exynos_pinctrl_softc * parent, const struct fdt_attach_args *faa, int node) { @@ -294,13 +297,14 @@ exynos_gpio_bank_config(struct exynos_pi if (bank == NULL) { aprint_error_dev(parent->sc_dev, "no bank found for %s\n", result); - return; + return NULL; } sc->sc_dev = parent->sc_dev; sc->sc_bst = &armv7_generic_bs_tag; sc->sc_bsh = parent->sc_bsh; - + sc->sc_bank = bank; + gc_tag = &bank->bank_gc; gc_tag->gp_cookie = bank; gc_tag->gp_pin_read = exynos_gpio_pin_read; @@ -327,14 +331,23 @@ exynos_gpio_bank_config(struct exynos_pi fdtbus_register_gpio_controller(bank->bank_dev, node, &exynos_gpio_funcs); + return sc; } -static struct exynos_gpio_bank * +/* + * This function is a bit funky. Given a string that may look like + * 'gpAN' or 'gpAN-P' it is meant to find a match to the part before + * the '-', or the four character string if the dash is not present. + */ +struct exynos_gpio_bank * exynos_gpio_bank_lookup(const char *name) { + struct exynos_gpio_bank *bank; + for (u_int n = 0; n < __arraycount(exynos5_banks); n++) { - struct exynos_gpio_bank *bank = &exynos_gpio_banks[n]; - if (strncmp(bank->bank_name, name, strlen(name)) == 0) { + bank = &exynos_gpio_banks[n]; + if (!strncmp(bank->bank_name, name, + strlen(bank->bank_name))) { return bank; } } Index: src/sys/arch/arm/samsung/exynos_i2c.c diff -u src/sys/arch/arm/samsung/exynos_i2c.c:1.8 src/sys/arch/arm/samsung/exynos_i2c.c:1.9 --- src/sys/arch/arm/samsung/exynos_i2c.c:1.8 Thu Dec 24 21:30:05 2015 +++ src/sys/arch/arm/samsung/exynos_i2c.c Wed Dec 30 04:30:27 2015 @@ -1,12 +1,9 @@ -/* $NetBSD: exynos_i2c.c,v 1.8 2015/12/24 21:30:05 marty Exp $ */ +/* $NetBSD: exynos_i2c.c,v 1.9 2015/12/30 04:30:27 marty Exp $ */ /* - * Copyright (c) 2014 The NetBSD Foundation, Inc. + * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca> * 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: @@ -34,16 +31,18 @@ #include "opt_arm_debug.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: exynos_i2c.c,v 1.8 2015/12/24 21:30:05 marty Exp $"); +__KERNEL_RCSID(0, "$NetBSD: exynos_i2c.c,v 1.9 2015/12/30 04:30:27 marty Exp $"); #include <sys/param.h> #include <sys/bus.h> #include <sys/device.h> #include <sys/intr.h> #include <sys/systm.h> +#include <sys/kernel.h> #include <sys/kmem.h> #include <arm/samsung/exynos_reg.h> +#include <arm/samsung/exynos_var.h> #include <arm/samsung/exynos_intr.h> #include <sys/gpio.h> @@ -59,19 +58,18 @@ struct exynos_i2c_softc { bus_space_tag_t sc_bst; bus_space_handle_t sc_bsh; void * sc_ih; - u_int sc_port; + struct clk * sc_clk; - struct fdtbus_gpio_pin *sc_sda; - struct fdtbus_gpio_pin *sc_scl; + struct fdtbus_pinctrl_pin *sc_sda; + struct fdtbus_pinctrl_pin *sc_scl; bool sc_sda_is_output; + struct i2c_controller sc_ic; kmutex_t sc_lock; kcondvar_t sc_cv; device_t sc_i2cdev; }; -static u_int i2c_port; - static int exynos_i2c_intr(void *); static int exynos_i2c_acquire_bus(void *, int); @@ -83,22 +81,46 @@ static int exynos_i2c_initiate_xfer(void static int exynos_i2c_read_byte(void *, uint8_t *, int); static int exynos_i2c_write_byte(void *, uint8_t , int); -static bool exynos_i2c_attach_i2cbus(struct exynos_i2c_softc *, - struct i2c_controller *); +static int exynos_i2c_wait(struct exynos_i2c_softc *, int); + static int exynos_i2c_match(device_t, cfdata_t, void *); static void exynos_i2c_attach(device_t, device_t, void *); +static i2c_tag_t exynos_i2c_get_tag(device_t); + +struct fdtbus_i2c_controller_func exynos_i2c_funcs = { + .get_tag = exynos_i2c_get_tag +}; + CFATTACH_DECL_NEW(exynos_i2c, sizeof(struct exynos_i2c_softc), exynos_i2c_match, exynos_i2c_attach, NULL, NULL); #define I2C_WRITE(sc, reg, val) \ - bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) + bus_space_write_1((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) #define I2C_READ(sc, reg) \ - bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) + bus_space_read_1((sc)->sc_bst, (sc)->sc_bsh, (reg)) -#define IICON 0 -#define IRQPEND (1<<4) +#define IICCON 0x00 +#define IICSTAT 0x04 +#define IICADD 0x08 +#define IICDS 0x0C + +#define ACKENABLE (1<<7) +#define TXPRESCALE (1<<6) +#define INTENABLE (1<<5) +#define IRQPEND (1<<4) +#define PRESCALE (0x0f) + +#define MODESELECT (3<<6) +#define BUSYSTART (1<<5) +#define BUSENABLE (1<<4) +#define ARBITRATION (1<<3) +#define SLAVESTATUS (1<<2) +#define ZEROSTATUS (1<<1) +#define LASTBIT (1<<0) + +#define READBIT (1<<7) static int exynos_i2c_match(device_t self, cfdata_t cf, void *aux) @@ -126,7 +148,7 @@ exynos_i2c_attach(device_t parent, devic int i2c_handle; int len; int handle; - int func /*, pud, drv */; + int func, pud, drv; if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { aprint_error(": couldn't get registers\n"); @@ -143,7 +165,6 @@ exynos_i2c_attach(device_t parent, devic return; } - sc->sc_port = i2c_port++; mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM); cv_init(&sc->sc_cv, device_xname(self)); aprint_normal(" @ 0x%08x\n", (uint)addr); @@ -184,11 +205,18 @@ exynos_i2c_attach(device_t parent, devic } else func = be32toh(handle); - sc->sc_sda = fdtbus_gpio_acquire(phandle, &result[0], func); - sc->sc_scl = fdtbus_gpio_acquire(phandle, &result[7], func); + sc->sc_sda = fdtbus_pinctrl_acquire(phandle, &result[0]); + if (sc->sc_sda == NULL) { + printf("could not acquire sda gpio %s\n", &result[0]); + return; + } + + sc->sc_scl = fdtbus_pinctrl_acquire(phandle, &result[7]); + if (sc->sc_scl == NULL) { + printf("could not acquire scl gpio %s\n", &result[7]); + return; + } - /* MJF: Need fdtbus_gpio_configure */ -#if 0 len = OF_getprop(i2c_handle, "samsung,pin-pud", &handle, sizeof(&handle)); if (len <= 0) { @@ -205,100 +233,47 @@ exynos_i2c_attach(device_t parent, devic } else drv = be32toh(handle); -#endif - if (!exynos_i2c_attach_i2cbus(sc, &sc->sc_ic)) - return; + struct exynos_gpio_pin_cfg cfg; + cfg.cfg = func; + cfg.pud = pud; + cfg.drv = drv; + cfg.conpwd = 0; + cfg.pudpwd = 0; + + fdtbus_pinctrl_set_cfg(sc->sc_scl, &cfg); + fdtbus_pinctrl_set_cfg(sc->sc_sda, &cfg); + + sc->sc_ic.ic_cookie = sc; + sc->sc_ic.ic_acquire_bus = exynos_i2c_acquire_bus; + sc->sc_ic.ic_release_bus = exynos_i2c_release_bus; + sc->sc_ic.ic_send_start = exynos_i2c_send_start; + sc->sc_ic.ic_send_stop = exynos_i2c_send_stop; + sc->sc_ic.ic_initiate_xfer = exynos_i2c_initiate_xfer; + sc->sc_ic.ic_read_byte = exynos_i2c_read_byte; + sc->sc_ic.ic_write_byte = exynos_i2c_write_byte; sc->sc_i2cdev = config_found_ia(self, "i2cbus", &iba, iicbus_print); } -static bool -exynos_i2c_attach_i2cbus(struct exynos_i2c_softc *i2c_sc, - struct i2c_controller *i2c_cntr) -{ - i2c_cntr->ic_cookie = i2c_sc; - i2c_cntr->ic_acquire_bus = exynos_i2c_acquire_bus; - i2c_cntr->ic_release_bus = exynos_i2c_release_bus; - i2c_cntr->ic_send_start = exynos_i2c_send_start; - i2c_cntr->ic_send_stop = exynos_i2c_send_stop; - i2c_cntr->ic_initiate_xfer = exynos_i2c_initiate_xfer; - i2c_cntr->ic_read_byte = exynos_i2c_read_byte; - i2c_cntr->ic_write_byte = exynos_i2c_write_byte; - - return 1; -} - -#define EXYNOS_I2C_BB_SDA __BIT(1) -#define EXYNOS_I2C_BB_SCL __BIT(2) -#define EXYNOS_I2C_BB_SDA_OUT __BIT(3) -#define EXYNOS_I2C_BB_SDA_IN 0 - -static void -exynos_i2c_bb_set_bits(void *cookie, uint32_t bits) -{ - struct exynos_i2c_softc *i2c_sc = cookie; - int sda, scl; - - sda = (bits & EXYNOS_I2C_BB_SDA) ? true : false; - scl = (bits & EXYNOS_I2C_BB_SCL) ? true : false; - - if (i2c_sc->sc_sda_is_output) - fdtbus_gpio_write(i2c_sc->sc_sda, sda); - fdtbus_gpio_write(i2c_sc->sc_scl, scl); -} - -static uint32_t -exynos_i2c_bb_read_bits(void *cookie) +static i2c_tag_t +exynos_i2c_get_tag(device_t dev) { - struct exynos_i2c_softc *i2c_sc = cookie; - int sda, scl; - - sda = 0; - if (!i2c_sc->sc_sda_is_output) - sda = fdtbus_gpio_read(i2c_sc->sc_sda); - scl = fdtbus_gpio_read(i2c_sc->sc_scl); + struct exynos_i2c_softc * const sc = device_private(dev); - return (sda ? EXYNOS_I2C_BB_SDA : 0) | (scl ? EXYNOS_I2C_BB_SCL : 0); + return &sc->sc_ic; } -static void -exynos_i2c_bb_set_dir(void *cookie, uint32_t bits) -{ - struct exynos_i2c_softc *i2c_sc = cookie; - int flags; - - flags = GPIO_PIN_INPUT | GPIO_PIN_TRISTATE; - i2c_sc->sc_sda_is_output = ((bits & EXYNOS_I2C_BB_SDA_OUT) != 0); - if (i2c_sc->sc_sda_is_output) - flags = GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE; - - /* MJF: This is wrong but fdtbus has no ctrl operation */ - fdtbus_gpio_write(i2c_sc->sc_sda, flags); -} - -static const struct i2c_bitbang_ops exynos_i2c_bbops = { - exynos_i2c_bb_set_bits, - exynos_i2c_bb_set_dir, - exynos_i2c_bb_read_bits, - { - EXYNOS_I2C_BB_SDA, - EXYNOS_I2C_BB_SCL, - EXYNOS_I2C_BB_SDA_OUT, - EXYNOS_I2C_BB_SDA_IN, - } -}; - static int exynos_i2c_intr(void *priv) { struct exynos_i2c_softc * const sc = priv; - uint32_t istatus = I2C_READ(sc, IICON); + uint8_t istatus = I2C_READ(sc, IICCON); if (!(istatus & IRQPEND)) return 0; istatus &= ~IRQPEND; - I2C_WRITE(sc, IICON, istatus); + I2C_WRITE(sc, IICCON, istatus); mutex_enter(&sc->sc_lock); cv_broadcast(&sc->sc_cv); @@ -312,9 +287,6 @@ exynos_i2c_acquire_bus(void *cookie, int { struct exynos_i2c_softc *i2c_sc = cookie; - /* XXX what to do in polling case? could another cpu help */ - if (flags & I2C_F_POLL) - return 0; mutex_enter(&i2c_sc->sc_lock); return 0; } @@ -324,41 +296,94 @@ exynos_i2c_release_bus(void *cookie, int { struct exynos_i2c_softc *i2c_sc = cookie; - /* XXX what to do in polling case? could another cpu help */ - if (flags & I2C_F_POLL) - return; mutex_exit(&i2c_sc->sc_lock); } static int +exynos_i2c_wait(struct exynos_i2c_softc *sc, int flags) +{ + int error, retry; + uint8_t stat = 0; + + retry = (flags & I2C_F_POLL) ? 100000 : 100; + + while (--retry > 0) { + if ((flags & I2C_F_POLL) == 0) { + error = cv_timedwait_sig(&sc->sc_cv, &sc->sc_lock, + max(mstohz(10), 1)); + if (error) { + return error; + } + } + stat = I2C_READ(sc, IICSTAT); + if (!(stat & BUSYSTART)) { + break; + } + if (flags & I2C_F_POLL) { + delay(10); + } + } + if (retry == 0) { + stat = I2C_READ(sc, IICSTAT); + device_printf(sc->sc_dev, "timed out, status = %#x\n", stat); + return ETIMEDOUT; + } + + return 0; +} + + +static int exynos_i2c_send_start(void *cookie, int flags) { - return i2c_bitbang_send_start(cookie, flags, &exynos_i2c_bbops); + struct exynos_i2c_softc *sc = cookie; + I2C_WRITE(sc, IICSTAT, 0xF0); + return 0; } static int exynos_i2c_send_stop(void *cookie, int flags) { - return i2c_bitbang_send_stop(cookie, flags, &exynos_i2c_bbops); + struct exynos_i2c_softc *sc = cookie; + I2C_WRITE(sc, IICSTAT, 0xD0); + return 0; } static int exynos_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags) { - return i2c_bitbang_initiate_xfer(cookie, addr, flags, - &exynos_i2c_bbops); + struct exynos_i2c_softc *sc = cookie; + uint8_t byte = addr & 0x7f; + if (flags & I2C_F_READ) + byte |= READBIT; + else + byte &= ~READBIT; + I2C_WRITE(sc, IICADD, addr); + exynos_i2c_send_start(cookie, flags); + exynos_i2c_write_byte(cookie, byte, flags); + return exynos_i2c_wait(cookie, flags); } static int exynos_i2c_read_byte(void *cookie, uint8_t *bytep, int flags) { - return i2c_bitbang_read_byte(cookie, bytep, flags, - &exynos_i2c_bbops); + struct exynos_i2c_softc *sc = cookie; + int error = exynos_i2c_wait(sc, flags); + if (error) + return error; + *bytep = I2C_READ(sc, IICDS) & 0xff; + if (flags & I2C_F_STOP) + exynos_i2c_send_stop(cookie, flags); + return 0; } static int exynos_i2c_write_byte(void *cookie, uint8_t byte, int flags) { - return i2c_bitbang_write_byte(cookie, byte, flags, - &exynos_i2c_bbops); + struct exynos_i2c_softc *sc = cookie; + int error = exynos_i2c_wait(sc, flags); + if (error) + return error; + I2C_WRITE(sc, IICDS, byte); + return 0; } Index: src/sys/arch/arm/samsung/exynos_pinctrl.c diff -u src/sys/arch/arm/samsung/exynos_pinctrl.c:1.7 src/sys/arch/arm/samsung/exynos_pinctrl.c:1.8 --- src/sys/arch/arm/samsung/exynos_pinctrl.c:1.7 Sun Dec 27 12:21:37 2015 +++ src/sys/arch/arm/samsung/exynos_pinctrl.c Wed Dec 30 04:30:27 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: exynos_pinctrl.c,v 1.7 2015/12/27 12:21:37 jmcneill Exp $ */ +/* $NetBSD: exynos_pinctrl.c,v 1.8 2015/12/30 04:30:27 marty Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ #include "gpio.h" #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: exynos_pinctrl.c,v 1.7 2015/12/27 12:21:37 jmcneill Exp $"); +__KERNEL_RCSID(1, "$NetBSD: exynos_pinctrl.c,v 1.8 2015/12/30 04:30:27 marty Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -56,6 +56,18 @@ __KERNEL_RCSID(1, "$NetBSD: exynos_pinct static int exynos_pinctrl_match(device_t, cfdata_t, void *); static void exynos_pinctrl_attach(device_t, device_t, void *); +static void *exynos_pinctrl_acquire(device_t, const char *); +static void exynos_pinctrl_release(device_t, void *); +static void exynos_pinctrl_get_cfg(struct fdtbus_pinctrl_pin *, void *); +static void exynos_pinctrl_set_cfg(struct fdtbus_pinctrl_pin *, void *); + +static struct fdtbus_pinctrl_controller_func exynos_pinctrl_controller_func = { + .acquire = exynos_pinctrl_acquire, + .release = exynos_pinctrl_release, + .get = exynos_pinctrl_get_cfg, + .set = exynos_pinctrl_set_cfg, +}; + CFATTACH_DECL_NEW(exynos_pinctrl, sizeof(struct exynos_pinctrl_softc), exynos_pinctrl_match, exynos_pinctrl_attach, NULL, NULL); @@ -74,6 +86,7 @@ exynos_pinctrl_attach(device_t parent, d struct exynos_pinctrl_softc * const sc = kmem_zalloc(sizeof(*sc), KM_SLEEP); struct fdt_attach_args * const faa = aux; + struct exynos_gpio_softc *child_sc; bus_addr_t addr; bus_size_t size; int error; @@ -101,6 +114,41 @@ exynos_pinctrl_attach(device_t parent, d child = OF_peer(child)) { if (of_getprop_bool(child, "gpio-controller") == false) continue; - exynos_gpio_bank_config(sc, faa, child); + child_sc = exynos_gpio_bank_config(sc, faa, child); + fdtbus_register_pinctrl_controller(child_sc->sc_dev, child, + &exynos_pinctrl_controller_func); } } + + +static void *exynos_pinctrl_acquire(device_t self, const char *name) +{ + return exynos_gpio_bank_lookup(name); +} + +static void exynos_pinctrl_release(device_t self, void *cookie) +{ +} + +static void exynos_pinctrl_get_cfg(struct fdtbus_pinctrl_pin *pin, + void *cookie) +{ + struct exynos_gpio_bank *bank = pin->pp_priv; + struct exynos_gpio_pin_cfg *cfg = cookie; + struct exynos_gpio_pin_cfg **cfgp = &cfg; + struct exynos_gpio_pin_cfg *newcfg = kmem_zalloc(sizeof(*newcfg), + KM_SLEEP); + if (newcfg == NULL) + return; + exynos_gpio_pin_ctl_read(bank, newcfg); + *cfgp = newcfg; + return; +} + +static void exynos_pinctrl_set_cfg(struct fdtbus_pinctrl_pin *pin, + void *cookie) +{ + struct exynos_gpio_bank *bank = pin->pp_priv; + struct exynos_gpio_pin_cfg *cfg = cookie; + exynos_gpio_pin_ctl_write(bank, cfg); +} Index: src/sys/arch/arm/samsung/exynos_var.h diff -u src/sys/arch/arm/samsung/exynos_var.h:1.22 src/sys/arch/arm/samsung/exynos_var.h:1.23 --- src/sys/arch/arm/samsung/exynos_var.h:1.22 Thu Dec 24 01:10:51 2015 +++ src/sys/arch/arm/samsung/exynos_var.h Wed Dec 30 04:30:27 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: exynos_var.h,v 1.22 2015/12/24 01:10:51 marty Exp $ */ +/* $NetBSD: exynos_var.h,v 1.23 2015/12/30 04:30:27 marty Exp $ */ /*- * Copyright (c) 2013, 2014 The NetBSD Foundation, Inc. @@ -104,6 +104,21 @@ struct exynos_gpio_pindata { int pd_pin; }; +struct exynos_gpio_pin_cfg { + uint32_t cfg; + uint32_t pud; + uint32_t drv; + uint32_t conpwd; + uint32_t pudpwd; +}; + +struct exynos_gpio_softc { + device_t sc_dev; + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh; + struct exynos_gpio_bank *sc_bank; + int sc_phandle; +}; #define EXYNOS_MAX_IIC_BUSSES 9 struct i2c_controller; @@ -127,8 +142,10 @@ extern void exynos_bootstrap(vaddr_t, va extern void exynos_dma_bootstrap(psize_t memsize); struct exynos_pinctrl_softc; +struct exynos_gpio_softc; struct fdt_attach_args; -extern void exynos_gpio_bank_config(struct exynos_pinctrl_softc *, + +extern struct exynos_gpio_softc * exynos_gpio_bank_config(struct exynos_pinctrl_softc *, const struct fdt_attach_args *, int); extern void exynos_wdt_reset(void); @@ -146,13 +163,17 @@ extern void exynos_usb_soc_powerup(void) extern void exyo_device_register(device_t self, void *aux); extern void exyo_device_register_post_config(device_t self, void *aux); +extern struct exynos_gpio_bank *exynos_gpio_bank_lookup(const char *name); 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 void exynos_gpio_pinset_to_pindata(const struct exynos_gpio_pinset *, int pinnr, struct exynos_gpio_pindata *); extern bool exynos_gpio_pin_reserve(const char *, struct exynos_gpio_pindata *); - +extern void exynos_gpio_pin_ctl_read(const struct exynos_gpio_bank *, + struct exynos_gpio_pin_cfg *); +extern void exynos_gpio_pin_ctl_write(const struct exynos_gpio_bank *, + const struct exynos_gpio_pin_cfg *); static inline void exynos_gpio_pindata_write(const struct exynos_gpio_pindata *pd, int value) {