1/* $NetBSD: ixdp425_pci.c,v 1.5 2005/12/11 12:17:09 christos Exp $ */ 2/* 3 * Copyright (c) 2003 4 * Ichiro FUKUHARA <ichiro@ichiro.org>. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Ichiro FUKUHARA. 18 * 4. The name of the company nor the name of the author may be used to 19 * endorse or promote products derived from this software without specific 20 * prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR 26 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35#include <sys/cdefs.h> 36__FBSDID("$FreeBSD$"); 37 38#define _ARM32_BUS_DMA_PRIVATE 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/bus.h> 42#include <sys/kernel.h> 43#include <sys/module.h> 44#include <sys/malloc.h> 45#include <sys/rman.h> 46 47#include <dev/pci/pcivar.h> 48 49#include <machine/bus.h> 50#include <machine/intr.h> 51 52#include <arm/xscale/ixp425/ixp425reg.h> 53#include <arm/xscale/ixp425/ixp425var.h> 54#include <arm/xscale/ixp425/ixp425_intr.h> 55#include <arm/xscale/ixp425/ixdp425reg.h> 56 57void 58ixp425_md_attach(device_t dev) 59{ 60 struct ixp425_softc *sc = device_get_softc(device_get_parent(dev)); 61 struct ixppcib_softc *pci_sc = device_get_softc(dev); 62 uint32_t reg; 63 64 65 /* PCI Reset Assert */ 66 reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOUTR); 67 reg &= ~(1U << GPIO_PCI_RESET); 68 GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg); 69 70 /* PCI Clock Disable */ 71 reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPCLKR); 72 reg &= ~GPCLKR_MUX14; 73 GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg); 74 75 /* 76 * set GPIO Direction 77 * Output: PCI_CLK, PCI_RESET 78 * Input: PCI_INTA, PCI_INTB, PCI_INTC, PCI_INTD 79 */ 80 reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOER); 81 reg &= ~(1U << GPIO_PCI_CLK); 82 reg &= ~(1U << GPIO_PCI_RESET); 83 reg |= ((1U << GPIO_PCI_INTA) | (1U << GPIO_PCI_INTB) | 84 (1U << GPIO_PCI_INTC) | (1U << GPIO_PCI_INTD)); 85 GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOER, reg); 86 87 /* 88 * Set GPIO interrupt type 89 * PCI_INT_A, PCI_INTB, PCI_INT_C, PCI_INT_D: Active Low 90 */ 91 reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTA)); 92 reg &= ~GPIO_TYPE(GPIO_PCI_INTA, GPIO_TYPE_MASK); 93 reg |= GPIO_TYPE(GPIO_PCI_INTA, GPIO_TYPE_ACT_LOW); 94 GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTA), reg); 95 96 reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTB)); 97 reg &= ~GPIO_TYPE(GPIO_PCI_INTB, GPIO_TYPE_MASK); 98 reg |= GPIO_TYPE(GPIO_PCI_INTB, GPIO_TYPE_ACT_LOW); 99 GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTB), reg); 100 101 reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTC)); 102 reg &= ~GPIO_TYPE(GPIO_PCI_INTC, GPIO_TYPE_MASK); 103 reg |= GPIO_TYPE(GPIO_PCI_INTC, GPIO_TYPE_ACT_LOW); 104 GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTC), reg); 105 106 reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTD)); 107 reg &= ~GPIO_TYPE(GPIO_PCI_INTD, GPIO_TYPE_MASK); 108 reg |= GPIO_TYPE(GPIO_PCI_INTD, GPIO_TYPE_ACT_LOW); 109 GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTD), reg); 110 111 /* clear ISR */ 112 GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPISR, 113 (1U << GPIO_PCI_INTA) | (1U << GPIO_PCI_INTB) | 114 (1U << GPIO_PCI_INTC) | (1U << GPIO_PCI_INTD)); 115 116 /* wait 1ms to satisfy "minimum reset assertion time" of the PCI spec */ 117 DELAY(1000); 118 reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPCLKR); 119 GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg | 120 (0xf << GPCLKR_CLK0DC_SHIFT) | (0xf << GPCLKR_CLK0TC_SHIFT)); 121 122 /* PCI Clock Enable */ 123 reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPCLKR); 124 reg |= GPCLKR_MUX14; 125 GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg | GPCLKR_MUX14); 126 127 /* 128 * wait 100us to satisfy "minimum reset assertion time from clock stable 129 * requirement of the PCI spec 130 */ 131 DELAY(100); 132 /* PCI Reset deassert */ 133 reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOUTR); 134 reg |= 1U << GPIO_PCI_RESET; 135 GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg | (1U << GPIO_PCI_RESET)); 136 pci_sc->sc_irq_rman.rm_type = RMAN_ARRAY; 137 pci_sc->sc_irq_rman.rm_descr = "IXP425 PCI IRQs"; 138 CTASSERT(PCI_INT_D < PCI_INT_A); 139 /* XXX this overlaps the irq's setup in ixp425_attach */ 140 if (rman_init(&pci_sc->sc_irq_rman) != 0 || 141 rman_manage_region(&pci_sc->sc_irq_rman, PCI_INT_D, PCI_INT_A) != 0) 142 panic("ixp425_md_attach: failed to set up IRQ rman"); 143} 144 145#define IXP425_MAX_DEV 5 146#define IXP425_MAX_LINE 4 147 148int 149ixp425_md_route_interrupt(device_t bridge, device_t device, int pin) 150{ 151 static int ixp425_pci_table[IXP425_MAX_DEV][IXP425_MAX_LINE] = { 152 {PCI_INT_A, PCI_INT_B, PCI_INT_C, PCI_INT_D}, 153 {PCI_INT_B, PCI_INT_C, PCI_INT_D, PCI_INT_A}, 154 {PCI_INT_C, PCI_INT_D, PCI_INT_A, PCI_INT_B}, 155 {PCI_INT_D, PCI_INT_A, PCI_INT_B, PCI_INT_C}, 156 /* NB: for optional USB controller on Gateworks Avila */ 157 {PCI_INT_A, PCI_INT_B, PCI_INT_C, PCI_INT_D}, 158 }; 159 int dev; 160 161 dev = pci_get_slot(device); 162 if (bootverbose) 163 device_printf(bridge, "routing pin %d for %s\n", pin, 164 device_get_nameunit(device)); 165 if (pin >= 1 && pin <= IXP425_MAX_LINE && 166 dev >= 1 && dev <= IXP425_MAX_DEV) { 167 return (ixp425_pci_table[dev - 1][pin - 1]); 168 } else 169 printf("ixppcib: no mapping for %d/%d/%d\n", 170 pci_get_bus(device), dev, pci_get_function(device)); 171 172 return (-1); 173} 174