1/* $NetBSD: i80321.c,v 1.15 2003/10/06 16:06:05 thorpej Exp $ */ 2 3/*- 4 * Copyright (c) 2002 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38/* 39 * Autoconfiguration support for the Intel i80321 I/O Processor. 40 */ 41 42#include <sys/cdefs.h> 43__FBSDID("$FreeBSD$"); 44 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/bus.h> 48#include <sys/kernel.h> 49#include <sys/module.h> 50 51#define _ARM32_BUS_DMA_PRIVATE 52#include <machine/bus.h> 53#include <machine/intr.h> 54 55#include <arm/xscale/i80321/i80321reg.h> 56#include <arm/xscale/i80321/i80321var.h> 57#include <arm/xscale/i80321/i80321_intr.h> 58 59#include <dev/pci/pcireg.h> 60 61volatile uint32_t intr_enabled; 62uint32_t intr_steer = 0; 63/* 64 * Statically-allocated bus_space stucture used to access the 65 * i80321's own registers. 66 */ 67struct bus_space i80321_bs_tag; 68 69/* 70 * There can be only one i80321, so we keep a global pointer to 71 * the softc, so board-specific code can use features of the 72 * i80321 without having to have a handle on the softc itself. 73 */ 74struct i80321_softc *i80321_softc; 75 76#define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0) 77/* 78 * i80321_attach: 79 * 80 * Board-independent attach routine for the i80321. 81 */ 82void 83i80321_attach(struct i80321_softc *sc) 84{ 85 86 i80321_softc = sc; 87 uint32_t preg; 88 89 /* We expect the Memory Controller to be already sliced off. */ 90 91 /* 92 * Program the Inbound windows. 93 */ 94 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR0, 95 (0xffffffff - (sc->sc_iwin[0].iwin_size - 1)) & 0xffffffc0); 96 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR0, 97 sc->sc_iwin[0].iwin_xlate); 98 if (sc->sc_is_host) { 99 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 100 PCIR_BARS, sc->sc_iwin[0].iwin_base_lo); 101 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 102 PCIR_BARS + 0x04, sc->sc_iwin[0].iwin_base_hi); 103 } else { 104 sc->sc_iwin[0].iwin_base_lo = bus_space_read_4(sc->sc_st, 105 sc->sc_atu_sh, PCIR_BARS); 106 sc->sc_iwin[0].iwin_base_hi = bus_space_read_4(sc->sc_st, 107 sc->sc_atu_sh, PCIR_BARS + 0x04); 108 sc->sc_iwin[0].iwin_base_lo = 109 PCI_MAPREG_MEM_ADDR(sc->sc_iwin[0].iwin_base_lo); 110 } 111 112 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR1, 113 (0xffffffff - (sc->sc_iwin[1].iwin_size - 1)) & 0xffffffc0); 114 115 /* no xlate for window 1 */ 116 if (sc->sc_is_host) { 117 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 118 PCIR_BARS + 0x08, sc->sc_iwin[1].iwin_base_lo); 119 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 120 PCIR_BARS + 0x0c, sc->sc_iwin[1].iwin_base_hi); 121 } else { 122 sc->sc_iwin[1].iwin_base_lo = bus_space_read_4(sc->sc_st, 123 sc->sc_atu_sh, PCIR_BARS + 0x08); 124 sc->sc_iwin[1].iwin_base_hi = bus_space_read_4(sc->sc_st, 125 sc->sc_atu_sh, PCIR_BARS + 0x0c); 126 sc->sc_iwin[1].iwin_base_lo = 127 PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo); 128 } 129 130 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR2, 131 (0xffffffff - (sc->sc_iwin[2].iwin_size - 1)) & 0xffffffc0); 132 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR2, 133 sc->sc_iwin[2].iwin_xlate); 134 135 if (sc->sc_is_host) { 136 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 137 PCIR_BARS + 0x10, sc->sc_iwin[2].iwin_base_lo); 138 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 139 PCIR_BARS + 0x14, sc->sc_iwin[2].iwin_base_hi); 140 } else { 141 sc->sc_iwin[2].iwin_base_lo = bus_space_read_4(sc->sc_st, 142 sc->sc_atu_sh, PCIR_BARS + 0x10); 143 sc->sc_iwin[2].iwin_base_hi = bus_space_read_4(sc->sc_st, 144 sc->sc_atu_sh, PCIR_BARS + 0x14); 145 sc->sc_iwin[2].iwin_base_lo = 146 PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo); 147 } 148 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR3, 149 (0xffffffff - (sc->sc_iwin[3].iwin_size - 1)) & 0xffffffc0); 150 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR3, 151 sc->sc_iwin[3].iwin_xlate); 152 153 if (sc->sc_is_host) { 154 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 155 ATU_IABAR3, sc->sc_iwin[3].iwin_base_lo); 156 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 157 ATU_IAUBAR3, sc->sc_iwin[3].iwin_base_hi); 158 } else { 159 sc->sc_iwin[3].iwin_base_lo = bus_space_read_4(sc->sc_st, 160 sc->sc_atu_sh, ATU_IABAR3); 161 sc->sc_iwin[3].iwin_base_hi = bus_space_read_4(sc->sc_st, 162 sc->sc_atu_sh, ATU_IAUBAR3); 163 sc->sc_iwin[3].iwin_base_lo = 164 PCI_MAPREG_MEM_ADDR(sc->sc_iwin[3].iwin_base_lo); 165 } 166 /* 167 * Mask (disable) the ATU interrupt sources. 168 * XXX May want to revisit this if we encounter 169 * XXX an application that wants it. 170 */ 171 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 172 ATU_ATUIMR, 173 ATUIMR_IMW1BU|ATUIMR_ISCEM|ATUIMR_RSCEM|ATUIMR_PST| 174 ATUIMR_DPE|ATUIMR_P_SERR_ASRT|ATUIMR_PMA|ATUIMR_PTAM| 175 ATUIMR_PTAT|ATUIMR_PMPE); 176 177 /* 178 * Program the outbound windows. 179 */ 180 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 181 ATU_OIOWTVR, sc->sc_ioout_xlate); 182 183 if (!sc->sc_is_host) { 184 sc->sc_owin[0].owin_xlate_lo = sc->sc_iwin[1].iwin_base_lo; 185 sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi; 186 } 187 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 188 ATU_OMWTVR0, sc->sc_owin[0].owin_xlate_lo); 189 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 190 ATU_OUMWTVR0, sc->sc_owin[0].owin_xlate_hi); 191 192 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 193 ATU_OMWTVR1, sc->sc_owin[1].owin_xlate_lo); 194 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 195 ATU_OUMWTVR1, sc->sc_owin[1].owin_xlate_hi); 196 197 /* 198 * Set up the ATU configuration register. All we do 199 * right now is enable Outbound Windows. 200 */ 201 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUCR, 202 ATUCR_OUT_EN); 203 204 /* 205 * Enable bus mastering, memory access, SERR, and parity 206 * checking on the ATU. 207 */ 208 if (sc->sc_is_host) { 209 preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, 210 PCIR_COMMAND); 211 preg |= PCIM_CMD_MEMEN | 212 PCIM_CMD_BUSMASTEREN | PCIM_CMD_PERRESPEN | 213 PCIM_CMD_SERRESPEN; 214 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 215 PCIR_COMMAND, preg); 216 } 217 /* Initialize the bus space tags. */ 218 i80321_io_bs_init(&sc->sc_pci_iot, sc); 219 i80321_mem_bs_init(&sc->sc_pci_memt, sc); 220 intr_enabled = 0; 221 i80321_set_intrmask(); 222 i80321_set_intrsteer(); 223} 224 225 226static __inline uint32_t 227i80321_iintsrc_read(void) 228{ 229 uint32_t iintsrc; 230 231 __asm __volatile("mrc p6, 0, %0, c8, c0, 0" 232 : "=r" (iintsrc)); 233 234 /* 235 * The IINTSRC register shows bits that are active even 236 * if they are masked in INTCTL, so we have to mask them 237 * off with the interrupts we consider enabled. 238 */ 239 return (iintsrc & intr_enabled); 240} 241 242int 243arm_get_next_irq(int last __unused) 244{ 245 int irq; 246 247 if ((irq = i80321_iintsrc_read())) 248 return (ffs(irq) - 1); 249 return (-1); 250} 251