11.20Sthorpej/* $NetBSD: vrc4172pci.c,v 1.20 2021/08/07 16:18:54 thorpej Exp $ */ 21.1Stakemura 31.1Stakemura/*- 41.1Stakemura * Copyright (c) 2002 TAKEMURA Shin 51.1Stakemura * All rights reserved. 61.1Stakemura * 71.1Stakemura * Redistribution and use in source and binary forms, with or without 81.1Stakemura * modification, are permitted provided that the following conditions 91.1Stakemura * are met: 101.1Stakemura * 1. Redistributions of source code must retain the above copyright 111.1Stakemura * notice, this list of conditions and the following disclaimer. 121.1Stakemura * 2. Redistributions in binary form must reproduce the above copyright 131.1Stakemura * notice, this list of conditions and the following disclaimer in the 141.1Stakemura * documentation and/or other materials provided with the distribution. 151.1Stakemura * 3. Neither the name of the project nor the names of its contributors 161.1Stakemura * may be used to endorse or promote products derived from this software 171.1Stakemura * without specific prior written permission. 181.1Stakemura * 191.1Stakemura * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 201.1Stakemura * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 211.1Stakemura * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 221.1Stakemura * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 231.1Stakemura * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 241.1Stakemura * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 251.1Stakemura * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 261.1Stakemura * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 271.1Stakemura * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 281.1Stakemura * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 291.1Stakemura * SUCH DAMAGE. 301.1Stakemura */ 311.10Slukem 321.10Slukem#include <sys/cdefs.h> 331.20Sthorpej__KERNEL_RCSID(0, "$NetBSD: vrc4172pci.c,v 1.20 2021/08/07 16:18:54 thorpej Exp $"); 341.1Stakemura 351.1Stakemura#include <sys/param.h> 361.1Stakemura#include <sys/systm.h> 371.1Stakemura#include <sys/device.h> 381.1Stakemura 391.1Stakemura#include <machine/bus.h> 401.1Stakemura#include <machine/bus_space_hpcmips.h> 411.1Stakemura#include <machine/bus_dma_hpcmips.h> 421.1Stakemura#include <machine/config_hook.h> 431.1Stakemura#include <machine/platid.h> 441.1Stakemura#include <machine/platid_mask.h> 451.1Stakemura 461.1Stakemura#include <dev/pci/pcivar.h> 471.1Stakemura#include <dev/pci/pcidevs.h> 481.1Stakemura#include <dev/pci/pciidereg.h> 491.1Stakemura 501.1Stakemura#include <hpcmips/vr/icureg.h> 511.1Stakemura#include <hpcmips/vr/vripif.h> 521.1Stakemura#include <hpcmips/vr/vrc4172pcireg.h> 531.1Stakemura 541.1Stakemura#include "pci.h" 551.3Stakemura#include "opt_vrc4172pci.h" 561.1Stakemura 571.1Stakemura#ifdef DEBUG 581.1Stakemura#define DPRINTF(args) printf args 591.1Stakemura#else 601.3Stakemura#define DPRINTF(args) while (0) {} 611.1Stakemura#endif 621.1Stakemura 631.1Stakemurastruct vrc4172pci_softc { 641.16Schs device_t sc_dev; 651.1Stakemura 661.1Stakemura bus_space_tag_t sc_iot; 671.1Stakemura bus_space_handle_t sc_ioh; 681.1Stakemura 691.1Stakemura struct hpcmips_pci_chipset sc_pc; 701.3Stakemura#ifdef VRC4172PCI_MCR700_SUPPORT 711.3Stakemura pcireg_t sc_fake_baseaddr; 721.3Stakemura hpcio_chip_t sc_iochip; 731.3Stakemura#if 0 741.3Stakemura hpcio_intr_handle_t sc_ih; 751.3Stakemura#endif 761.3Stakemura#endif /* VRC4172PCI_MCR700_SUPPORT */ 771.1Stakemura}; 781.1Stakemura 791.16Schsstatic int vrc4172pci_match(device_t, cfdata_t, void *); 801.16Schsstatic void vrc4172pci_attach(device_t, device_t, void *); 811.16Schsstatic void vrc4172pci_attach_hook(device_t, device_t, 821.1Stakemura struct pcibus_attach_args *); 831.1Stakemurastatic int vrc4172pci_bus_maxdevs(pci_chipset_tag_t, int); 841.15Sdyoungstatic int vrc4172pci_bus_devorder(pci_chipset_tag_t, int, uint8_t *, int); 851.1Stakemurastatic pcitag_t vrc4172pci_make_tag(pci_chipset_tag_t, int, int, int); 861.1Stakemurastatic void vrc4172pci_decompose_tag(pci_chipset_tag_t, pcitag_t, int *, 871.1Stakemura int *, int *); 881.1Stakemurastatic pcireg_t vrc4172pci_conf_read(pci_chipset_tag_t, pcitag_t, int); 891.1Stakemurastatic void vrc4172pci_conf_write(pci_chipset_tag_t, pcitag_t, int, 901.1Stakemura pcireg_t); 911.16Schsstatic int vrc4172pci_intr_map(const struct pci_attach_args *, 921.1Stakemura pci_intr_handle_t *); 931.17Schristosstatic const char *vrc4172pci_intr_string(pci_chipset_tag_t,pci_intr_handle_t, 941.17Schristos char *, size_t); 951.1Stakemurastatic const struct evcnt *vrc4172pci_intr_evcnt(pci_chipset_tag_t, 961.1Stakemura pci_intr_handle_t); 971.1Stakemurastatic void *vrc4172pci_intr_establish(pci_chipset_tag_t, 981.1Stakemura pci_intr_handle_t, int, int (*)(void *), void *); 991.1Stakemurastatic void vrc4172pci_intr_disestablish(pci_chipset_tag_t, void *); 1001.3Stakemura#ifdef VRC4172PCI_MCR700_SUPPORT 1011.3Stakemura#if 0 1021.3Stakemurastatic int vrc4172pci_mcr700_intr(void *arg); 1031.3Stakemura#endif 1041.3Stakemura#endif 1051.1Stakemura 1061.16SchsCFATTACH_DECL_NEW(vrc4172pci, sizeof(struct vrc4172pci_softc), 1071.7Sthorpej vrc4172pci_match, vrc4172pci_attach, NULL, NULL); 1081.1Stakemura 1091.1Stakemurastatic inline void 1101.1Stakemuravrc4172pci_write(struct vrc4172pci_softc *sc, int offset, u_int32_t val) 1111.1Stakemura{ 1121.1Stakemura 1131.1Stakemura bus_space_write_4(sc->sc_iot, sc->sc_ioh, offset, val); 1141.1Stakemura} 1151.1Stakemura 1161.1Stakemurastatic inline u_int32_t 1171.1Stakemuravrc4172pci_read(struct vrc4172pci_softc *sc, int offset) 1181.1Stakemura{ 1191.2Stakemura u_int32_t res; 1201.1Stakemura 1211.2Stakemura if (bus_space_peek(sc->sc_iot, sc->sc_ioh, offset, 4, &res) < 0) { 1221.2Stakemura res = 0xffffffff; 1231.2Stakemura } 1241.2Stakemura 1251.2Stakemura return (res); 1261.1Stakemura} 1271.1Stakemura 1281.1Stakemurastatic int 1291.16Schsvrc4172pci_match(device_t parent, cfdata_t match, void *aux) 1301.1Stakemura{ 1311.1Stakemura 1321.1Stakemura return (1); 1331.1Stakemura} 1341.1Stakemura 1351.1Stakemurastatic void 1361.16Schsvrc4172pci_attach(device_t parent, device_t self, void *aux) 1371.1Stakemura{ 1381.16Schs struct vrc4172pci_softc *sc = device_private(self); 1391.1Stakemura pci_chipset_tag_t pc = &sc->sc_pc; 1401.1Stakemura struct vrip_attach_args *va = aux; 1411.1Stakemura#if NPCI > 0 1421.1Stakemura struct pcibus_attach_args pba; 1431.1Stakemura#endif 1441.1Stakemura 1451.16Schs sc->sc_dev = self; 1461.1Stakemura sc->sc_iot = va->va_iot; 1471.1Stakemura if (bus_space_map(sc->sc_iot, va->va_addr, va->va_size, 0, 1481.1Stakemura &sc->sc_ioh)) { 1491.1Stakemura printf(": couldn't map io space\n"); 1501.1Stakemura return; 1511.1Stakemura } 1521.1Stakemura printf("\n"); 1531.1Stakemura 1541.3Stakemura#ifdef VRC4172PCI_MCR700_SUPPORT 1551.4Stakemura if (platid_match(&platid, &platid_mask_MACH_NEC_MCR_700) || 1561.11Sshin platid_match(&platid, &platid_mask_MACH_NEC_MCR_700A) || 1571.11Sshin platid_match(&platid, &platid_mask_MACH_NEC_MCR_730) || 1581.11Sshin platid_match(&platid, &platid_mask_MACH_NEC_MCR_730A)) { 1591.3Stakemura /* power USB controller on MC-R700 */ 1601.3Stakemura sc->sc_iochip = va->va_gpio_chips[VRIP_IOCHIP_VRGIU]; 1611.3Stakemura hpcio_portwrite(sc->sc_iochip, 45, 1); 1621.3Stakemura sc->sc_fake_baseaddr = 0x0afe0000; 1631.3Stakemura#if 0 1641.3Stakemura sc->sc_ih = hpcio_intr_establish(sc->sc_iochip, 1, 1651.3Stakemura HPCIO_INTR_EDGE|HPCIO_INTR_HOLD, 1661.3Stakemura vrc4172pci_mcr700_intr, sc); 1671.3Stakemura#endif 1681.3Stakemura } 1691.3Stakemura#endif /* VRC4172PCI_MCR700_SUPPORT */ 1701.3Stakemura 1711.16Schs pc->pc_dev = sc->sc_dev; 1721.1Stakemura pc->pc_attach_hook = vrc4172pci_attach_hook; 1731.1Stakemura pc->pc_bus_maxdevs = vrc4172pci_bus_maxdevs; 1741.1Stakemura pc->pc_bus_devorder = vrc4172pci_bus_devorder; 1751.1Stakemura pc->pc_make_tag = vrc4172pci_make_tag; 1761.1Stakemura pc->pc_decompose_tag = vrc4172pci_decompose_tag; 1771.1Stakemura pc->pc_conf_read = vrc4172pci_conf_read; 1781.1Stakemura pc->pc_conf_write = vrc4172pci_conf_write; 1791.1Stakemura pc->pc_intr_map = vrc4172pci_intr_map; 1801.1Stakemura pc->pc_intr_string = vrc4172pci_intr_string; 1811.1Stakemura pc->pc_intr_evcnt = vrc4172pci_intr_evcnt; 1821.1Stakemura pc->pc_intr_establish = vrc4172pci_intr_establish; 1831.1Stakemura pc->pc_intr_disestablish = vrc4172pci_intr_disestablish; 1841.1Stakemura 1851.1Stakemura#if 0 1861.1Stakemura { 1871.1Stakemura int i; 1881.1Stakemura 1891.1Stakemura for (i = 0; i < 2; i++) 1901.1Stakemura printf("%s: ID_REG(0, 0, %d) = 0x%08x\n", 1911.16Schs device_xname(self), i, 1921.1Stakemura pci_conf_read(pc, pci_make_tag(pc, 0, 0, i), 1931.1Stakemura PCI_ID_REG)); 1941.1Stakemura } 1951.1Stakemura#endif 1961.1Stakemura 1971.1Stakemura#if NPCI > 0 1981.1Stakemura memset(&pba, 0, sizeof(pba)); 1991.1Stakemura pba.pba_iot = sc->sc_iot; 2001.1Stakemura pba.pba_memt = sc->sc_iot; 2011.1Stakemura pba.pba_dmat = &hpcmips_default_bus_dma_tag.bdt; 2021.9Sfvdl pba.pba_dmat64 = NULL; 2031.1Stakemura pba.pba_bus = 0; 2041.5Sthorpej pba.pba_bridgetag = NULL; 2051.14Sdyoung pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY | 2061.1Stakemura PCI_FLAGS_MRL_OKAY; 2071.1Stakemura pba.pba_pc = pc; 2081.1Stakemura 2091.20Sthorpej config_found(self, &pba, pcibusprint, CFARGS_NONE); 2101.1Stakemura#endif 2111.1Stakemura} 2121.1Stakemura 2131.1Stakemuravoid 2141.16Schsvrc4172pci_attach_hook(device_t parent, device_t self, 2151.1Stakemura struct pcibus_attach_args *pba) 2161.1Stakemura{ 2171.1Stakemura 2181.1Stakemura return; 2191.1Stakemura} 2201.1Stakemura 2211.1Stakemuraint 2221.1Stakemuravrc4172pci_bus_maxdevs(pci_chipset_tag_t pc, int busno) 2231.1Stakemura{ 2241.1Stakemura 2251.1Stakemura return (1); /* Vrc4172 has only one device */ 2261.1Stakemura} 2271.1Stakemura 2281.1Stakemuraint 2291.15Sdyoungvrc4172pci_bus_devorder(pci_chipset_tag_t pc, int busno, uint8_t *devs, 2301.15Sdyoung int maxdevs) 2311.1Stakemura{ 2321.15Sdyoung if (maxdevs <= 0) 2331.15Sdyoung return 0; 2341.15Sdyoung devs[0] = 0; 2351.15Sdyoung return 1; 2361.1Stakemura} 2371.1Stakemura 2381.1Stakemurapcitag_t 2391.1Stakemuravrc4172pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function) 2401.1Stakemura{ 2411.1Stakemura 2421.1Stakemura return ((bus << 16) | (device << 11) | (function << 8)); 2431.1Stakemura} 2441.1Stakemura 2451.1Stakemuravoid 2461.1Stakemuravrc4172pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, 2471.1Stakemura int *fp) 2481.1Stakemura{ 2491.1Stakemura 2501.1Stakemura if (bp != NULL) 2511.1Stakemura *bp = (tag >> 16) & 0xff; 2521.1Stakemura if (dp != NULL) 2531.1Stakemura *dp = (tag >> 11) & 0x1f; 2541.1Stakemura if (fp != NULL) 2551.1Stakemura *fp = (tag >> 8) & 0x07; 2561.1Stakemura} 2571.1Stakemura 2581.1Stakemurapcireg_t 2591.1Stakemuravrc4172pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) 2601.1Stakemura{ 2611.16Schs struct vrc4172pci_softc *sc = device_private(pc->pc_dev); 2621.1Stakemura u_int32_t val; 2631.1Stakemura 2641.18Smsaitoh if ((unsigned int)reg >= PCI_CONF_SIZE) 2651.18Smsaitoh return ((pcireg_t) -1); 2661.18Smsaitoh 2671.3Stakemura#ifdef VRC4172PCI_MCR700_SUPPORT 2681.3Stakemura if (sc->sc_fake_baseaddr != 0 && 2691.3Stakemura tag == vrc4172pci_make_tag(pc, 0, 0, 1) && 2701.3Stakemura reg == PCI_MAPREG_START) { 2711.3Stakemura val = sc->sc_fake_baseaddr; 2721.3Stakemura goto out; 2731.3Stakemura } 2741.3Stakemura#endif /* VRC4172PCI_MCR700_SUPPORT */ 2751.3Stakemura 2761.1Stakemura tag |= VRC4172PCI_CONFADDR_CONFIGEN; 2771.1Stakemura 2781.1Stakemura vrc4172pci_write(sc, VRC4172PCI_CONFAREG, tag | reg); 2791.1Stakemura val = vrc4172pci_read(sc, VRC4172PCI_CONFDREG); 2801.3Stakemura 2811.3Stakemura#ifdef VRC4172PCI_MCR700_SUPPORT 2821.3Stakemura out: 2831.3Stakemura#endif 2841.2Stakemura DPRINTF(("%s: conf_read: tag = 0x%08x, reg = 0x%x, val = 0x%08x\n", 2851.16Schs device_xname(sc->sc_dev), (u_int32_t)tag, reg, val)); 2861.1Stakemura 2871.1Stakemura return (val); 2881.1Stakemura} 2891.1Stakemura 2901.1Stakemuravoid 2911.1Stakemuravrc4172pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, 2921.1Stakemura pcireg_t data) 2931.1Stakemura{ 2941.16Schs struct vrc4172pci_softc *sc = device_private(pc->pc_dev); 2951.1Stakemura 2961.2Stakemura DPRINTF(("%s: conf_write: tag = 0x%08x, reg = 0x%x, val = 0x%08x\n", 2971.16Schs device_xname(sc->sc_dev), (u_int32_t)tag, reg, (u_int32_t)data)); 2981.3Stakemura 2991.18Smsaitoh if ((unsigned int)reg >= PCI_CONF_SIZE) 3001.18Smsaitoh return; 3011.18Smsaitoh 3021.3Stakemura#ifdef VRC4172PCI_MCR700_SUPPORT 3031.3Stakemura if (sc->sc_fake_baseaddr != 0 && 3041.3Stakemura tag == vrc4172pci_make_tag(pc, 0, 0, 1) && 3051.3Stakemura reg == PCI_MAPREG_START) { 3061.3Stakemura sc->sc_fake_baseaddr = (data & 0xfffff000); 3071.3Stakemura return; 3081.3Stakemura } 3091.3Stakemura#endif /* VRC4172PCI_MCR700_SUPPORT */ 3101.3Stakemura 3111.1Stakemura tag |= VRC4172PCI_CONFADDR_CONFIGEN; 3121.1Stakemura 3131.1Stakemura vrc4172pci_write(sc, VRC4172PCI_CONFAREG, tag | reg); 3141.1Stakemura vrc4172pci_write(sc, VRC4172PCI_CONFDREG, data); 3151.1Stakemura} 3161.1Stakemura 3171.1Stakemuraint 3181.16Schsvrc4172pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) 3191.1Stakemura{ 3201.1Stakemura pci_chipset_tag_t pc = pa->pa_pc; 3211.1Stakemura pcitag_t intrtag = pa->pa_intrtag; 3221.1Stakemura int bus, dev, func; 3231.1Stakemura 3241.1Stakemura pci_decompose_tag(pc, intrtag, &bus, &dev, &func); 3251.16Schs DPRINTF(("%s(%d, %d, %d): line = %d, pin = %d\n", device_xname(pc->pc_dev), 3261.1Stakemura bus, dev, func, pa->pa_intrline, pa->pa_intrpin)); 3271.1Stakemura 3281.1Stakemura *ihp = CONFIG_HOOK_PCIINTR_ID(bus, dev, func); 3291.1Stakemura 3301.1Stakemura return (0); 3311.1Stakemura} 3321.1Stakemura 3331.1Stakemuraconst char * 3341.17Schristosvrc4172pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih, char *buf, 3351.17Schristos size_t len) 3361.1Stakemura{ 3371.17Schristos snprintf(buf, len, "pciintr %d:%d:%d", 3381.1Stakemura CONFIG_HOOK_PCIINTR_BUS((int)ih), 3391.1Stakemura CONFIG_HOOK_PCIINTR_DEVICE((int)ih), 3401.1Stakemura CONFIG_HOOK_PCIINTR_FUNCTION((int)ih)); 3411.1Stakemura 3421.17Schristos return buf; 3431.1Stakemura} 3441.1Stakemura 3451.1Stakemuraconst struct evcnt * 3461.1Stakemuravrc4172pci_intr_evcnt(pci_chipset_tag_t pc, pci_intr_handle_t ih) 3471.1Stakemura{ 3481.1Stakemura 3491.1Stakemura return (NULL); 3501.1Stakemura} 3511.1Stakemura 3521.1Stakemuravoid * 3531.1Stakemuravrc4172pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, 3541.1Stakemura int level, int (*func)(void *), void *arg) 3551.1Stakemura{ 3561.1Stakemura 3571.1Stakemura if (ih == -1) 3581.1Stakemura return (NULL); 3591.1Stakemura DPRINTF(("vrc4172pci_intr_establish: %lx\n", ih)); 3601.1Stakemura 3611.1Stakemura return (config_hook(CONFIG_HOOK_PCIINTR, ih, CONFIG_HOOK_EXCLUSIVE, 3621.1Stakemura (int (*)(void *, int, long, void *))func, arg)); 3631.1Stakemura} 3641.1Stakemura 3651.1Stakemuravoid 3661.1Stakemuravrc4172pci_intr_disestablish(pci_chipset_tag_t pc, void *cookie) 3671.1Stakemura{ 3681.1Stakemura 3691.1Stakemura DPRINTF(("vrc4172pci_intr_disestablish: %p\n", cookie)); 3701.1Stakemura config_unhook(cookie); 3711.1Stakemura} 3721.3Stakemura 3731.3Stakemura#ifdef VRC4172PCI_MCR700_SUPPORT 3741.3Stakemura#if 0 3751.3Stakemuraint 3761.3Stakemuravrc4172pci_mcr700_intr(void *arg) 3771.3Stakemura{ 3781.3Stakemura struct vrc4172pci_softc *sc = arg; 3791.3Stakemura 3801.3Stakemura hpcio_intr_clear(sc->sc_iochip, sc->sc_ih); 3811.3Stakemura printf("USB port %s\n", hpcio_portread(sc->sc_iochip, 1) ? "ON" : "OFF"); 3821.3Stakemura hpcio_portwrite(sc->sc_iochip, 45, hpcio_portread(sc->sc_iochip, 1)); 3831.3Stakemura 3841.3Stakemura return (0); 3851.3Stakemura} 3861.3Stakemura#endif 3871.3Stakemura#endif /* VRC4172PCI_MCR700_SUPPORT */ 388