Date: Fri, 1 Dec 2017 20:51:08 +0000 (UTC) From: Kyle Evans <kevans@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r326433 - head/sys/arm/allwinner Message-ID: <201712012051.vB1Kp8Gn049159@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kevans Date: Fri Dec 1 20:51:08 2017 New Revision: 326433 URL: https://svnweb.freebsd.org/changeset/base/326433 Log: a10_gpio: Add support for more modern pin configuration a10_gpio previously accepted only {allwinner,}drive and {allwinner,}pull for drive/bias setting, while newer DTS is using drive-strength and bias-{disable,pull-up,pull-down} properties. Accept these properties as well. Additionally make bias and drive strength optional rather than required; not setting them should just indicate that we do not need to configure these properties. Tested on: BananaPi-M3 (a83t) Reviewed by: manu Approved by: emaste (implicit) Obtained from: NetBSD (partially) Differential Revision: https://reviews.freebsd.org/D13284 Modified: head/sys/arm/allwinner/a10_gpio.c Modified: head/sys/arm/allwinner/a10_gpio.c ============================================================================== --- head/sys/arm/allwinner/a10_gpio.c Fri Dec 1 17:58:20 2017 (r326432) +++ head/sys/arm/allwinner/a10_gpio.c Fri Dec 1 20:51:08 2017 (r326433) @@ -203,6 +203,11 @@ struct a10_gpio_softc { #define A10_GPIO_GP_INT_STA 0x214 #define A10_GPIO_GP_INT_DEB 0x218 +static char *a10_gpio_parse_function(phandle_t node); +static const char **a10_gpio_parse_pins(phandle_t node, int *pins_nb); +static uint32_t a10_gpio_parse_bias(phandle_t node); +static int a10_gpio_parse_drive_strength(phandle_t node, uint32_t *drive); + static int a10_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value); static int a10_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value); static int a10_gpio_pin_get_locked(struct a10_gpio_softc *sc, uint32_t pin, unsigned int *value); @@ -278,6 +283,9 @@ a10_gpio_set_pud(struct a10_gpio_softc *sc, uint32_t p { uint32_t bank, offset, val; + if (a10_gpio_get_pud(sc, pin) == state) + return; + /* Must be called with lock held. */ A10_GPIO_LOCK_ASSERT(sc); @@ -313,6 +321,9 @@ a10_gpio_set_drv(struct a10_gpio_softc *sc, uint32_t p { uint32_t bank, offset, val; + if (a10_gpio_get_drv(sc, pin) == drive) + return; + /* Must be called with lock held. */ A10_GPIO_LOCK_ASSERT(sc); @@ -541,7 +552,76 @@ a10_gpio_pin_get_locked(struct a10_gpio_softc *sc,uint return (0); } +static char * +a10_gpio_parse_function(phandle_t node) +{ + char *function; + + if (OF_getprop_alloc(node, "function", sizeof(*function), + (void **)&function) != -1) + return (function); + if (OF_getprop_alloc(node, "allwinner,function", sizeof(*function), + (void **)&function) != -1) + return (function); + + return (NULL); +} + +static const char ** +a10_gpio_parse_pins(phandle_t node, int *pins_nb) +{ + const char **pinlist; + + *pins_nb = ofw_bus_string_list_to_array(node, "pins", &pinlist); + if (*pins_nb > 0) + return (pinlist); + + *pins_nb = ofw_bus_string_list_to_array(node, "allwinner,pins", + &pinlist); + if (*pins_nb > 0) + return (pinlist); + + return (NULL); +} + +static uint32_t +a10_gpio_parse_bias(phandle_t node) +{ + uint32_t bias; + + if (OF_getencprop(node, "pull", &bias, sizeof(bias)) != -1) + return (bias); + if (OF_getencprop(node, "allwinner,pull", &bias, sizeof(bias)) != -1) + return (bias); + if (OF_hasprop(node, "bias-disable")) + return (A10_GPIO_NONE); + if (OF_hasprop(node, "bias-pull-up")) + return (A10_GPIO_PULLUP); + if (OF_hasprop(node, "bias-pull-down")) + return (A10_GPIO_PULLDOWN); + + return (A10_GPIO_NONE); +} + static int +a10_gpio_parse_drive_strength(phandle_t node, uint32_t *drive) +{ + uint32_t drive_str; + + if (OF_getencprop(node, "drive", drive, sizeof(*drive)) != -1) + return (0); + if (OF_getencprop(node, "allwinner,drive", drive, sizeof(*drive)) != -1) + return (0); + if (OF_getencprop(node, "drive-strength", &drive_str, + sizeof(drive_str)) != -1) { + *drive = (drive_str / 10) - 1; + return (0); + } + + return (1); +} + +static int a10_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) { struct a10_gpio_softc *sc; @@ -682,46 +762,29 @@ aw_fdt_configure_pins(device_t dev, phandle_t cfgxref) char *pin_function = NULL; uint32_t pin_drive, pin_pull; int pins_nb, pin_num, pin_func, i, ret; + bool set_drive; sc = device_get_softc(dev); node = OF_node_from_xref(cfgxref); ret = 0; + set_drive = false; /* Getting all prop for configuring pins */ - pins_nb = ofw_bus_string_list_to_array(node, "pins", &pinlist); - if (pins_nb <= 0) { - pins_nb = ofw_bus_string_list_to_array(node, "allwinner,pins", - &pinlist); - if (pins_nb <= 0) - return (ENOENT); + pinlist = a10_gpio_parse_pins(node, &pins_nb); + if (pinlist == NULL) + return (ENOENT); + + pin_function = a10_gpio_parse_function(node); + if (pin_function == NULL) { + ret = ENOENT; + goto out; } - if (OF_getprop_alloc(node, "function", - sizeof(*pin_function), - (void **)&pin_function) == -1) { - if (OF_getprop_alloc(node, "allwinner,function", - sizeof(*pin_function), - (void **)&pin_function) == -1) { - ret = ENOENT; - goto out; - } - } - if (OF_getencprop(node, "drive", - &pin_drive, sizeof(pin_drive)) == -1) { - if (OF_getencprop(node, "allwinner,drive", - &pin_drive, sizeof(pin_drive)) == -1) { - ret = ENOENT; - goto out; - } - } - if (OF_getencprop(node, "pull", - &pin_pull, sizeof(pin_pull)) == -1) { - if (OF_getencprop(node, "allwinner,pull", - &pin_pull, sizeof(pin_pull)) == -1) { - ret = ENOENT; - goto out; - } - } + if (a10_gpio_parse_drive_strength(node, &pin_drive) == 0) + set_drive = true; + + pin_pull = a10_gpio_parse_bias(node); + /* Configure each pin to the correct function, drive and pull */ for (i = 0; i < pins_nb; i++) { pin_num = aw_find_pinnum_by_name(sc, pinlist[i]); @@ -739,12 +802,11 @@ aw_fdt_configure_pins(device_t dev, phandle_t cfgxref) if (a10_gpio_get_function(sc, pin_num) != pin_func) a10_gpio_set_function(sc, pin_num, pin_func); - if (a10_gpio_get_drv(sc, pin_num) != pin_drive) + if (set_drive) a10_gpio_set_drv(sc, pin_num, pin_drive); - if (a10_gpio_get_pud(sc, pin_num) != pin_pull && - (pin_pull == A10_GPIO_PULLUP || - pin_pull == A10_GPIO_PULLDOWN)) + if (pin_pull != A10_GPIO_NONE) a10_gpio_set_pud(sc, pin_num, pin_pull); + A10_GPIO_UNLOCK(sc); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201712012051.vB1Kp8Gn049159>