From owner-svn-src-head@freebsd.org Wed Apr 4 13:12:51 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id D4EFAF8DA70; Wed, 4 Apr 2018 13:12:50 +0000 (UTC) (envelope-from mw@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 7046E7A2AA; Wed, 4 Apr 2018 13:12:50 +0000 (UTC) (envelope-from mw@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 6B281142FA; Wed, 4 Apr 2018 13:12:50 +0000 (UTC) (envelope-from mw@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w34DCoSx062710; Wed, 4 Apr 2018 13:12:50 GMT (envelope-from mw@FreeBSD.org) Received: (from mw@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w34DCoWm062707; Wed, 4 Apr 2018 13:12:50 GMT (envelope-from mw@FreeBSD.org) Message-Id: <201804041312.w34DCoWm062707@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mw set sender to mw@FreeBSD.org using -f From: Marcin Wojtas Date: Wed, 4 Apr 2018 13:12:50 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r332021 - head/sys/arm/mv X-SVN-Group: head X-SVN-Commit-Author: mw X-SVN-Commit-Paths: head/sys/arm/mv X-SVN-Commit-Revision: 332021 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 04 Apr 2018 13:12:51 -0000 Author: mw Date: Wed Apr 4 13:12:49 2018 New Revision: 332021 URL: https://svnweb.freebsd.org/changeset/base/332021 Log: Improve interrupt and resource allocation in Marvell GPIO driver This patch adds support for more than one interrupts in GPIO controller. It reads necessary information (such as cell size) from FDT, so there are no magic numbers. Note that interrupts are still not working, but this patch makes one good step in correct direction Submitted by: Patryk Duda Obtained from: Semihalf Sponsored by: Stormshield Differential Revision: https://reviews.freebsd.org/D14754 Modified: head/sys/arm/mv/gpio.c head/sys/arm/mv/mvvar.h Modified: head/sys/arm/mv/gpio.c ============================================================================== --- head/sys/arm/mv/gpio.c Wed Apr 4 13:08:51 2018 (r332020) +++ head/sys/arm/mv/gpio.c Wed Apr 4 13:12:49 2018 (r332021) @@ -67,7 +67,10 @@ __FBSDID("$FreeBSD$"); #define DEBOUNCE_CHECK_TICKS ((hz / 1000) * DEBOUNCE_CHECK_MS) struct mv_gpio_softc { - struct resource * res[GPIO_MAX_INTR_COUNT + 1]; + struct resource * mem_res; + int mem_rid; + struct resource * irq_res[GPIO_MAX_INTR_COUNT]; + int irq_rid[GPIO_MAX_INTR_COUNT]; void *ih_cookie[GPIO_MAX_INTR_COUNT]; bus_space_tag_t bst; bus_space_handle_t bsh; @@ -83,8 +86,6 @@ struct mv_gpio_softc { int *debounce_counters; }; -extern struct resource_spec mv_gpio_res[]; - static struct mv_gpio_softc *mv_gpio_softc = NULL; static uint32_t gpio_setup[MV_GPIO_MAX_NPINS]; @@ -119,6 +120,15 @@ static void mv_gpio_int_ack(uint32_t pin); static void mv_gpio_value_set(uint32_t pin, uint8_t val); static uint32_t mv_gpio_value_get(uint32_t pin, uint8_t exclude_polar); +static void mv_gpio_intr_mask(int pin); +static void mv_gpio_intr_unmask(int pin); +int mv_gpio_setup_intrhandler(const char *name, driver_filter_t *filt, + void (*hand)(void *), void *arg, int pin, int flags, void **cookiep); + +int mv_gpio_configure(uint32_t pin, uint32_t flags, uint32_t mask); +void mv_gpio_out(uint32_t pin, uint8_t val, uint8_t enable); +uint8_t mv_gpio_in(uint32_t pin); + #define MV_GPIO_LOCK() mtx_lock_spin(&mv_gpio_softc->mutex) #define MV_GPIO_UNLOCK() mtx_unlock_spin(&mv_gpio_softc->mutex) #define MV_GPIO_ASSERT_LOCKED() mtx_assert(&mv_gpio_softc->mutex, MA_OWNED) @@ -171,9 +181,12 @@ mv_gpio_probe(device_t dev) static int mv_gpio_attach(device_t dev) { - int error, i; + int error, i, size; struct mv_gpio_softc *sc; uint32_t dev_id, rev_id; + pcell_t pincnt = 0; + pcell_t irq_cells = 0; + phandle_t iparent; sc = (struct mv_gpio_softc *)device_get_softc(dev); if (sc == NULL) @@ -201,10 +214,45 @@ mv_gpio_attach(device_t dev) sc->use_high = 1; } else { - device_printf(dev, "unknown chip id=0x%x\n", dev_id); + if (OF_getencprop(ofw_bus_get_node(dev), "pin-count", &pincnt, + sizeof(pcell_t)) >= 0 || + OF_getencprop(ofw_bus_get_node(dev), "ngpios", &pincnt, + sizeof(pcell_t)) >= 0) { + sc->pin_num = pincnt; + device_printf(dev, "%d pins available\n", sc->pin_num); + } else { + device_printf(dev, "ERROR: no pin-count entry found!\n"); + return (ENXIO); + } + } + + /* Find root interrupt controller */ + iparent = ofw_bus_find_iparent(ofw_bus_get_node(dev)); + if (iparent == 0) { + device_printf(dev, "No interrupt-parrent found. " + "Error in DTB\n"); return (ENXIO); + } else { + /* While at parent - store interrupt cells prop */ + if (OF_searchencprop(OF_node_from_xref(iparent), + "#interrupt-cells", &irq_cells, sizeof(irq_cells)) == -1) { + device_printf(dev, "DTB: Missing #interrupt-cells " + "property in interrupt parent node\n"); + return (ENXIO); + } } + size = OF_getproplen(ofw_bus_get_node(dev), "interrupts"); + if (size != -1) { + size = size / sizeof(pcell_t); + size = size / irq_cells; + sc->irq_num = size; + device_printf(dev, "%d IRQs available\n", sc->irq_num); + } else { + device_printf(dev, "ERROR: no interrupts entry found!\n"); + return (ENXIO); + } + sc->debounce_callouts = (struct callout **)malloc(sc->pin_num * sizeof(struct callout *), M_DEVBUF, M_WAITOK | M_ZERO); if (sc->debounce_callouts == NULL) @@ -217,16 +265,31 @@ mv_gpio_attach(device_t dev) mtx_init(&sc->mutex, device_get_nameunit(dev), NULL, MTX_SPIN); - error = bus_alloc_resources(dev, mv_gpio_res, sc->res); - if (error) { + sc->mem_rid = 0; + sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid, + RF_ACTIVE); + + if (!sc->mem_res) { mtx_destroy(&sc->mutex); - device_printf(dev, "could not allocate resources\n"); + device_printf(dev, "could not allocate memory window\n"); return (ENXIO); } - sc->bst = rman_get_bustag(sc->res[0]); - sc->bsh = rman_get_bushandle(sc->res[0]); + sc->bst = rman_get_bustag(sc->mem_res); + sc->bsh = rman_get_bushandle(sc->mem_res); + for (i = 0; i < sc->irq_num; i++) { + sc->irq_rid[i] = i; + sc->irq_res[i] = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &sc->irq_rid[i], RF_ACTIVE); + if (!sc->irq_res[i]) { + mtx_destroy(&sc->mutex); + device_printf(dev, + "could not allocate gpio%d interrupt\n", i+1); + return (ENXIO); + } + } + /* Disable all interrupts */ bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_EDGE_MASK, 0); bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_LEV_MASK, 0); @@ -241,12 +304,13 @@ mv_gpio_attach(device_t dev) } for (i = 0; i < sc->irq_num; i++) { - if (bus_setup_intr(dev, sc->res[1 + i], + if (bus_setup_intr(dev, sc->irq_res[i], INTR_TYPE_MISC, (driver_filter_t *)mv_gpio_intr, NULL, sc, &sc->ih_cookie[i]) != 0) { mtx_destroy(&sc->mutex); - bus_release_resources(dev, mv_gpio_res, sc->res); + bus_release_resource(dev, SYS_RES_IRQ, + sc->irq_rid[i], sc->irq_res[i]); device_printf(dev, "could not set up intr %d\n", i); return (ENXIO); } @@ -419,15 +483,21 @@ mv_gpio_exec_intr_handlers(uint32_t status, int high) static void mv_gpio_intr_handler(int pin) { - struct intr_event *event; +#ifdef INTRNG + struct intr_irqsrc isrc; MV_GPIO_ASSERT_LOCKED(); - event = gpio_events[pin]; - if (event == NULL || TAILQ_EMPTY(&event->ie_handlers)) +#ifdef INTR_SOLO + isrc.isrc_filter = NULL; +#endif + isrc.isrc_event = gpio_events[pin]; + + if (isrc.isrc_event == NULL || TAILQ_EMPTY(&isrc.isrc_event->ie_handlers)) return; - intr_event_handle(event, NULL); + intr_isrc_dispatch(&isrc, NULL); +#endif } int Modified: head/sys/arm/mv/mvvar.h ============================================================================== --- head/sys/arm/mv/mvvar.h Wed Apr 4 13:08:51 2018 (r332020) +++ head/sys/arm/mv/mvvar.h Wed Apr 4 13:12:49 2018 (r332021) @@ -83,15 +83,6 @@ extern const struct decode_win *xor_wins; extern int idma_wins_no; extern int xor_wins_no; -/* Function prototypes */ -int mv_gpio_setup_intrhandler(const char *name, driver_filter_t *filt, - void (*hand)(void *), void *arg, int pin, int flags, void **cookiep); -void mv_gpio_intr_mask(int pin); -void mv_gpio_intr_unmask(int pin); -int mv_gpio_configure(uint32_t pin, uint32_t flags, uint32_t mask); -void mv_gpio_out(uint32_t pin, uint8_t val, uint8_t enable); -uint8_t mv_gpio_in(uint32_t pin); - int soc_decode_win(void); void soc_id(uint32_t *dev, uint32_t *rev); void soc_dump_decode_win(void);