From owner-svn-src-head@freebsd.org Thu Dec 24 18:33:09 2015 Return-Path: Delivered-To: svn-src-head@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 57099A50941; Thu, 24 Dec 2015 18:33:09 +0000 (UTC) (envelope-from adrian@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 mx1.freebsd.org (Postfix) with ESMTPS id 26B451C85; Thu, 24 Dec 2015 18:33:09 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id tBOIX8lU061928; Thu, 24 Dec 2015 18:33:08 GMT (envelope-from adrian@FreeBSD.org) Received: (from adrian@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id tBOIX8pV061926; Thu, 24 Dec 2015 18:33:08 GMT (envelope-from adrian@FreeBSD.org) Message-Id: <201512241833.tBOIX8pV061926@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: adrian set sender to adrian@FreeBSD.org using -f From: Adrian Chadd Date: Thu, 24 Dec 2015 18:33:08 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r292700 - head/sys/mips/rt305x X-SVN-Group: head 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.20 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: Thu, 24 Dec 2015 18:33:09 -0000 Author: adrian Date: Thu Dec 24 18:33:08 2015 New Revision: 292700 URL: https://svnweb.freebsd.org/changeset/base/292700 Log: [rt305x] add PCI bus / resource allocation code for the MT7620. This is based on the sys/arm/mv/ pci resource/allocation code. Submitted by: Stanislav Galabov Added: head/sys/mips/rt305x/rt305x_pci.c (contents, props changed) head/sys/mips/rt305x/rt305x_pcireg.h (contents, props changed) Added: head/sys/mips/rt305x/rt305x_pci.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/mips/rt305x/rt305x_pci.c Thu Dec 24 18:33:08 2015 (r292700) @@ -0,0 +1,955 @@ +/*- + * Copyright (c) 2015 Stanislav Galabov. + * + * 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. + * + * This is based on the pci allocator code from sys/dev/arm/mv/: + * + * Copyright (c) 2008 MARVELL INTERNATIONAL LTD. + * Copyright (c) 2010 The FreeBSD Foundation + * Copyright (c) 2010-2012 Semihalf + * All rights reserved. + * + * Developed by Semihalf. + */ +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include "pcib_if.h" + +#include +#include +#include + +struct mtx rt305x_pci_mtx; +MTX_SYSINIT(rt305x_pci_mtx, &rt305x_pci_mtx, "rt305x PCI/PCIe mutex", MTX_SPIN); + +struct rt305x_pci_softc { + device_t sc_dev; + + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh; + + int sc_busno; + + struct rman sc_mem_rman; + struct rman sc_io_rman; + struct rman sc_irq_rman; + + bus_addr_t sc_mem_base; + bus_addr_t sc_mem_size; + uint32_t sc_mem_map[(256*1024*1024) / + (PCI_MIN_MEM_ALLOC * BITS_PER_UINT32)]; + + bus_addr_t sc_io_base; + bus_addr_t sc_io_size; + uint32_t sc_io_map[(16*1024*1024) / + (PCI_MIN_IO_ALLOC * BITS_PER_UINT32)]; + + struct intr_event *sc_eventstab[RT305X_PCI_NIRQS]; + mips_intrcnt_t sc_intr_counter[RT305X_PCI_NIRQS]; + + int pcie_link_status; +}; + +static void rt305x_pci_phy_init(device_t); +static void rt305x_pci_init(device_t); +static int rt305x_pcib_init(device_t, int, int); +static int rt305x_pci_intr(void *); + +static void rt305x_pci_dump_regs(device_t); + +static struct rt305x_pci_softc *rt_sc = NULL; + +static int +rt305x_pci_probe(device_t dev) +{ + + return (BUS_PROBE_NOWILDCARD); +} + +static int +rt305x_pci_attach(device_t dev) +{ + struct rt305x_pci_softc *sc = device_get_softc(dev); + + rt_sc = sc; + + sc->sc_dev = dev; + sc->sc_mem_base = PCIE_MEM_BASE; + sc->sc_mem_size = 0x10000000; + sc->sc_io_base = PCIE_IO_BASE; + sc->sc_io_size = 0x10000; + + sc->sc_bsh = MIPS_PHYS_TO_KSEG1(PCIE_BASE); + sc->sc_bst = mips_bus_space_generic; + + sc->sc_mem_rman.rm_type = RMAN_ARRAY; + sc->sc_mem_rman.rm_descr = "rt305x pci memory window"; + if (rman_init(&sc->sc_mem_rman) != 0 || + rman_manage_region(&sc->sc_mem_rman, sc->sc_mem_base, + sc->sc_mem_base + sc->sc_mem_size - 1) != 0) { + panic("%s: failed to set up memory rman", __FUNCTION__); + } + + sc->sc_io_rman.rm_type = RMAN_ARRAY; + sc->sc_io_rman.rm_descr = "rt305x pci io window"; + if (rman_init(&sc->sc_io_rman) != 0 || + rman_manage_region(&sc->sc_io_rman, sc->sc_io_base, + sc->sc_io_base + sc->sc_io_size - 1) != 0) { + panic("%s: failed to set up io rman", __FUNCTION__); + } + + sc->sc_irq_rman.rm_type = RMAN_ARRAY; + sc->sc_irq_rman.rm_descr = "rt305x pci irqs"; + if (rman_init(&sc->sc_irq_rman) != 0 || + rman_manage_region(&sc->sc_irq_rman, RT305X_PCIE0_IRQ, + RT305X_PCIE0_IRQ) != 0) { + panic("%s: failed to set up irq rman", __FUNCTION__); + } + + cpu_establish_hardintr("pci", rt305x_pci_intr, NULL, sc, + RT305X_PCI_INTR_PIN, INTR_TYPE_MISC | INTR_EXCL, NULL); + + rt305x_pci_phy_init(dev); + + rt305x_pci_init(dev); + + rt305x_pci_dump_regs(dev); + + rt305x_pcib_init(dev, 0, PCI_SLOTMAX); + + device_add_child(dev, "pci", -1); + + return (bus_generic_attach(dev)); +} + +static int +rt305x_pci_read_ivar(device_t dev, device_t child, int which, + uintptr_t *result) +{ + struct rt305x_pci_softc *sc = device_get_softc(dev); + + switch (which) { + case PCIB_IVAR_DOMAIN: + *result = device_get_unit(dev); + return (0); + case PCIB_IVAR_BUS: + *result = sc->sc_busno; + return (0); + } + + return (ENOENT); +} + +static int +rt305x_pci_write_ivar(device_t dev, device_t child, int which, + uintptr_t result) +{ + struct rt305x_pci_softc *sc = device_get_softc(dev); + + switch (which) { + case PCIB_IVAR_BUS: + sc->sc_busno = result; + return (0); + } + + return (ENOENT); +} + +static struct resource * +rt305x_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct rt305x_pci_softc *sc = device_get_softc(bus); + struct resource *rv; + struct rman *rm; + vm_offset_t va; + + switch (type) { + case SYS_RES_IRQ: + rm = &sc->sc_irq_rman; + break; + case SYS_RES_IOPORT: + rm = &sc->sc_io_rman; + break; + case SYS_RES_MEMORY: + rm = &sc->sc_mem_rman; + break; + default: + return (NULL); + } + + rv = rman_reserve_resource(rm, start, end, count, flags, child); + + if (rv == NULL) + return (NULL); + + rman_set_rid(rv, *rid); + + if (type != SYS_RES_IRQ) { + if (type == SYS_RES_MEMORY) { + va = (vm_offset_t)pmap_mapdev(start, count); + } else if (type == SYS_RES_IOPORT){ + va = (vm_offset_t)MIPS_PHYS_TO_KSEG1(start); + } + rman_set_bushandle(rv, va); + rman_set_virtual(rv, (void *)va); + rman_set_bustag(rv, mips_bus_space_generic); + } + + if (flags & RF_ACTIVE) { + if (bus_activate_resource(child, type, *rid, rv)) { + rman_release_resource(rv); + return (NULL); + } + } + + return (rv); +} + +static int +rt305x_pci_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + + return rman_activate_resource(r); +} + +static inline int +rt305x_idx_to_irq(int idx) +{ + + return ((idx == 0) ? RT305X_PCIE0_IRQ : + (idx == 1) ? RT305X_PCIE1_IRQ : + (idx == 2) ? RT305X_PCIE2_IRQ : -1); +} + +static inline int +rt305x_irq_to_idx(int irq) +{ + + return ((irq == RT305X_PCIE0_IRQ) ? 0 : + (irq == RT305X_PCIE1_IRQ) ? 1 : + (irq == RT305X_PCIE2_IRQ) ? 2 : -1); +} + +static void +rt305x_pci_mask_irq(void *source) +{ + + RT_WRITE32(rt_sc, RT305X_PCI_PCIENA, + RT_READ32(rt_sc, RT305X_PCI_PCIENA) & ~(1<<((int)source))); +} + +static void +rt305x_pci_unmask_irq(void *source) +{ + + RT_WRITE32(rt_sc, RT305X_PCI_PCIENA, + RT_READ32(rt_sc, RT305X_PCI_PCIENA) | (1<<((int)source))); +} + +static int +rt305x_pci_setup_intr(device_t bus, device_t child, struct resource *ires, + int flags, driver_filter_t *filt, driver_intr_t *handler, + void *arg, void **cookiep) +{ + struct rt305x_pci_softc *sc = device_get_softc(bus); + struct intr_event *event; + int irq, error, irqidx; + + irq = rman_get_start(ires); + + if ((irqidx = rt305x_irq_to_idx(irq)) == -1) + panic("%s: bad irq %d", __FUNCTION__, irq); + + event = sc->sc_eventstab[irqidx]; + if (event == NULL) { + error = intr_event_create(&event, (void *)irq, 0, irq, + rt305x_pci_mask_irq, rt305x_pci_unmask_irq, NULL, NULL, + "pci intr%d:", irq); + + if (error == 0) { + sc->sc_eventstab[irqidx] = event; + sc->sc_intr_counter[irqidx] = + mips_intrcnt_create(event->ie_name); + } + else + return (error); + } + + intr_event_add_handler(event, device_get_nameunit(child), filt, + handler, arg, intr_priority(flags), flags, cookiep); + + mips_intrcnt_setname(sc->sc_intr_counter[irqidx], event->ie_fullname); + + rt305x_pci_unmask_irq((void*)irq); + + return (0); +} + +static int +rt305x_pci_teardown_intr(device_t dev, device_t child, struct resource *ires, + void *cookie) +{ + struct rt305x_pci_softc *sc = device_get_softc(dev); + int irq, result, irqidx; + + irq = rman_get_start(ires); + if ((irqidx = rt305x_irq_to_idx(irq)) == -1) + panic("%s: bad irq %d", __FUNCTION__, irq); + + if (sc->sc_eventstab[irqidx] == NULL) + panic("Trying to teardown unoccupied IRQ"); + + rt305x_pci_mask_irq((void*)irq); + + result = intr_event_remove_handler(cookie); + if (!result) + sc->sc_eventstab[irqidx] = NULL; + + return (result); +} + +static inline uint32_t +rt305x_pci_make_addr(int bus, int slot, int func, int reg) +{ + uint32_t addr; + + addr = (((reg & 0xf00) >> 8) << 24) | (bus << 16) | (slot << 11) | + (func << 8) | (reg & 0xfc) | (1 << 31); + + return (addr); +} + +static int +rt305x_pci_maxslots(device_t dev) +{ + + return (PCI_SLOTMAX); +} + +static uint32_t +rt305x_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func, + u_int reg, int bytes) +{ + struct rt305x_pci_softc *sc = device_get_softc(dev); + uint32_t addr = 0, data = 0; + + if (bus == 0 && (sc->pcie_link_status & (1<pcie_link_status & (1<sc_mem_base); + RT_WRITE32(sc, RT305X_PCI_IOBASE, sc->sc_io_base); + + RT_WRITE32(sc, RT305X_PCI_PCICFG, RT_READ32(sc, 0) & ~(1<<1)); + DELAY(500000); + if ((RT_READ32(sc, RT305X_PCI_PCIE0_STATUS) & 0x1) == 1) + sc->pcie_link_status = 1; + else + sc->pcie_link_status = 0; + + RT_WRITE32(sc, RT305X_PCI_PCIE0_BAR0SETUP, 0x7FFF0001); + RT_WRITE32(sc, RT305X_PCI_PCIE0_BAR1SETUP, 0x00000000); + RT_WRITE32(sc, RT305X_PCI_PCIE0_IMBASEBAR0, 0x00000000); + RT_WRITE32(sc, RT305X_PCI_PCIE0_CLASS, 0x06040001); + + tmp = rt305x_pci_read_config(dev, 0, 0, 0, 4, 4); + rt305x_pci_write_config(dev, 0, 0, 0, 4, tmp | 0x7, 4); + tmp = rt305x_pci_read_config(dev, 0, 0, 0, 0x70c, 4); + tmp &= ~(0xff)<<8; + tmp |= 0x50<<8; + rt305x_pci_write_config(dev, 0, 0, 0, 0x70c, tmp, 4); + tmp = rt305x_pci_read_config(dev, 0, 0, 0, 0x70c, 4); + + rt305x_pci_write_config(dev, 0, 0, 0, PCIR_BAR(0), 0, 4); +} + +static inline uint32_t +pcib_bit_get(uint32_t *map, uint32_t bit) +{ + uint32_t n = bit / BITS_PER_UINT32; + + bit = bit % BITS_PER_UINT32; + return (map[n] & (1 << bit)); +} + +static inline void +pcib_bit_set(uint32_t *map, uint32_t bit) +{ + uint32_t n = bit / BITS_PER_UINT32; + + bit = bit % BITS_PER_UINT32; + map[n] |= (1 << bit); +} + +static inline uint32_t +pcib_map_check(uint32_t *map, uint32_t start, uint32_t bits) +{ + uint32_t i; + + for (i = start; i < start + bits; i++) + if (pcib_bit_get(map, i)) + return (0); + + return (1); +} + +static inline void +pcib_map_set(uint32_t *map, uint32_t start, uint32_t bits) +{ + uint32_t i; + + for (i = start; i < start + bits; i++) + pcib_bit_set(map, i); +} + +static bus_addr_t +pcib_alloc(device_t dev, uint32_t smask) +{ + struct rt305x_pci_softc *sc = device_get_softc(dev); + uint32_t bits, bits_limit, i, *map, min_alloc, size; + bus_addr_t addr = 0; + bus_addr_t base; + + if (smask & 1) { + base = sc->sc_io_base; + min_alloc = PCI_MIN_IO_ALLOC; + bits_limit = sc->sc_io_size / min_alloc; + map = sc->sc_io_map; + smask &= ~0x3; + } else { + base = sc->sc_mem_base; + min_alloc = PCI_MIN_MEM_ALLOC; + bits_limit = sc->sc_mem_size / min_alloc; + map = sc->sc_mem_map; + smask &= ~0xF; + } + + size = ~smask + 1; + bits = size / min_alloc; + + for (i = 0; i + bits <= bits_limit; i+= bits) + if (pcib_map_check(map, i, bits)) { + pcib_map_set(map, i, bits); + addr = base + (i * min_alloc); + return (addr); + } + + return (addr); +} + +static int +rt305x_pcib_init_bar(device_t dev, int bus, int slot, int func, int barno) +{ + uint32_t addr, bar; + int reg, width; + + reg = PCIR_BAR(barno); + + rt305x_pci_write_config(dev, bus, slot, func, reg, ~0, 4); + bar = rt305x_pci_read_config(dev, bus, slot, func, reg, 4); + if (bar == 0) + return (1); + + /* Calculate BAR size: 64 or 32 bit (in 32-bit units) */ + width = ((bar & 7) == 4) ? 2 : 1; + + addr = pcib_alloc(dev, bar); + if (!addr) + return (-1); + + if (bootverbose) + printf("PCI %u:%u:%u: reg %x: smask=%08x: addr=%08x\n", + bus, slot, func, reg, bar, addr); + + rt305x_pci_write_config(dev, bus, slot, func, reg, addr, 4); + if (width == 2) + rt305x_pci_write_config(dev, bus, slot, func, reg + 4, 0, 4); + + return (width); +} + +static int +rt305x_pcib_init_all_bars(device_t dev, int bus, int slot, int func, + int hdrtype) +{ + int maxbar, bar, i; + + maxbar = (hdrtype & PCIM_HDRTYPE) ? 0 : 6; + bar = 0; + + while (bar < maxbar) { + i = rt305x_pcib_init_bar(dev, bus, slot, func, bar); + bar += i; + if (i < 0) { + device_printf(dev, "PCI IO/Memory space exhausted\n"); + return (ENOMEM); + } + } + + return (0); +} + +static inline int +rt305x_pci_slot_has_link(device_t dev, int slot) +{ + struct rt305x_pci_softc *sc = device_get_softc(dev); + + return !!(sc->pcie_link_status & (1<sc_io_base; + io_limit = io_base + sc->sc_io_size - 1; + mem_base = sc->sc_mem_base; + mem_limit = mem_base + sc->sc_mem_size - 1; + + rt305x_pci_write_config(dev, bus, slot, func, PCIR_IOBASEL_1, + io_base >> 8, 1); + rt305x_pci_write_config(dev, bus, slot, func, PCIR_IOBASEH_1, + io_base >> 16, 2); + rt305x_pci_write_config(dev, bus, slot, func, PCIR_IOLIMITL_1, + io_limit >> 8, 1); + rt305x_pci_write_config(dev, bus, slot, func, PCIR_IOLIMITH_1, + io_limit >> 16, 2); + + rt305x_pci_write_config(dev, bus, slot, func, PCIR_MEMBASE_1, + mem_base >> 16, 2); + rt305x_pci_write_config(dev, bus, slot, func, PCIR_MEMLIMIT_1, + mem_limit >> 16, 2); + + rt305x_pci_write_config(dev, bus, slot, func, PCIR_PMBASEL_1, + 0x10, 2); + rt305x_pci_write_config(dev, bus, slot, func, PCIR_PMBASEH_1, + 0x0, 4); + rt305x_pci_write_config(dev, bus, slot, func, PCIR_PMLIMITL_1, + 0xF, 2); + rt305x_pci_write_config(dev, bus, slot, func, PCIR_PMLIMITH_1, + 0x0, 4); + + secbus = rt305x_pci_read_config(dev, bus, slot, func, PCIR_SECBUS_1, 1); + + if (secbus == 0) { + rt305x_pci_write_config(dev, bus, slot, func, PCIR_SECBUS_1, + ++cur_secbus, 1); + rt305x_pci_write_config(dev, bus, slot, func, PCIR_SUBBUS_1, + cur_secbus, 1); + secbus = cur_secbus; + } + + rt305x_pcib_init(dev, secbus, PCI_SLOTMAX); +} + +static int +rt305x_pcib_init(device_t dev, int bus, int maxslot) +{ + int slot, func, maxfunc, error; + uint8_t hdrtype, command, class, subclass; + + for (slot = 0; slot <= maxslot; slot++) { + maxfunc = 0; + for (func = 0; func <= maxfunc; func++) { + hdrtype = rt305x_pci_read_config(dev, bus, slot, func, + PCIR_HDRTYPE, 1); + + if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) + continue; + + if (func == 0 && (hdrtype & PCIM_MFDEV)) + maxfunc = PCI_FUNCMAX; + + command = rt305x_pci_read_config(dev, bus, slot, func, + PCIR_COMMAND, 1); + command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN); + rt305x_pci_write_config(dev, bus, slot, func, + PCIR_COMMAND, command, 1); + + error = rt305x_pcib_init_all_bars(dev, bus, slot, func, + hdrtype); + + if (error) + return (error); + + command |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN | + PCIM_CMD_PORTEN; + rt305x_pci_write_config(dev, bus, slot, func, + PCIR_COMMAND, command, 1); + + rt305x_pci_write_config(dev, bus, slot, func, + PCIR_CACHELNSZ, 16, 1); + + class = rt305x_pci_read_config(dev, bus, slot, func, + PCIR_CLASS, 1); + subclass = rt305x_pci_read_config(dev, bus, slot, func, + PCIR_SUBCLASS, 1); + + if (class != PCIC_BRIDGE || subclass != PCIS_BRIDGE_PCI) + continue; + + rt305x_pcib_init_bridge(dev, bus, slot, func); + } + } + + return (0); +} + +#define BUSY 0x80000000 +#define WAITRETRY_MAX 10 +#define WRITE_MODE (1<<23) +#define DATA_SHIFT 0 +#define ADDR_SHIFT 8 + +static int +rt305x_wait_pci_phy_busy(struct rt305x_pci_softc *sc) +{ + uint32_t reg_value = 0x0, retry = 0; + + while (1) { + reg_value = RT_READ32(sc, RT305X_PCI_PHY0_CFG); + if (reg_value & BUSY) + DELAY(100000); + else + break; + if (retry++ > WAITRETRY_MAX) { + printf("PHY retry failed\n"); + return (-1); + } + } + return (0); +} + +static uint32_t +rt305x_pci_phy(struct rt305x_pci_softc *sc, char rwmode, uint32_t addr, + uint32_t val) +{ + uint32_t reg_value = 0x0; + + rt305x_wait_pci_phy_busy(sc); + if (rwmode == 'w') { + reg_value |= WRITE_MODE; + reg_value |= (val) << DATA_SHIFT; + } + reg_value |= (addr) << ADDR_SHIFT; + + RT_WRITE32(sc, RT305X_PCI_PHY0_CFG, reg_value); + DELAY(1000); + + rt305x_wait_pci_phy_busy(sc); + + if (rwmode == 'r') { + reg_value = RT_READ32(sc, RT305X_PCI_PHY0_CFG); + return (reg_value); + } + + return (0); +} + +static void +rt305x_pci_phy_init(device_t dev) +{ + struct rt305x_pci_softc *sc = device_get_softc(dev); + uint32_t tmp; + + rt305x_pci_phy(sc, 'w', 0x00, 0x80); + rt305x_pci_phy(sc, 'w', 0x01, 0x04); + rt305x_pci_phy(sc, 'w', 0x68, 0x84); + + rt305x_sysctl_set(SYSCTL_RSTCTRL, + rt305x_sysctl_get(SYSCTL_RSTCTRL) | (1<<26)); + rt305x_sysctl_set(SYSCTL_CLKCFG1, + rt305x_sysctl_get(SYSCTL_CLKCFG1) & ~(1<<26)); + + tmp = rt305x_sysctl_get(SYSCTL_PPLL_CFG1); + tmp &= ~(1<<19); + rt305x_sysctl_set(SYSCTL_PPLL_CFG1, tmp); + tmp |= (1<<31); + rt305x_sysctl_set(SYSCTL_PPLL_CFG1, tmp); +} + +static int +rt305x_pci_intr(void *arg) +{ + struct rt305x_pci_softc *sc = arg; + struct intr_event *event; + uint32_t reg, irq, irqidx; + + reg = RT_READ32(sc, RT305X_PCI_PCIINT); + + for (irqidx = 0; irqidx < RT305X_PCI_NIRQS; irqidx++) { + irq = rt305x_idx_to_irq(irqidx); + if (reg & (1<sc_eventstab[irqidx]; + if (!event || TAILQ_EMPTY(&event->ie_handlers)) { + if (irq != 0) + printf("Stray PCI IRQ %d\n", irq); + continue; + } + + intr_event_handle(event, NULL); + mips_intrcnt_inc(sc->sc_intr_counter[irqidx]); + } + } + + return (FILTER_HANDLED); +} Added: head/sys/mips/rt305x/rt305x_pcireg.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/mips/rt305x/rt305x_pcireg.h Thu Dec 24 18:33:08 2015 (r292700) @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 2015 Stanislav Galabov. + * All rights reserved. + * + * 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 __RT305X_PCIREG_H__ +#define __RT305X_PCIREG_H__ + +#define RT305X_PCI_NIRQS 1 +#define RT305X_PCI_BASESLOT 0 + +#define RT305X_PCI_PCICFG 0x0000 +#define RT305X_PCI_PCIINT 0x0008 +#define RT305X_PCI_PCIENA 0x000C +#define RT305X_PCI_CFGADDR 0x0020 +#define RT305X_PCI_CFGDATA 0x0024 +#define RT305X_PCI_MEMBASE 0x0028 *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***