ixdp425_pci.c revision 164426
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: head/sys/arm/xscale/ixp425/ixdp425_pci.c 164426 2006-11-19 23:55:23Z sam $"); 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#include <machine/bus.h> 47#include <machine/intr.h> 48 49#include <arm/xscale/ixp425/ixp425reg.h> 50#include <arm/xscale/ixp425/ixp425var.h> 51#include <arm/xscale/ixp425/ixp425_intr.h> 52#include <arm/xscale/ixp425/ixdp425reg.h> 53 54void 55ixp425_md_attach(device_t dev) 56{ 57 struct ixp425_softc *sc = device_get_softc(device_get_parent(dev)); 58 struct ixppcib_softc *pci_sc = device_get_softc(dev); 59 uint32_t reg; 60 61 62 /* PCI Reset Assert */ 63 reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOUTR); 64 reg &= ~(1U << GPIO_PCI_RESET); 65 GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg & ~(1U << GPIO_PCI_RESET)); 66 67 /* PCI Clock Disable */ 68 reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPCLKR); 69 reg &= ~GPCLKR_MUX14; 70 GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg & ~GPCLKR_MUX14); 71 72 /* 73 * set GPIO Direction 74 * Output: PCI_CLK, PCI_RESET 75 * Input: PCI_INTA, PCI_INTB, PCI_INTC, PCI_INTD 76 */ 77 reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOER); 78 reg &= ~(1U << GPIO_PCI_CLK); 79 reg &= ~(1U << GPIO_PCI_RESET); 80 reg |= ((1U << GPIO_PCI_INTA) | (1U << GPIO_PCI_INTB) | 81 (1U << GPIO_PCI_INTC) | (1U << GPIO_PCI_INTD)); 82 GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOER, reg); 83 84 /* 85 * Set GPIO interrupt type 86 * PCI_INT_A, PCI_INTB, PCI_INT_C, PCI_INT_D: Active Low 87 */ 88 reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTA)); 89 reg &= ~GPIO_TYPE(GPIO_PCI_INTA, GPIO_TYPE_MASK); 90 reg |= GPIO_TYPE(GPIO_PCI_INTA, GPIO_TYPE_ACT_LOW); 91 GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTA), reg); 92 93 reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTB)); 94 reg &= ~GPIO_TYPE(GPIO_PCI_INTB, GPIO_TYPE_MASK); 95 reg |= GPIO_TYPE(GPIO_PCI_INTB, GPIO_TYPE_ACT_LOW); 96 GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTB), reg); 97 98 reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTC)); 99 reg &= ~GPIO_TYPE(GPIO_PCI_INTC, GPIO_TYPE_MASK); 100 reg |= GPIO_TYPE(GPIO_PCI_INTC, GPIO_TYPE_ACT_LOW); 101 GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTC), reg); 102 103 reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTD)); 104 reg &= ~GPIO_TYPE(GPIO_PCI_INTD, GPIO_TYPE_MASK); 105 reg |= GPIO_TYPE(GPIO_PCI_INTD, GPIO_TYPE_ACT_LOW); 106 GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTD), reg); 107 108 /* clear ISR */ 109 GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPISR, 110 (1U << GPIO_PCI_INTA) | (1U << GPIO_PCI_INTB) | 111 (1U << GPIO_PCI_INTC) | (1U << GPIO_PCI_INTD)); 112 113 /* wait 1ms to satisfy "minimum reset assertion time" of the PCI spec */ 114 DELAY(1000); 115 reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPCLKR); 116 GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg | 117 (0xf << GPCLKR_CLK0DC_SHIFT) | (0xf << GPCLKR_CLK0TC_SHIFT)); 118 119 /* PCI Clock Enable */ 120 reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPCLKR); 121 reg |= GPCLKR_MUX14; 122 GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg | GPCLKR_MUX14); 123 124 /* 125 * wait 100us to satisfy "minimum reset assertion time from clock stable 126 * requirement of the PCI spec 127 */ 128 DELAY(100); 129 /* PCI Reset deassert */ 130 reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOUTR); 131 reg |= 1U << GPIO_PCI_RESET; 132 GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg | (1U << GPIO_PCI_RESET)); 133 pci_sc->sc_irq_rman.rm_type = RMAN_ARRAY; 134 pci_sc->sc_irq_rman.rm_descr = "IXP425 PCI IRQs"; 135 CTASSERT(PCI_INT_D < PCI_INT_A); 136 /* XXX this overlaps the irq's setup in ixp425_attach */ 137 if (rman_init(&pci_sc->sc_irq_rman) != 0 || 138 rman_manage_region(&pci_sc->sc_irq_rman, PCI_INT_D, PCI_INT_A) != 0) 139 panic("ixp425_md_attach: failed to set up IRQ rman"); 140} 141 142#define IXP425_MAX_DEV 4 143#define IXP425_MAX_LINE 4 144 145int 146ixp425_md_route_interrupt(device_t bridge, device_t device, int pin) 147{ 148 static int ixp425_pci_table[IXP425_MAX_DEV][IXP425_MAX_LINE] = 149 { 150 {PCI_INT_A, PCI_INT_B, PCI_INT_C, PCI_INT_D}, 151 {PCI_INT_B, PCI_INT_C, PCI_INT_D, PCI_INT_A}, 152 {PCI_INT_C, PCI_INT_D, PCI_INT_A, PCI_INT_B}, 153 {PCI_INT_D, PCI_INT_A, PCI_INT_B, PCI_INT_C}, 154 }; 155 int dev; 156 157 dev = pci_get_slot(device); 158 if (bootverbose) 159 device_printf(bridge, "routing pin %d for %s\n", pin, 160 device_get_nameunit(device)); 161 if (pin >= 1 && pin <= IXP425_MAX_LINE && 162 dev >= 1 && dev <= IXP425_MAX_DEV) { 163 return (ixp425_pci_table[dev - 1][pin - 1]); 164 } else 165 printf("ixppcib: no mapping for %d/%d/%d\n", 166 pci_get_bus(device), dev, pci_get_function(device)); 167 168 return (-1); 169} 170