From owner-svn-src-head@FreeBSD.ORG Fri Sep 14 10:06:56 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id CFBD0106566B; Fri, 14 Sep 2012 10:06:56 +0000 (UTC) (envelope-from gber@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id B0EAF8FC15; Fri, 14 Sep 2012 10:06:56 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8EA6uZc094102; Fri, 14 Sep 2012 10:06:56 GMT (envelope-from gber@svn.freebsd.org) Received: (from gber@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8EA6upc094100; Fri, 14 Sep 2012 10:06:56 GMT (envelope-from gber@svn.freebsd.org) Message-Id: <201209141006.q8EA6upc094100@svn.freebsd.org> From: Grzegorz Bernacki Date: Fri, 14 Sep 2012 10:06:56 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r240493 - head/sys/arm/mv X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 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: Fri, 14 Sep 2012 10:06:56 -0000 Author: gber Date: Fri Sep 14 10:06:56 2012 New Revision: 240493 URL: http://svn.freebsd.org/changeset/base/240493 Log: Implement MSI support. MSI are implemented via Inbound Shared Doorbell 1 interrupts. Interrupts are triggered by writing to Software Triggered Interrupt registeri (PCIe card using physical address of this register in BAR0 space). There are 32 interrupts available. It can be increased by using Doorbell 2 and Doorbell 3 registers to 96 interrupts. Obtained from: Marvell, Semihalf Modified: head/sys/arm/mv/mv_pci.c Modified: head/sys/arm/mv/mv_pci.c ============================================================================== --- head/sys/arm/mv/mv_pci.c Fri Sep 14 10:05:01 2012 (r240492) +++ head/sys/arm/mv/mv_pci.c Fri Sep 14 10:06:56 2012 (r240493) @@ -53,6 +53,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #include #include @@ -73,6 +75,12 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef DEBUG +#define debugf(fmt, args...) do { printf(fmt,##args); } while (0) +#else +#define debugf(fmt, args...) +#endif + #define PCI_CFG_ENA (1 << 31) #define PCI_CFG_BUS(bus) (((bus) & 0xff) << 16) #define PCI_CFG_DEV(dev) (((dev) & 0x1f) << 11) @@ -81,7 +89,6 @@ __FBSDID("$FreeBSD$"); #define PCI_REG_CFG_ADDR 0x0C78 #define PCI_REG_CFG_DATA 0x0C7C -#define PCI_REG_P2P_CONF 0x1D14 #define PCIE_REG_CFG_ADDR 0x18F8 #define PCIE_REG_CFG_DATA 0x18FC @@ -127,6 +134,9 @@ struct mv_pcib_softc { bus_space_tag_t sc_bst; int sc_rid; + struct mtx sc_msi_mtx; + uint32_t sc_msi_bitmap; + int sc_busnr; /* Host bridge bus number */ int sc_devnr; /* Host bridge device number */ int sc_type; @@ -166,6 +176,11 @@ static uint32_t mv_pcib_read_config(devi static void mv_pcib_write_config(device_t, u_int, u_int, u_int, u_int, uint32_t, int); static int mv_pcib_route_interrupt(device_t, device_t, int); +#if defined(SOC_MV_ARMADAXP) +static int mv_pcib_alloc_msi(device_t, device_t, int, int, int *); +static int mv_pcib_map_msi(device_t, device_t, int, uint64_t *, uint32_t *); +static int mv_pcib_release_msi(device_t, device_t, int, int *); +#endif /* * Bus interface definitions. @@ -190,7 +205,13 @@ static device_method_t mv_pcib_methods[] DEVMETHOD(pcib_read_config, mv_pcib_read_config), DEVMETHOD(pcib_write_config, mv_pcib_write_config), DEVMETHOD(pcib_route_interrupt, mv_pcib_route_interrupt), - + +#if defined(SOC_MV_ARMADAXP) + DEVMETHOD(pcib_alloc_msi, mv_pcib_alloc_msi), + DEVMETHOD(pcib_release_msi, mv_pcib_release_msi), + DEVMETHOD(pcib_map_msi, mv_pcib_map_msi), +#endif + /* OFW bus interface */ DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), @@ -318,6 +339,7 @@ mv_pcib_attach(device_t self) device_add_child(self, "pci_ep", -1); } + mtx_init(&sc->sc_msi_mtx, "msi_mtx", NULL, MTX_DEF); return (bus_generic_attach(self)); error: @@ -927,3 +949,80 @@ mv_pcib_intr_info(phandle_t node, struct return (0); } +#if defined(SOC_MV_ARMADAXP) +static int +mv_pcib_map_msi(device_t dev, device_t child, int irq, uint64_t *addr, + uint32_t *data) +{ + struct mv_pcib_softc *sc; + + sc = device_get_softc(dev); + irq = irq - MSI_IRQ; + + /* validate parameters */ + if (isclr(&sc->sc_msi_bitmap, irq)) { + device_printf(dev, "invalid MSI 0x%x\n", irq); + return (EINVAL); + } + + mv_msi_data(irq, addr, data); + + debugf("%s: irq: %d addr: %jx data: %x\n", + __func__, irq, *addr, *data); + + return (0); +} + +static int +mv_pcib_alloc_msi(device_t dev, device_t child, int count, + int maxcount __unused, int *irqs) +{ + struct mv_pcib_softc *sc; + u_int start = 0, i; + + if (powerof2(count) == 0 || count > MSI_IRQ_NUM) + return (EINVAL); + + sc = device_get_softc(dev); + mtx_lock(&sc->sc_msi_mtx); + + for (start = 0; (start + count) < MSI_IRQ_NUM; start++) { + for (i = start; i < start + count; i++) { + if (isset(&sc->sc_msi_bitmap, i)) + break; + } + if (i == start + count) + break; + } + + if ((start + count) == MSI_IRQ_NUM) { + mtx_unlock(&sc->sc_msi_mtx); + return (ENXIO); + } + + for (i = start; i < start + count; i++) { + setbit(&sc->sc_msi_bitmap, i); + irqs[i] = MSI_IRQ + i; + } + debugf("%s: start: %x count: %x\n", __func__, start, count); + + mtx_unlock(&sc->sc_msi_mtx); + return (0); +} + +static int +mv_pcib_release_msi(device_t dev, device_t child, int count, int *irqs) +{ + struct mv_pcib_softc *sc; + u_int i; + + sc = device_get_softc(dev); + mtx_lock(&sc->sc_msi_mtx); + + for (i = 0; i < count; i++) + clrbit(&sc->sc_msi_bitmap, irqs[i] - MSI_IRQ); + + mtx_unlock(&sc->sc_msi_mtx); + return (0); +} +#endif