From owner-svn-src-all@freebsd.org Fri Nov 24 09:21:39 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 90F11DC1F63 for ; Fri, 24 Nov 2017 09:21:39 +0000 (UTC) (envelope-from wma@semihalf.com) Received: from mail-qt0-x233.google.com (mail-qt0-x233.google.com [IPv6:2607:f8b0:400d:c0d::233]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority G2" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 32F916C6A1 for ; Fri, 24 Nov 2017 09:21:39 +0000 (UTC) (envelope-from wma@semihalf.com) Received: by mail-qt0-x233.google.com with SMTP id r39so30618906qtr.13 for ; Fri, 24 Nov 2017 01:21:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20150623.gappssmtp.com; s=20150623; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=plTXRLx9wFU3C9gNKwvNULArkc9AvIrN4vL4S10l/mM=; b=1b3addDsA+fuRoF8w98mnTGqBTb7vJTsXfOb6thi/J+99DJSAwDRQcG99/GbTzq+Ld 2p0sPD3Rn2xasIM6eaLhcQCSquaavXBFHXWTYh9kXHmxAn2AuU4gKZkrf0d5MegxHQrs 6LeN3RTikcBuuvdk45JJGhq3MzEB3BflzRkj7zrR0CgqGuHAY5Erqh7hmhAVtJwIqraI VkbChJELCgThz05qAwuRFM+B83TYcSQ/ABT405d7tjfN6vB9BpLeuxTJPBNRjvVfcfas YZVbqPo92yLKyxlTEWueflYFdi4QieaLSIKGg2kfqhAbIRdWIE8woxwaUm/7dL85AvpR NgPQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=plTXRLx9wFU3C9gNKwvNULArkc9AvIrN4vL4S10l/mM=; b=UixzpP/Rl6gmMbZ39vPxok8SvlKTx8irSwhfgWyaB5ZkU58OwrZ7aEyER98AknF1ja IqXPHIPLF/l7MNy4yroTnNLN7X80G/rFzC/Nz2UPRUqHKNpO1NJUQm+Odpm2xQY0NfK+ 0lPo2OkqzD3hz62wkq6z4g4i7Kl7C4XI6QffN5DJXghad+64J2dfoI7kj7ybBNlHB9TY 4NoIvFQdSQq4cBYPfurtwsK9CXkiUF4Pr20vsuCfxVQC0k8NjGt8U8anzfxnsP1RXJEs 9XygYbVB83G9vFC9YeEzoJofdD9YV6VjvJoJV1zhto762/wdU1PGRE44nJk2DKreQMpS clpw== X-Gm-Message-State: AJaThX76u6LoTGDFLSkGvfTZR078ok5/hgIXTbmyIneXb97/lvlqHQEJ iXE0IAYtPdcfgTXAh4BdVPNXJYzmwaYsq6bYxHsT+olEomw= X-Google-Smtp-Source: AGs4zMYau7I0ndbjBhPlsJwju4KKL7OlD5HB8cF5OQssfhstjX8w5d+muiean/YPxda/5qdJJ6rVTael8w0dw1jfo/M= X-Received: by 10.200.55.231 with SMTP id e36mr44023899qtc.274.1511515298015; Fri, 24 Nov 2017 01:21:38 -0800 (PST) MIME-Version: 1.0 Received: by 10.200.57.73 with HTTP; Fri, 24 Nov 2017 01:21:17 -0800 (PST) In-Reply-To: <201711222310.vAMNAKmb048921@repo.freebsd.org> References: <201711222310.vAMNAKmb048921@repo.freebsd.org> From: Wojciech Macek Date: Fri, 24 Nov 2017 10:21:17 +0100 Message-ID: Subject: Re: svn commit: r326109 - in head/sys: conf dev/bhnd dev/bhnd/cores/chipc mips/conf modules/bhnd To: "Landon J. Fuller" , adrian@freebsd.org Cc: src-committers , svn-src-all@freebsd.org, svn-src-head@freebsd.org Content-Type: text/plain; charset="UTF-8" X-Content-Filtered-By: Mailman/MimeDel 2.1.25 X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 24 Nov 2017 09:21:39 -0000 Hi, The patch breaks the build for ppc64. Could you please add missing ofw_bus_if.h to the Makefile? cc -isystem /home/wma/ppc64-freebsd/obj/home/wma/ppc64-freebsd/powerpc.powerpc64/tmp/usr/include -L/home/wma/ppc64-freebsd/obj/home/wma/ppc64-freebsd/powerpc.powerpc64/tmp/usr/lib -B/home/wma/ppc64-freebsd/obj/home/wma/ppc64-freebsd/powerpc.powerpc64/tmp/usr/lib --sysroot=/home/wma/ppc64-freebsd/obj/home/wma/ppc64-freebsd/powerpc.powerpc64/tmp -B/home/wma/ppc64-freebsd/obj/home/wma/ppc64-freebsd/powerpc.powerpc64/tmp/usr/bin -O2 -pipe -fno-strict-aliasing -Werror -D_KERNEL -DKLD_MODULE -nostdinc -DHAVE_KERNEL_OPTION_HEADERS -include /home/wma/ppc64-freebsd/obj/home/wma/ppc64-freebsd/powerpc.powerpc64/sys/GENERIC64/opt_global.h -I. -I/home/wma/ppc64-freebsd/sys -fno-common -g -mlongcall -fno-omit-frame-pointer -I/home/wma/ppc64-freebsd/obj/home/wma/ppc64-freebsd/powerpc.powerpc64/sys/GENERIC64 -MD -MF.depend.chipc_gpio.o -MTchipc_gpio.o -mno-altivec -ffreestanding -fwrapv -fstack-protector -gdwarf-2 -Wall -Wredundant-decls -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Winline -Wcast-qual -Wundef -Wno-pointer-sign -fformat-extensions -Wmissing-include-dirs -fdiagnostics-show-option -Wno-unknown-pragmas -Wno-uninitialized -finline-limit=15000 -fms-extensions --param inline-unit-growth=100 --param large-function-growth=1000 -msoft-float -mcall-aixdesc -std=iso9899:1999 -c /home/wma/ppc64-freebsd/sys/dev/bhnd/cores/chipc/chipc_gpio.c -o chipc_gpio.o In file included from /home/wma/ppc64-freebsd/sys/dev/gpio/gpiobusvar.h:40, from /home/wma/ppc64-freebsd/sys/dev/bhnd/cores/chipc/chipc_gpio.c:48: /home/wma/ppc64-freebsd/sys/dev/ofw/ofw_bus_subr.h:40:24: error: ofw_bus_if.h: No such file or directory cc1: warnings being treated as errors In file included from /home/wma/ppc64-freebsd/sys/dev/gpio/gpiobusvar.h:40, from /home/wma/ppc64-freebsd/sys/dev/bhnd/cores/chipc/chipc_gpio.c:48: /home/wma/ppc64-freebsd/sys/dev/ofw/ofw_bus_subr.h:71: warning: 'struct ofw_bus_devinfo' declared inside parameter list /home/wma/ppc64-freebsd/sys/dev/ofw/ofw_bus_subr.h:71: warning: its scope is only this definition or declaration, which is probably not what you want /home/wma/ppc64-freebsd/sys/dev/ofw/ofw_bus_subr.h:72: warning: 'struct ofw_bus_devinfo' declared inside parameter list /home/wma/ppc64-freebsd/sys/dev/ofw/ofw_bus_subr.h:74: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'ofw_bus_gen_get_compat' /home/wma/ppc64-freebsd/sys/dev/ofw/ofw_bus_subr.h:75: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'ofw_bus_gen_get_model' /home/wma/ppc64-freebsd/sys/dev/ofw/ofw_bus_subr.h:76: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'ofw_bus_gen_get_name' /home/wma/ppc64-freebsd/sys/dev/ofw/ofw_bus_subr.h:77: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'ofw_bus_gen_get_node' /home/wma/ppc64-freebsd/sys/dev/ofw/ofw_bus_subr.h:78: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'ofw_bus_gen_get_type' In file included from /home/wma/ppc64-freebsd/sys/dev/bhnd/cores/chipc/chipc_gpio.c:48: /home/wma/ppc64-freebsd/sys/dev/gpio/gpiobusvar.h:115: error: field 'opd_obdinfo' has incomplete type *** [chipc_gpio.o] Error code 1 make[4]: stopped in /home/wma/ppc64-freebsd/sys/modules/bhnd --- all_subdir_cardbus --- --- cardbus.o --- ctfconvert -L VERSION -g cardbus.o A failure has been detected in another branch of the parallel make Regards, Wojtek 2017-11-23 0:10 GMT+01:00 Landon J. Fuller : > Author: landonf > Date: Wed Nov 22 23:10:20 2017 > New Revision: 326109 > URL: https://svnweb.freebsd.org/changeset/base/326109 > > Log: > bhnd(4): Add a basic ChipCommon GPIO driver sufficient to support bwn(4) > > The driver is functional on both BHND Wi-Fi adapters and MIPS SoCs, but > does not currently include support for features not required by bwn(4), > including GPIO interrupt handling. > > Approved by: adrian (mentor, implicit) > Sponsored by: The FreeBSD Foundation > Differential Revision: https://reviews.freebsd.org/D12708 > > Added: > head/sys/dev/bhnd/cores/chipc/chipc_gpio.c (contents, props changed) > head/sys/dev/bhnd/cores/chipc/chipc_gpiovar.h (contents, props > changed) > Modified: > head/sys/conf/files > head/sys/dev/bhnd/bhnd_types.h > head/sys/dev/bhnd/cores/chipc/chipc.c > head/sys/dev/bhnd/cores/chipc/chipc_subr.c > head/sys/dev/bhnd/cores/chipc/chipcreg.h > head/sys/mips/conf/BCM > head/sys/mips/conf/SENTRY5 > head/sys/modules/bhnd/Makefile > > Modified: head/sys/conf/files > ============================================================ > ================== > --- head/sys/conf/files Wed Nov 22 22:04:27 2017 (r326108) > +++ head/sys/conf/files Wed Nov 22 23:10:20 2017 (r326109) > @@ -1246,6 +1246,7 @@ dev/bhnd/cores/chipc/bhnd_sprom_chipc.c optional > bhnd > dev/bhnd/cores/chipc/bhnd_pmu_chipc.c optional bhnd > dev/bhnd/cores/chipc/chipc.c optional bhnd > dev/bhnd/cores/chipc/chipc_cfi.c optional bhnd cfi > +dev/bhnd/cores/chipc/chipc_gpio.c optional bhnd gpio > dev/bhnd/cores/chipc/chipc_slicer.c optional bhnd cfi | bhnd spibus > dev/bhnd/cores/chipc/chipc_spi.c optional bhnd spibus > dev/bhnd/cores/chipc/chipc_subr.c optional bhnd > > Modified: head/sys/dev/bhnd/bhnd_types.h > ============================================================ > ================== > --- head/sys/dev/bhnd/bhnd_types.h Wed Nov 22 22:04:27 2017 > (r326108) > +++ head/sys/dev/bhnd/bhnd_types.h Wed Nov 22 23:10:20 2017 > (r326109) > @@ -75,6 +75,7 @@ typedef enum { > BHND_SERVICE_PWRCTL, /**< legacy pwrctl service; > implements the bhnd_pwrctl interface */ > BHND_SERVICE_PMU, /**< pmu service; implements the > bhnd_pmu interface */ > BHND_SERVICE_NVRAM, /**< nvram service; implements the > bhnd_nvram interface */ > + BHND_SERVICE_GPIO, /**< gpio service; implements the > standard gpio interface */ > > BHND_SERVICE_ANY = 1000, /**< match on any service type */ > } bhnd_service_t; > > Modified: head/sys/dev/bhnd/cores/chipc/chipc.c > ============================================================ > ================== > --- head/sys/dev/bhnd/cores/chipc/chipc.c Wed Nov 22 22:04:27 2017 > (r326108) > +++ head/sys/dev/bhnd/cores/chipc/chipc.c Wed Nov 22 23:10:20 2017 > (r326109) > @@ -306,6 +306,20 @@ chipc_add_children(struct chipc_softc *sc) > } > } > > + /* GPIO */ > + child = BUS_ADD_CHILD(sc->dev, 0, "gpio", 0); > + if (child == NULL) { > + device_printf(sc->dev, "failed to add gpio\n"); > + return (ENXIO); > + } > + > + error = chipc_set_mem_resource(sc, child, 0, 0, RM_MAX_END, 0, 0); > + if (error) { > + device_printf(sc->dev, "failed to set gpio memory > resource: " > + "%d\n", error); > + return (error); > + } > + > /* All remaining devices are SoC-only */ > if (bhnd_get_attach_type(sc->dev) != BHND_ATTACH_NATIVE) > return (0); > @@ -835,6 +849,25 @@ chipc_alloc_resource(device_t dev, device_t child, int > if ((cr = chipc_find_region(sc, start, end)) == NULL) { > /* Resource requests outside our shared port regions can be > * delegated to our parent. */ > + rv = bus_generic_rl_alloc_resource(dev, child, type, rid, > + start, end, count, flags); > + return (rv); > + } > + > + /* > + * As a special case, children that map the complete ChipCommon > register > + * block are delegated to our parent. > + * > + * The rman API does not support sharing resources that are not > + * identical in size; since we allocate subregions to various > children, > + * any children that need to map the entire register block (e.g. > because > + * they require access to discontiguous register ranges) must make > the > + * allocation through our parent, where we hold a compatible > + * RF_SHAREABLE allocation. > + */ > + if (cr == sc->core_region && cr->cr_addr == start && > + cr->cr_end == end && cr->cr_count == count) > + { > rv = bus_generic_rl_alloc_resource(dev, child, type, rid, > start, end, count, flags); > return (rv); > > Added: head/sys/dev/bhnd/cores/chipc/chipc_gpio.c > ============================================================ > ================== > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ head/sys/dev/bhnd/cores/chipc/chipc_gpio.c Wed Nov 22 23:10:20 2017 > (r326109) > @@ -0,0 +1,846 @@ > +/*- > + * Copyright (c) 2017 The FreeBSD Foundation > + * All rights reserved. > + * > + * This software was developed by Landon Fuller under sponsorship from > + * the FreeBSD Foundation. > + * > + * 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 AUTHOR 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 AUTHOR 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. > + * > + * $FreeBSD$ > + */ > + > +#include > +__FBSDID("$FreeBSD$"); > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > + > +#include > +#include > + > +#include "gpio_if.h" > + > +#include "bhnd_nvram_map.h" > + > +#include "chipcreg.h" > +#include "chipc_gpiovar.h" > + > +/* > + * ChipCommon GPIO driver > + */ > + > +static int chipc_gpio_check_flags( > + struct chipc_gpio_softc *sc, > + uint32_t pin_num, uint32_t flags, > + chipc_gpio_pin_mode *mode); > +static int chipc_gpio_pin_update( > + struct chipc_gpio_softc *sc, > + struct chipc_gpio_update *update, > + uint32_t pin_num, uint32_t flags); > +static int chipc_gpio_commit_update( > + struct chipc_gpio_softc *sc, > + struct chipc_gpio_update *update); > +static chipc_gpio_pin_mode chipc_gpio_pin_get_mode( > + struct chipc_gpio_softc *sc, > + uint32_t pin_num); > + > + > +/* Debugging flags */ > +static u_long chipc_gpio_debug = 0; > +TUNABLE_ULONG("hw.bhnd_chipc.gpio_debug", &chipc_gpio_debug); > + > +enum { > + /** Allow userspace GPIO access on bridged network (e.g. wi-fi) > + * adapters */ > + CC_GPIO_DEBUG_ADAPTER_GPIOC = 1 << 0, > +}; > + > +#define CC_GPIO_DEBUG(_type) (CC_GPIO_DEBUG_ ## _type & > chipc_gpio_debug) > + > +static struct bhnd_device_quirk chipc_gpio_quirks[]; > + > +/* Supported parent core device identifiers */ > +static const struct bhnd_device chipc_gpio_devices[] = { > + BHND_DEVICE(BCM, CC, "Broadcom ChipCommon GPIO", > chipc_gpio_quirks), > + BHND_DEVICE_END > +}; > + > +/* Device quirks table */ > +static struct bhnd_device_quirk chipc_gpio_quirks[] = { > + BHND_CORE_QUIRK (HWREV_LTE(10), CC_GPIO_QUIRK_NO_EVENTS), > + BHND_CORE_QUIRK (HWREV_LTE(15), CC_GPIO_QUIRK_NO_DCTIMER), > + BHND_CORE_QUIRK (HWREV_LTE(19), CC_GPIO_QUIRK_NO_PULLUPDOWN), > + > + BHND_DEVICE_QUIRK_END > +}; > + > +static int > +chipc_gpio_probe(device_t dev) > +{ > + const struct bhnd_device *id; > + device_t chipc; > + > + /* Look for compatible chipc parent */ > + chipc = device_get_parent(dev); > + id = bhnd_device_lookup(chipc, chipc_gpio_devices, > + sizeof(chipc_gpio_devices[0])); > + if (id == NULL) > + return (ENXIO); > + > + device_set_desc(dev, id->desc); > + return (BUS_PROBE_NOWILDCARD); > +} > + > +static int > +chipc_gpio_attach(device_t dev) > +{ > + struct chipc_gpio_softc *sc; > + device_t chipc; > + int error; > + > + chipc = device_get_parent(dev); > + > + sc = device_get_softc(dev); > + sc->dev = dev; > + sc->quirks = bhnd_device_quirks(chipc, chipc_gpio_devices, > + sizeof(chipc_gpio_devices[0])); > + > + /* If this is a bridged wi-fi adapter, we don't want to support > + * userspace requests via gpioc(4) */ > + if (bhnd_get_attach_type(chipc) == BHND_ATTACH_ADAPTER) { > + if (!CC_GPIO_DEBUG(ADAPTER_GPIOC)) > + sc->quirks |= CC_GPIO_QUIRK_NO_GPIOC; > + } > + > + CC_GPIO_LOCK_INIT(sc); > + > + sc->mem_rid = 0; > + sc->mem_res = bhnd_alloc_resource_any(dev, SYS_RES_MEMORY, > &sc->mem_rid, > + RF_ACTIVE|RF_SHAREABLE); > + if (sc->mem_res == NULL) { > + device_printf(dev, "failed to allocate chipcommon > registers\n"); > + error = ENXIO; > + goto failed; > + } > + > + /* > + * If hardware 'pulsate' support is available, set the timer > duty-cycle > + * to either the NVRAM 'leddc' value if available, or the default > duty > + * cycle. > + */ > + if (!CC_GPIO_QUIRK(sc, NO_DCTIMER)) { > + uint32_t dctimerval; > + > + error = bhnd_nvram_getvar_uint32(chipc, BHND_NVAR_LEDDC, > + &dctimerval); > + if (error == ENOENT) { > + /* Fall back on default duty cycle */ > + dctimerval = CHIPC_GPIOTIMERVAL_DEFAULT; > + } else if (error) { > + device_printf(dev, "error reading %s from NVRAM: > %d\n", > + BHND_NVAR_LEDDC, error); > + goto failed; > + } > + > + CC_GPIO_WR4(sc, CHIPC_GPIOTIMERVAL, dctimerval); > + } > + > + /* Attach gpioc/gpiobus */ > + if (CC_GPIO_QUIRK(sc, NO_GPIOC)) { > + sc->gpiobus = NULL; > + } else { > + if ((sc->gpiobus = gpiobus_attach_bus(dev)) == NULL) { > + device_printf(dev, "failed to attach gpiobus\n"); > + error = ENXIO; > + goto failed; > + } > + } > + > + /* Register as the bus GPIO provider */ > + if ((error = bhnd_register_provider(dev, BHND_SERVICE_GPIO))) { > + device_printf(dev, "failed to register gpio with bus: > %d\n", > + error); > + goto failed; > + } > + > + return (0); > + > +failed: > + device_delete_children(dev); > + > + if (sc->mem_res != NULL) { > + bhnd_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, > + sc->mem_res); > + } > + > + CC_GPIO_LOCK_DESTROY(sc); > + > + return (error); > +} > + > +static int > +chipc_gpio_detach(device_t dev) > +{ > + struct chipc_gpio_softc *sc; > + int error; > + > + sc = device_get_softc(dev); > + > + if ((error = bus_generic_detach(dev))) > + return (error); > + > + if ((error = bhnd_deregister_provider(dev, BHND_SERVICE_ANY))) > + return (error); > + > + bhnd_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, > sc->mem_res); > + CC_GPIO_LOCK_DESTROY(sc); > + > + return (0); > +} > + > +static device_t > +chipc_gpio_get_bus(device_t dev) > +{ > + struct chipc_gpio_softc *sc = device_get_softc(dev); > + > + return (sc->gpiobus); > +} > + > +static int > +chipc_gpio_pin_max(device_t dev, int *maxpin) > +{ > + *maxpin = CC_GPIO_NPINS-1; > + return (0); > +} > + > +static int > +chipc_gpio_pin_set(device_t dev, uint32_t pin_num, uint32_t pin_value) > +{ > + struct chipc_gpio_softc *sc; > + bool pin_high; > + int error; > + > + sc = device_get_softc(dev); > + error = 0; > + > + if (!CC_GPIO_VALID_PIN(pin_num)) > + return (EINVAL); > + > + switch (pin_value) { > + case GPIO_PIN_HIGH: > + pin_high = true; > + break; > + case GPIO_PIN_LOW: > + pin_high = false; > + break; > + default: > + return (EINVAL); > + } > + > + CC_GPIO_LOCK(sc); > + > + switch (chipc_gpio_pin_get_mode(sc, pin_num)) { > + case CC_GPIO_PIN_INPUT: > + case CC_GPIO_PIN_TRISTATE: > + error = ENODEV; > + break; > + > + case CC_GPIO_PIN_OUTPUT: > + CC_GPIO_WRFLAG(sc, pin_num, GPIOOUT, pin_high); > + break; > + } > + > + CC_GPIO_UNLOCK(sc); > + > + return (error); > +} > + > +static int > +chipc_gpio_pin_get(device_t dev, uint32_t pin_num, uint32_t *pin_value) > +{ > + struct chipc_gpio_softc *sc; > + bool pin_high; > + > + if (!CC_GPIO_VALID_PIN(pin_num)) > + return (EINVAL); > + > + sc = device_get_softc(dev); > + pin_high = false; > + > + CC_GPIO_LOCK(sc); > + > + switch (chipc_gpio_pin_get_mode(sc, pin_num)) { > + case CC_GPIO_PIN_INPUT: > + pin_high = CC_GPIO_RDFLAG(sc, pin_num, GPIOIN); > + break; > + > + case CC_GPIO_PIN_OUTPUT: > + pin_high = CC_GPIO_RDFLAG(sc, pin_num, GPIOOUT); > + break; > + > + case CC_GPIO_PIN_TRISTATE: > + pin_high = false; > + break; > + } > + > + CC_GPIO_UNLOCK(sc); > + > + *pin_value = pin_high ? GPIO_PIN_HIGH : GPIO_PIN_LOW; > + > + return (0); > +} > + > +static int > +chipc_gpio_pin_toggle(device_t dev, uint32_t pin_num) > +{ > + struct chipc_gpio_softc *sc; > + bool pin_high; > + int error; > + > + if (!CC_GPIO_VALID_PIN(pin_num)) > + return (EINVAL); > + > + sc = device_get_softc(dev); > + error = 0; > + > + CC_GPIO_LOCK(sc); > + > + switch (chipc_gpio_pin_get_mode(sc, pin_num)) { > + case CC_GPIO_PIN_INPUT: > + case CC_GPIO_PIN_TRISTATE: > + error = ENODEV; > + break; > + > + case CC_GPIO_PIN_OUTPUT: > + pin_high = CC_GPIO_RDFLAG(sc, pin_num, GPIOOUT); > + CC_GPIO_WRFLAG(sc, pin_num, GPIOOUT, !pin_high); > + break; > + } > + > + CC_GPIO_UNLOCK(sc); > + > + return (error); > +} > + > +static int > +chipc_gpio_pin_getcaps(device_t dev, uint32_t pin_num, uint32_t *caps) > +{ > + struct chipc_gpio_softc *sc = device_get_softc(dev); > + > + if (!CC_GPIO_VALID_PIN(pin_num)) > + return (EINVAL); > + > + *caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE); > + > + if (!CC_GPIO_QUIRK(sc, NO_PULLUPDOWN)) > + *caps |= (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN); > + > + if (!CC_GPIO_QUIRK(sc, NO_DCTIMER)) > + *caps |= GPIO_PIN_PULSATE; > + > + return (0); > +} > + > +static int > +chipc_gpio_pin_getflags(device_t dev, uint32_t pin_num, uint32_t *flags) > +{ > + struct chipc_gpio_softc *sc = device_get_softc(dev); > + > + if (!CC_GPIO_VALID_PIN(pin_num)) > + return (EINVAL); > + > + CC_GPIO_LOCK(sc); > + > + switch (chipc_gpio_pin_get_mode(sc, pin_num)) { > + case CC_GPIO_PIN_INPUT: > + *flags = GPIO_PIN_INPUT; > + > + if (!CC_GPIO_QUIRK(sc, NO_PULLUPDOWN)) { > + if (CC_GPIO_RDFLAG(sc, pin_num, GPIOPU)) { > + *flags |= GPIO_PIN_PULLUP; > + } else if (CC_GPIO_RDFLAG(sc, pin_num, GPIOPD)) { > + *flags |= GPIO_PIN_PULLDOWN; > + } > + } > + break; > + > + case CC_GPIO_PIN_OUTPUT: > + *flags = GPIO_PIN_OUTPUT; > + > + if (!CC_GPIO_QUIRK(sc, NO_DCTIMER)) { > + if (CC_GPIO_RDFLAG(sc, pin_num, GPIOTIMEROUTMASK)) > + *flags |= GPIO_PIN_PULSATE; > + } > + > + break; > + > + case CC_GPIO_PIN_TRISTATE: > + *flags = GPIO_PIN_TRISTATE|GPIO_PIN_OUTPUT; > + break; > + } > + > + CC_GPIO_UNLOCK(sc); > + > + return (0); > +} > + > +static int > +chipc_gpio_pin_getname(device_t dev, uint32_t pin_num, char *name) > +{ > + int ret; > + > + if (!CC_GPIO_VALID_PIN(pin_num)) > + return (EINVAL); > + > + ret = snprintf(name, GPIOMAXNAME, "bhnd_gpio%02" PRIu32, pin_num); > + > + if (ret < 0) > + return (ENXIO); > + > + if (ret >= GPIOMAXNAME) > + return (ENOMEM); > + > + return (0); > +} > + > +static int > +chipc_gpio_pin_setflags(device_t dev, uint32_t pin_num, uint32_t flags) > +{ > + struct chipc_gpio_softc *sc; > + struct chipc_gpio_update upd; > + int error; > + > + sc = device_get_softc(dev); > + > + if (!CC_GPIO_VALID_PIN(pin_num)) > + return (EINVAL); > + > + /* Produce an update descriptor */ > + memset(&upd, 0, sizeof(upd)); > + if ((error = chipc_gpio_pin_update(sc, &upd, pin_num, flags))) > + return (error); > + > + /* Commit the update */ > + CC_GPIO_LOCK(sc); > + error = chipc_gpio_commit_update(sc, &upd); > + CC_GPIO_UNLOCK(sc); > + > + return (error); > +} > + > +static int > +chipc_gpio_pin_access_32(device_t dev, uint32_t first_pin, uint32_t > clear_pins, > + uint32_t change_pins, uint32_t *orig_pins) > +{ > + struct chipc_gpio_softc *sc; > + struct chipc_gpio_update upd; > + uint32_t out, outen, ctrl; > + uint32_t num_pins; > + int error; > + > + sc = device_get_softc(dev); > + > + if (first_pin >= CC_GPIO_NPINS) > + return (EINVAL); > + > + /* Determine the actual number of referenced pins */ > + if (clear_pins == 0 && change_pins == 0) { > + num_pins = CC_GPIO_NPINS - first_pin; > + } else { > + int num_clear_pins, num_change_pins; > + > + num_clear_pins = flsl((u_long)clear_pins); > + num_change_pins = flsl((u_long)change_pins); > + num_pins = MAX(num_clear_pins, num_change_pins); > + } > + > + /* Validate the full pin range */ > + if (!CC_GPIO_VALID_PINS(first_pin, num_pins)) > + return (EINVAL); > + > + /* Produce an update descriptor for all pins, relative to the > current > + * pin state */ > + CC_GPIO_LOCK(sc); > + memset(&upd, 0, sizeof(upd)); > + > + out = CC_GPIO_RD4(sc, CHIPC_GPIOOUT); > + outen = CC_GPIO_RD4(sc, CHIPC_GPIOOUTEN); > + ctrl = CC_GPIO_RD4(sc, CHIPC_GPIOCTRL); > + > + for (uint32_t i = 0; i < num_pins; i++) { > + uint32_t pin; > + bool pin_high; > + > + pin = first_pin + i; > + > + /* The pin must be configured for output */ > + if ((outen & (1 << pin)) == 0) { > + CC_GPIO_UNLOCK(sc); > + return (EINVAL); > + } > + > + /* The pin must not tristated */ > + if ((ctrl & (1 << pin)) != 0) { > + CC_GPIO_UNLOCK(sc); > + return (EINVAL); > + } > + > + /* Fetch current state */ > + if (out & (1 << pin)) { > + pin_high = true; > + } else { > + pin_high = false; > + } > + > + /* Apply clear/toggle request */ > + if (clear_pins & (1 << pin)) > + pin_high = false; > + > + if (change_pins & (1 << pin)) > + pin_high = !pin_high; > + > + /* Add to our update descriptor */ > + CC_GPIO_UPDATE(&upd, pin, out, pin_high); > + } > + > + /* Commit the update */ > + error = chipc_gpio_commit_update(sc, &upd); > + CC_GPIO_UNLOCK(sc); > + > + return (error); > +} > + > +static int > +chipc_gpio_pin_config_32(device_t dev, uint32_t first_pin, uint32_t > num_pins, > + uint32_t *pin_flags) > +{ > + struct chipc_gpio_softc *sc; > + struct chipc_gpio_update upd; > + int error; > + > + sc = device_get_softc(dev); > + > + if (!CC_GPIO_VALID_PINS(first_pin, num_pins)) > + return (EINVAL); > + > + /* Produce an update descriptor */ > + memset(&upd, 0, sizeof(upd)); > + for (uint32_t i = 0; i < num_pins; i++) { > + uint32_t pin, flags; > + > + pin = first_pin + i; > + flags = pin_flags[i]; > + > + /* As per the gpio_config_32 API documentation, any pins > for > + * which neither GPIO_PIN_OUTPUT or GPIO_PIN_INPUT are set > + * should be ignored and left unmodified */ > + if ((flags & (GPIO_PIN_OUTPUT|GPIO_PIN_INPUT)) == 0) > + continue; > + > + if ((error = chipc_gpio_pin_update(sc, &upd, pin, flags))) > + return (error); > + } > + > + /* Commit the update */ > + CC_GPIO_LOCK(sc); > + error = chipc_gpio_commit_update(sc, &upd); > + CC_GPIO_UNLOCK(sc); > + > + return (error); > +} > + > + > +/** > + * Commit a single @p reg register update. > + */ > +static void > +chipc_gpio_commit_reg(struct chipc_gpio_softc *sc, bus_size_t offset, > + struct chipc_gpio_reg *reg) > +{ > + uint32_t value; > + > + CC_GPIO_LOCK_ASSERT(sc, MA_OWNED); > + > + if (reg->mask == 0) > + return; > + > + value = bhnd_bus_read_4(sc->mem_res, offset); > + value &= ~reg->mask; > + value |= reg->value; > + > + bhnd_bus_write_4(sc->mem_res, offset, value); > +} > + > +/** > + * Commit the set of GPIO register updates described by @p update. > + */ > +static int > +chipc_gpio_commit_update(struct chipc_gpio_softc *sc, > + struct chipc_gpio_update *update) > +{ > + CC_GPIO_LOCK_ASSERT(sc, MA_OWNED); > + > + /* Commit pulldown/pullup before potentially disabling an output > pin */ > + chipc_gpio_commit_reg(sc, CHIPC_GPIOPD, &update->pulldown); > + chipc_gpio_commit_reg(sc, CHIPC_GPIOPU, &update->pullup); > + > + /* Commit output settings before potentially enabling an output > pin */ > + chipc_gpio_commit_reg(sc, CHIPC_GPIOTIMEROUTMASK, > + &update->timeroutmask); > + chipc_gpio_commit_reg(sc, CHIPC_GPIOOUT, &update->out); > + > + /* Commit input/output/tristate modes */ > + chipc_gpio_commit_reg(sc, CHIPC_GPIOOUTEN, &update->outen); > + chipc_gpio_commit_reg(sc, CHIPC_GPIOCTRL, &update->ctrl); > + > + return (0); > +} > + > +/** > + * Apply the changes described by @p flags for @p pin_num to the given @p > update > + * descriptor. > + */ > +static int > +chipc_gpio_pin_update(struct chipc_gpio_softc *sc, > + struct chipc_gpio_update *update, uint32_t pin_num, uint32_t flags) > +{ > + chipc_gpio_pin_mode mode; > + int error; > + > + if (!CC_GPIO_VALID_PIN(pin_num)) > + return (EINVAL); > + > + /* Verify flag compatibility and determine the pin mode */ > + if ((error = chipc_gpio_check_flags(sc, pin_num, flags, &mode))) > + return (error); > + > + /* Apply the mode-specific changes */ > + switch (mode) { > + case CC_GPIO_PIN_INPUT: > + CC_GPIO_UPDATE(update, pin_num, pullup, false); > + CC_GPIO_UPDATE(update, pin_num, pulldown, false); > + CC_GPIO_UPDATE(update, pin_num, out, false); > + CC_GPIO_UPDATE(update, pin_num, outen, false); > + CC_GPIO_UPDATE(update, pin_num, timeroutmask, false); > + CC_GPIO_UPDATE(update, pin_num, ctrl, false); > + > + if (flags & GPIO_PIN_PULLUP) { > + CC_GPIO_UPDATE(update, pin_num, pullup, true); > + } else if (flags & GPIO_PIN_PULLDOWN) { > + CC_GPIO_UPDATE(update, pin_num, pulldown, true); > + } > + > + return (0); > + > + case CC_GPIO_PIN_OUTPUT: > + CC_GPIO_UPDATE(update, pin_num, pullup, false); > + CC_GPIO_UPDATE(update, pin_num, pulldown, false); > + CC_GPIO_UPDATE(update, pin_num, outen, true); > + CC_GPIO_UPDATE(update, pin_num, timeroutmask, false); > + CC_GPIO_UPDATE(update, pin_num, ctrl, false); > + > + if (flags & GPIO_PIN_PRESET_HIGH) { > + CC_GPIO_UPDATE(update, pin_num, out, true); > + } else if (flags & GPIO_PIN_PRESET_LOW) { > + CC_GPIO_UPDATE(update, pin_num, out, false); > + } > + > + if (flags & GPIO_PIN_PULSATE) > + CC_GPIO_UPDATE(update, pin_num, timeroutmask, > true); > + > + return (0); > + > + case CC_GPIO_PIN_TRISTATE: > + CC_GPIO_UPDATE(update, pin_num, pullup, false); > + CC_GPIO_UPDATE(update, pin_num, pulldown, false); > + CC_GPIO_UPDATE(update, pin_num, out, false); > + CC_GPIO_UPDATE(update, pin_num, outen, false); > + CC_GPIO_UPDATE(update, pin_num, timeroutmask, false); > + CC_GPIO_UPDATE(update, pin_num, ctrl, true); > + > + if (flags & GPIO_PIN_OUTPUT) > + CC_GPIO_UPDATE(update, pin_num, outen, true); > + > + return (0); > + } > + > + device_printf(sc->dev, "unknown pin mode %d\n", mode); > + return (EINVAL); > +} > + > +/** > + * Verify that @p flags are valid for use with @p pin_num, and on success, > + * return the pin mode described by @p flags in @p mode. > + * > + * @param sc GPIO driver instance state. > + * @param pin_num The pin number to configure. > + * @param flags The pin flags to be validated. > + * @param[out] mode On success, will be populated with the GPIO pin > mode > + * defined by @p flags. > + * > + * @retval 0 success > + * @retval EINVAL if @p flags are invalid. > + */ > +static int > +chipc_gpio_check_flags(struct chipc_gpio_softc *sc, uint32_t pin_num, > + uint32_t flags, chipc_gpio_pin_mode *mode) > +{ > + uint32_t mode_flag, input_flag, output_flag; > + > + CC_GPIO_ASSERT_VALID_PIN(sc, pin_num); > + > + mode_flag = flags & (GPIO_PIN_OUTPUT | GPIO_PIN_INPUT | > + GPIO_PIN_TRISTATE); > + output_flag = flags & (GPIO_PIN_PRESET_HIGH | GPIO_PIN_PRESET_LOW > + | GPIO_PIN_PULSATE); > + input_flag = flags & (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN); > + > + switch (mode_flag) { > + case GPIO_PIN_OUTPUT: > + /* No input flag(s) should be set */ > + if (input_flag != 0) > + return (EINVAL); > + > + /* Validate our output flag(s) */ > + switch (output_flag) { > + case GPIO_PIN_PRESET_HIGH: > + case GPIO_PIN_PRESET_LOW: > + case (GPIO_PIN_PRESET_HIGH|GPIO_PIN_PULSATE): > + case (GPIO_PIN_PRESET_LOW|GPIO_PIN_PULSATE): > + case 0: > + /* Check for unhandled flags */ > + if ((flags & ~(mode_flag | output_flag)) != 0) > + return (EINVAL); > + > + *mode = CC_GPIO_PIN_OUTPUT; > + return (0); > + > + default: > + /* Incompatible output flags */ > + return (EINVAL); > + } > + > + case GPIO_PIN_INPUT: > + /* No output flag(s) should be set */ > + if (output_flag != 0) > + return (EINVAL); > + > + /* Validate our input flag(s) */ > + switch (input_flag) { > + case GPIO_PIN_PULLUP: > + case GPIO_PIN_PULLDOWN: > + case 0: > + /* Check for unhandled flags */ > + if ((flags & ~(mode_flag | input_flag)) != 0) > + return (EINVAL); > + > + *mode = CC_GPIO_PIN_INPUT; > + return (0); > + > + default: > + /* Incompatible input flags */ > + return (EINVAL); > + } > + > + break; > + > + case (GPIO_PIN_TRISTATE|GPIO_PIN_OUTPUT): > + case GPIO_PIN_TRISTATE: > + /* No input or output flag(s) should be set */ > + if (input_flag != 0 || output_flag != 0) > + return (EINVAL); > + > + /* Check for unhandled flags */ > + if ((flags & ~mode_flag) != 0) > + return (EINVAL); > + > + *mode = CC_GPIO_PIN_TRISTATE; > + return (0); > + > + default: > + /* Incompatible mode flags */ > + return (EINVAL); > + } > +} > + > +/** > + * Return the current pin mode for @p pin_num. > + * > + * @param sc GPIO driver instance state. > + * @param pin_num The pin number to query. > + */ > +static chipc_gpio_pin_mode > +chipc_gpio_pin_get_mode(struct chipc_gpio_softc *sc, uint32_t pin_num) > +{ > + CC_GPIO_LOCK_ASSERT(sc, MA_OWNED); > + CC_GPIO_ASSERT_VALID_PIN(sc, pin_num); > + > + if (CC_GPIO_RDFLAG(sc, pin_num, GPIOCTRL)) { > + return (CC_GPIO_PIN_TRISTATE); > + } else if (CC_GPIO_RDFLAG(sc, pin_num, GPIOOUTEN)) { > + return (CC_GPIO_PIN_OUTPUT); > + } else { > + return (CC_GPIO_PIN_INPUT); > + } > +} > + > +static device_method_t chipc_gpio_methods[] = { > + /* Device interface */ > + DEVMETHOD(device_probe, chipc_gpio_probe), > + DEVMETHOD(device_attach, chipc_gpio_attach), > + DEVMETHOD(device_detach, chipc_gpio_detach), > + > + /* GPIO interface */ > + DEVMETHOD(gpio_get_bus, chipc_gpio_get_bus), > + DEVMETHOD(gpio_pin_max, chipc_gpio_pin_max), > + DEVMETHOD(gpio_pin_getname, chipc_gpio_pin_getname), > + DEVMETHOD(gpio_pin_getflags, chipc_gpio_pin_getflags), > + DEVMETHOD(gpio_pin_getcaps, chipc_gpio_pin_getcaps), > + DEVMETHOD(gpio_pin_setflags, chipc_gpio_pin_setflags), > + DEVMETHOD(gpio_pin_get, chipc_gpio_pin_get), > + DEVMETHOD(gpio_pin_set, chipc_gpio_pin_set), > + DEVMETHOD(gpio_pin_toggle, chipc_gpio_pin_toggle), > + DEVMETHOD(gpio_pin_access_32, chipc_gpio_pin_access_32), > + DEVMETHOD(gpio_pin_config_32, chipc_gpio_pin_config_32), > + > + DEVMETHOD_END > +}; > + > +static devclass_t gpio_devclass; > + > +DEFINE_CLASS_0(gpio, chipc_gpio_driver, chipc_gpio_methods, sizeof(struct > chipc_gpio_softc)); > +EARLY_DRIVER_MODULE(chipc_gpio, bhnd_chipc, chipc_gpio_driver, > + gpio_devclass, NULL, NULL, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE); > + > +MODULE_DEPEND(chipc_gpio, bhnd, 1, 1, 1); > +MODULE_DEPEND(chipc_gpio, gpiobus, 1, 1, 1); > +MODULE_VERSION(chipc_gpio, 1); > > Added: head/sys/dev/bhnd/cores/chipc/chipc_gpiovar.h > ============================================================ > ================== > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ head/sys/dev/bhnd/cores/chipc/chipc_gpiovar.h Wed Nov 22 > 23:10:20 2017 (r326109) > @@ -0,0 +1,161 @@ > +/*- > + * Copyright (c) 2017 The FreeBSD Foundation > + * All rights reserved. > + * > + * This software was developed by Landon Fuller under sponsorship from > + * the FreeBSD Foundation. > + * > + * 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 AUTHOR 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 AUTHOR 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. > + * > + * $FreeBSD$ > + */ > + > +#ifndef _BHND_CORES_CHIPC_CHIPC_GPIOVAR_H_ > +#define _BHND_CORES_CHIPC_CHIPC_GPIOVAR_H_ > + > +#include > +#include > + > +#include > +#include > + > +#include > + > +/** > + * ChipCommon GPIO device quirks. > + */ > +enum { > + /** > + * No GPIO event support. > + * > + * The CHIPC_GPIOEVENT, CHIPC_GPIOEVENT_INTM, and > + * CHIPC_GPIOEVENT_INTPOLARITY registers are not available. > + */ > + CC_GPIO_QUIRK_NO_EVENTS = (1<<0), > + > + /** > + * No GPIO duty-cycle timer support. > + * > + * The CHIPC_GPIOTIMERVAL and CHIPC_GPIOTIMEROUTMASK registers are > not > + * available. > + */ > + CC_GPIO_QUIRK_NO_DCTIMER = (1<<1), > + > + /** > + * No GPIO pull-up/pull-down configuration support. > + * > + * The CHIPC_GPIOPU and CHIPC_GPIOPD registers are not available. > + */ > + CC_GPIO_QUIRK_NO_PULLUPDOWN = (1<<2), > + > + /** > + * Do not attach a child gpioc(4) device. > + * > + * This is primarily intended for use on bridged Wi-Fi adapters, > where > + * userspace modification of GPIO pin configuration could introduce > + * significant undesirable behavior. > + */ > + CC_GPIO_QUIRK_NO_GPIOC = (1<<3), > +}; > + > > *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** > >