xref: /netbsd-src/sys/arch/evbarm/nslu2/nslu2_pci.c (revision 923e03b5d7d2c5fb8ecfa9795cab50988ff70d54)
1*923e03b5Sjmcneill /*      $NetBSD: nslu2_pci.c,v 1.8 2018/11/18 14:25:17 jmcneill Exp $	*/
26f616773Sscw 
36f616773Sscw /*-
46f616773Sscw  * Copyright (c) 2006 The NetBSD Foundation, Inc.
56f616773Sscw  * All rights reserved.
66f616773Sscw  *
76f616773Sscw  * This code is derived from software contributed to The NetBSD Foundation
86f616773Sscw  * by Steve C. Woodford.
96f616773Sscw  *
106f616773Sscw  * Redistribution and use in source and binary forms, with or without
116f616773Sscw  * modification, are permitted provided that the following conditions
126f616773Sscw  * are met:
136f616773Sscw  * 1. Redistributions of source code must retain the above copyright
146f616773Sscw  *    notice, this list of conditions and the following disclaimer.
156f616773Sscw  * 2. Redistributions in binary form must reproduce the above copyright
166f616773Sscw  *    notice, this list of conditions and the following disclaimer in the
176f616773Sscw  *    documentation and/or other materials provided with the distribution.
186f616773Sscw  *
196f616773Sscw  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
206f616773Sscw  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
216f616773Sscw  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
226f616773Sscw  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
236f616773Sscw  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
246f616773Sscw  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
256f616773Sscw  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
266f616773Sscw  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
276f616773Sscw  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
286f616773Sscw  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
296f616773Sscw  * POSSIBILITY OF SUCH DAMAGE.
306f616773Sscw  */
316f616773Sscw /*
326f616773Sscw  * Copyright (c) 2003
336f616773Sscw  *      Ichiro FUKUHARA <ichiro@ichiro.org>.
346f616773Sscw  * All rights reserved.
356f616773Sscw  *
366f616773Sscw  * Redistribution and use in source and binary forms, with or without
376f616773Sscw  * modification, are permitted provided that the following conditions
386f616773Sscw  * are met:
396f616773Sscw  * 1. Redistributions of source code must retain the above copyright
406f616773Sscw  *    notice, this list of conditions and the following disclaimer.
416f616773Sscw  * 2. Redistributions in binary form must reproduce the above copyright
426f616773Sscw  *    notice, this list of conditions and the following disclaimer in the
436f616773Sscw  *    documentation and/or other materials provided with the distribution.
446f616773Sscw  *
456f616773Sscw  * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
466f616773Sscw  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
476f616773Sscw  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
486f616773Sscw  * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
496f616773Sscw  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
506f616773Sscw  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
516f616773Sscw  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
526f616773Sscw  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
536f616773Sscw  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
546f616773Sscw  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
556f616773Sscw  * SUCH DAMAGE.
566f616773Sscw  */
576f616773Sscw 
586f616773Sscw #include <sys/cdefs.h>
59*923e03b5Sjmcneill __KERNEL_RCSID(0, "$NetBSD: nslu2_pci.c,v 1.8 2018/11/18 14:25:17 jmcneill Exp $");
606f616773Sscw 
616f616773Sscw /*
626f616773Sscw  * Linksys NSLU2 PCI support.
636f616773Sscw  */
646f616773Sscw 
656f616773Sscw #include <sys/param.h>
666f616773Sscw #include <sys/systm.h>
676f616773Sscw #include <sys/device.h>
686f616773Sscw 
696f616773Sscw #include <arm/xscale/ixp425reg.h>
706f616773Sscw #include <arm/xscale/ixp425var.h>
716f616773Sscw 
726f616773Sscw #include <dev/pci/pcivar.h>
736f616773Sscw 
746f616773Sscw #include <evbarm/nslu2/nslu2reg.h>
756f616773Sscw 
766f616773Sscw static int
nslu2_pci_intr_map(const struct pci_attach_args * pa,pci_intr_handle_t * ihp)77d3e53912Sdyoung nslu2_pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
786f616773Sscw {
796f616773Sscw 
806f616773Sscw 	KASSERT(pa->pa_bus == 0 && pa->pa_device == 1);
816f616773Sscw 
826f616773Sscw 	switch (pa->pa_function) {
836f616773Sscw 	case 0:
846f616773Sscw 		*ihp = PCI_INT_A;
856f616773Sscw 		break;
866f616773Sscw 
876f616773Sscw 	case 1:
886f616773Sscw 		*ihp = PCI_INT_B;
896f616773Sscw 		break;
906f616773Sscw 
916f616773Sscw 	case 2:
926f616773Sscw 		*ihp = PCI_INT_C;
936f616773Sscw 		break;
946f616773Sscw 
956f616773Sscw 	default:
966f616773Sscw 		return (1);
976f616773Sscw 	}
986f616773Sscw 
996f616773Sscw 	return (0);
1006f616773Sscw }
1016f616773Sscw 
1026f616773Sscw static const char *
nslu2_pci_intr_string(void * v,pci_intr_handle_t ih,char * buf,size_t len)103e58a356cSchristos nslu2_pci_intr_string(void *v, pci_intr_handle_t ih, char *buf, size_t len)
1046f616773Sscw {
105e58a356cSchristos 	char c;
1066f616773Sscw 	switch (ih) {
1076f616773Sscw 	case PCI_INT_A:
108e58a356cSchristos 		c = 'A';
109e58a356cSchristos 		break;
1106f616773Sscw 
1116f616773Sscw 	case PCI_INT_B:
112e58a356cSchristos 		c = 'B';
113e58a356cSchristos 		break;
1146f616773Sscw 
1156f616773Sscw 	case PCI_INT_C:
116e58a356cSchristos 		c = 'C';
117e58a356cSchristos 		break;
118e58a356cSchristos 	default:
119e58a356cSchristos 		c = '?';
1206f616773Sscw 	}
121e58a356cSchristos 	snprintf(buf, len, "PCI%c", c);
1226f616773Sscw 
123c264ca3cSozaki-r 	return buf;
1246f616773Sscw }
1256f616773Sscw 
1266f616773Sscw static const struct evcnt *
nslu2_pci_intr_evcnt(void * v,pci_intr_handle_t ih)1276f616773Sscw nslu2_pci_intr_evcnt(void *v, pci_intr_handle_t ih)
1286f616773Sscw {
1296f616773Sscw 
1306f616773Sscw 	return (NULL);
1316f616773Sscw }
1326f616773Sscw 
1336f616773Sscw static void *
nslu2_pci_intr_establish(void * v,pci_intr_handle_t ih,int ipl,int (* func)(void *),void * arg,const char * xname)1346f616773Sscw nslu2_pci_intr_establish(void *v, pci_intr_handle_t ih, int ipl,
135*923e03b5Sjmcneill     int (*func)(void *), void *arg, const char *xname)
1366f616773Sscw {
1376f616773Sscw 
1386f616773Sscw 	return (ixp425_intr_establish(ih, ipl, func, arg));
1396f616773Sscw }
1406f616773Sscw 
1416f616773Sscw static void
nslu2_pci_intr_disestablish(void * v,void * cookie)1426f616773Sscw nslu2_pci_intr_disestablish(void *v, void *cookie)
1436f616773Sscw {
1446f616773Sscw 
1456f616773Sscw 	ixp425_intr_disestablish(cookie);
1466f616773Sscw }
1476f616773Sscw 
1486f616773Sscw void
ixp425_md_pci_conf_interrupt(pci_chipset_tag_t pc,int bus,int dev,int pin,int swiz,int * ilinep)1496f616773Sscw ixp425_md_pci_conf_interrupt(pci_chipset_tag_t pc, int bus, int dev, int pin,
1506f616773Sscw     int swiz, int *ilinep)
1516f616773Sscw {
1526f616773Sscw 
1536f616773Sscw 	KASSERT(bus == 0 && dev == 1);
1546f616773Sscw 
1556f616773Sscw 	*ilinep = ((swiz + pin - 1) & 3);
1566f616773Sscw }
1576f616773Sscw 
1586f616773Sscw void
ixp425_md_pci_init(struct ixp425_softc * sc)1596f616773Sscw ixp425_md_pci_init(struct ixp425_softc *sc)
1606f616773Sscw {
1616f616773Sscw 	pci_chipset_tag_t pc = &sc->ia_pci_chipset;
16208a4aba7Sskrll 	uint32_t reg;
1636f616773Sscw 
1646f616773Sscw 	pc->pc_intr_v = sc;
1656f616773Sscw 	pc->pc_intr_map = nslu2_pci_intr_map;
1666f616773Sscw 	pc->pc_intr_string = nslu2_pci_intr_string;
1676f616773Sscw 	pc->pc_intr_evcnt = nslu2_pci_intr_evcnt;
1686f616773Sscw 	pc->pc_intr_establish = nslu2_pci_intr_establish;
1696f616773Sscw 	pc->pc_intr_disestablish = nslu2_pci_intr_disestablish;
1706f616773Sscw 
1716f616773Sscw 	/* PCI Reset Assert */
1726f616773Sscw 	reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOUTR);
1736f616773Sscw 	reg &= ~(1u << GPIO_PCI_RESET);
1746f616773Sscw 	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg);
1756f616773Sscw 
1766f616773Sscw 	/* PCI Clock Disable */
1776f616773Sscw 	reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPCLKR);
1786f616773Sscw 	reg &= ~GPCLKR_MUX14;
1796f616773Sscw 	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg);
1806f616773Sscw 
1816f616773Sscw 	/*
1826f616773Sscw 	 * Set GPIO Direction
1836f616773Sscw 	 *	Output: PCI_CLK, PCI_RESET
1846f616773Sscw 	 *	Input:  PCI_INTA, PCI_INTB, PCI_INTC
1856f616773Sscw 	 */
1866f616773Sscw 	reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOER);
1876f616773Sscw 	reg &= ~((1u << GPIO_PCI_CLK) | (1u << GPIO_PCI_RESET));
1886f616773Sscw 	reg |= (1u << GPIO_PCI_INTA) | (1u << GPIO_PCI_INTB) |
1896f616773Sscw 	    (1u << GPIO_PCI_INTC);
1906f616773Sscw 	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOER, reg);
1916f616773Sscw 
1926f616773Sscw 	/*
1936f616773Sscw 	 * Set GPIO interrupt type
1946f616773Sscw 	 *      PCI_INT_A, PCI_INTB, PCI_INT_C: Active Low
1956f616773Sscw 	 */
1966f616773Sscw 	reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTA));
1976f616773Sscw 	reg &= ~GPIO_TYPE(GPIO_PCI_INTA, GPIO_TYPE_MASK);
1986f616773Sscw 	reg |= GPIO_TYPE(GPIO_PCI_INTA, GPIO_TYPE_ACT_LOW);
1996f616773Sscw 	GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTA), reg);
2006f616773Sscw 
2016f616773Sscw 	reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTB));
2026f616773Sscw 	reg &= ~GPIO_TYPE(GPIO_PCI_INTB, GPIO_TYPE_MASK);
2036f616773Sscw 	reg |= GPIO_TYPE(GPIO_PCI_INTB, GPIO_TYPE_ACT_LOW);
2046f616773Sscw 	GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTB), reg);
2056f616773Sscw 
2066f616773Sscw 	reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTC));
2076f616773Sscw 	reg &= ~GPIO_TYPE(GPIO_PCI_INTC, GPIO_TYPE_MASK);
2086f616773Sscw 	reg |= GPIO_TYPE(GPIO_PCI_INTC, GPIO_TYPE_ACT_LOW);
2096f616773Sscw 	GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTC), reg);
2106f616773Sscw 
2116f616773Sscw 	/* Clear ISR */
2126f616773Sscw 	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPISR, (1u << GPIO_PCI_INTA) |
2136f616773Sscw 	    (1u << GPIO_PCI_INTB) | (1u << GPIO_PCI_INTC));
2146f616773Sscw 
2156f616773Sscw 	/* Wait 1ms to satisfy "minimum reset assertion time" of the PCI spec */
2166f616773Sscw 	DELAY(1000);
2176f616773Sscw 	reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPCLKR);
2186f616773Sscw 	reg |= (0xf << GPCLKR_CLK0DC_SHIFT) | (0xf << GPCLKR_CLK0TC_SHIFT);
2196f616773Sscw 	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg);
2206f616773Sscw 
2216f616773Sscw 	/* PCI Clock Enable */
2226f616773Sscw 	reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPCLKR);
2236f616773Sscw 	reg |= GPCLKR_MUX14;
2246f616773Sscw 	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg);
2256f616773Sscw 
2266f616773Sscw 	/*
2276f616773Sscw 	 * Wait 100us to satisfy "minimum reset assertion time from clock stable
2286f616773Sscw 	 * requirement of the PCI spec
2296f616773Sscw 	 */
2306f616773Sscw 	DELAY(100);
2316f616773Sscw         /* PCI Reset deassert */
2326f616773Sscw 	reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOUTR);
2336f616773Sscw 	reg |= 1u << GPIO_PCI_RESET;
2346f616773Sscw 	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg);
2356f616773Sscw 
2366f616773Sscw 	/*
2376f616773Sscw 	 * AHB->PCI address translation
2386f616773Sscw 	 *	PCI Memory Map allocation in 0x48000000 (64MB)
2396f616773Sscw 	 *	see. IXP425_PCI_MEM_HWBASE
2406f616773Sscw 	 */
2416f616773Sscw 	PCI_CSR_WRITE_4(sc, PCI_PCIMEMBASE, 0x48494a4b);
2426f616773Sscw 
2436f616773Sscw 	/*
2446f616773Sscw 	 * PCI->AHB address translation
2456f616773Sscw 	 * 	begin at the physical memory start + OFFSET
2466f616773Sscw 	 */
2476f616773Sscw #define	AHB_OFFSET	0x10000000UL
2486f616773Sscw 	reg  = (AHB_OFFSET + 0x00000000) >> 0;
2496f616773Sscw 	reg |= (AHB_OFFSET + 0x01000000) >> 8;
2506f616773Sscw 	reg |= (AHB_OFFSET + 0x02000000) >> 16;
2516f616773Sscw 	reg |= (AHB_OFFSET + 0x03000000) >> 24;
2526f616773Sscw 	PCI_CSR_WRITE_4(sc, PCI_AHBMEMBASE, reg);
2536f616773Sscw 
2546f616773Sscw 	/* Write Mapping registers PCI Configuration Registers */
2556f616773Sscw 	/* Base Address 0 - 3 */
2566f616773Sscw 	ixp425_pci_conf_reg_write(sc, PCI_MAPREG_BAR0, AHB_OFFSET + 0x00000000);
2576f616773Sscw 	ixp425_pci_conf_reg_write(sc, PCI_MAPREG_BAR1, AHB_OFFSET + 0x01000000);
2586f616773Sscw 	ixp425_pci_conf_reg_write(sc, PCI_MAPREG_BAR2, AHB_OFFSET + 0x02000000);
2596f616773Sscw 	ixp425_pci_conf_reg_write(sc, PCI_MAPREG_BAR3, AHB_OFFSET + 0x03000000);
2606f616773Sscw 
2616f616773Sscw 	/* Base Address 4 */
2626f616773Sscw 	ixp425_pci_conf_reg_write(sc, PCI_MAPREG_BAR4, 0xffffffff);
2636f616773Sscw 
2646f616773Sscw 	/* Base Address 5 */
2656f616773Sscw 	ixp425_pci_conf_reg_write(sc, PCI_MAPREG_BAR5, 0x00000000);
2666f616773Sscw 
2676f616773Sscw 	/* Assert some PCI errors */
2686f616773Sscw 	PCI_CSR_WRITE_4(sc, PCI_ISR, ISR_AHBE | ISR_PPE | ISR_PFE | ISR_PSE);
2696f616773Sscw 
2706f616773Sscw 	/*
2716f616773Sscw 	 * Set up byte lane swapping between little-endian PCI
2726f616773Sscw 	 * and the big-endian AHB bus
2736f616773Sscw 	 */
2746f616773Sscw 	PCI_CSR_WRITE_4(sc, PCI_CSR, CSR_IC | CSR_ABE | CSR_PDS);
2756f616773Sscw 
2766f616773Sscw 	/*
2776f616773Sscw 	 * Enable bus mastering and I/O,memory access
2786f616773Sscw 	 */
2796f616773Sscw 	ixp425_pci_conf_reg_write(sc, PCI_COMMAND_STATUS_REG,
2806f616773Sscw 		PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
2816f616773Sscw 		PCI_COMMAND_MASTER_ENABLE);
2826f616773Sscw 
2836f616773Sscw 	/*
2846f616773Sscw 	 * Wait some more to ensure PCI devices have stabilised.
2856f616773Sscw 	 */
2866f616773Sscw 	DELAY(50000);
2876f616773Sscw }
288