i80321.c revision 135669
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: head/sys/arm/xscale/i80321/i80321.c 135669 2004-09-23 22:45:36Z cognet $"); 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/* Built-in devices. */ 77static const struct iopxs_device { 78 const char *id_name; 79 bus_addr_t id_offset; 80 bus_size_t id_size; 81} iopxs_devices[] = { 82 { "iopaau", VERDE_AAU_BASE, VERDE_AAU_SIZE }, 83/* { "iopdma", VERDE_DMA_BASE0, VERDE_DMA_CHSIZE }, */ 84/* { "iopdma", VERDE_DMA_BASE1, VERDE_DMA_CHSIZE }, */ 85 { "iopiic", VERDE_I2C_BASE0, VERDE_I2C_CHSIZE }, 86 { "iopiic", VERDE_I2C_BASE1, VERDE_I2C_CHSIZE }, 87/* { "iopssp", VERDE_SSP_BASE, VERDE_SSP_SIZE }, */ 88 { "iopmu", VERDE_MU_BASE, VERDE_MU_SIZE }, 89 { "iopwdog", 0, 0 }, 90 { NULL, 0, 0 } 91}; 92 93#define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0) 94/* 95 * i80321_attach: 96 * 97 * Board-independent attach routine for the i80321. 98 */ 99void 100i80321_attach(struct i80321_softc *sc) 101{ 102 103 i80321_softc = sc; 104 uint32_t preg; 105 106 /* We expect the Memory Controller to be already sliced off. */ 107 108 /* 109 * Program the Inbound windows. 110 */ 111 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR0, 112 (0xffffffff - (sc->sc_iwin[0].iwin_size - 1)) & 0xffffffc0); 113 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR0, 114 sc->sc_iwin[0].iwin_xlate); 115 if (sc->sc_is_host) { 116 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 117 PCIR_MAPS, sc->sc_iwin[0].iwin_base_lo); 118 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 119 PCIR_MAPS + 0x04, sc->sc_iwin[0].iwin_base_hi); 120 } else { 121 sc->sc_iwin[0].iwin_base_lo = bus_space_read_4(sc->sc_st, 122 sc->sc_atu_sh, PCIR_MAPS); 123 sc->sc_iwin[0].iwin_base_hi = bus_space_read_4(sc->sc_st, 124 sc->sc_atu_sh, PCIR_MAPS + 0x04); 125 sc->sc_iwin[0].iwin_base_lo = 126 PCI_MAPREG_MEM_ADDR(sc->sc_iwin[0].iwin_base_lo); 127 } 128 129 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR1, 130 (0xffffffff - (sc->sc_iwin[1].iwin_size - 1)) & 0xffffffc0); 131 132 /* no xlate for window 1 */ 133 if (sc->sc_is_host) { 134 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 135 PCIR_MAPS + 0x08, sc->sc_iwin[1].iwin_base_lo); 136 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 137 PCIR_MAPS + 0x0c, sc->sc_iwin[1].iwin_base_hi); 138 } else { 139 sc->sc_iwin[1].iwin_base_lo = bus_space_read_4(sc->sc_st, 140 sc->sc_atu_sh, PCIR_MAPS + 0x08); 141 sc->sc_iwin[1].iwin_base_hi = bus_space_read_4(sc->sc_st, 142 sc->sc_atu_sh, PCIR_MAPS + 0x0c); 143 sc->sc_iwin[1].iwin_base_lo = 144 PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo); 145 } 146 147 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR2, 148 (0xffffffff - (sc->sc_iwin[2].iwin_size - 1)) & 0xffffffc0); 149 printf("size : %d\n", (sc->sc_iwin[2].iwin_size - 1) / (1024 * 1024)); 150 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR2, 151 sc->sc_iwin[2].iwin_xlate); 152 153 if (sc->sc_is_host) { 154 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 155 PCIR_MAPS + 0x10, sc->sc_iwin[2].iwin_base_lo); 156 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 157 PCIR_MAPS + 0x14, sc->sc_iwin[2].iwin_base_hi); 158 } else { 159 sc->sc_iwin[2].iwin_base_lo = bus_space_read_4(sc->sc_st, 160 sc->sc_atu_sh, PCIR_MAPS + 0x10); 161 sc->sc_iwin[2].iwin_base_hi = bus_space_read_4(sc->sc_st, 162 sc->sc_atu_sh, PCIR_MAPS + 0x14); 163 sc->sc_iwin[2].iwin_base_lo = 164 PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo); 165 } 166 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR3, 167 (0xffffffff - (sc->sc_iwin[3].iwin_size - 1)) & 0xffffffc0); 168 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR3, 169 sc->sc_iwin[3].iwin_xlate); 170 171 if (sc->sc_is_host) { 172 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 173 ATU_IABAR3, sc->sc_iwin[3].iwin_base_lo); 174 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 175 ATU_IAUBAR3, sc->sc_iwin[3].iwin_base_hi); 176 } else { 177 sc->sc_iwin[3].iwin_base_lo = bus_space_read_4(sc->sc_st, 178 sc->sc_atu_sh, ATU_IABAR3); 179 sc->sc_iwin[3].iwin_base_hi = bus_space_read_4(sc->sc_st, 180 sc->sc_atu_sh, ATU_IAUBAR3); 181 sc->sc_iwin[3].iwin_base_lo = 182 PCI_MAPREG_MEM_ADDR(sc->sc_iwin[3].iwin_base_lo); 183 } 184 /* 185 * Mask (disable) the ATU interrupt sources. 186 * XXX May want to revisit this if we encounter 187 * XXX an application that wants it. 188 */ 189 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 190 ATU_ATUIMR, 191 ATUIMR_IMW1BU|ATUIMR_ISCEM|ATUIMR_RSCEM|ATUIMR_PST| 192 ATUIMR_DPE|ATUIMR_P_SERR_ASRT|ATUIMR_PMA|ATUIMR_PTAM| 193 ATUIMR_PTAT|ATUIMR_PMPE); 194 195 /* 196 * Program the outbound windows. 197 */ 198 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 199 ATU_OIOWTVR, sc->sc_ioout_xlate); 200 201 if (!sc->sc_is_host) { 202 sc->sc_owin[0].owin_xlate_lo = sc->sc_iwin[1].iwin_base_lo; 203 sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi; 204 } 205 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 206 ATU_OMWTVR0, sc->sc_owin[0].owin_xlate_lo); 207 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 208 ATU_OUMWTVR0, sc->sc_owin[0].owin_xlate_hi); 209 210 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 211 ATU_OMWTVR1, sc->sc_owin[1].owin_xlate_lo); 212 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 213 ATU_OUMWTVR1, sc->sc_owin[1].owin_xlate_hi); 214 215 /* 216 * Set up the ATU configuration register. All we do 217 * right now is enable Outbound Windows. 218 */ 219 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUCR, 220 ATUCR_OUT_EN); 221 222 /* 223 * Enable bus mastering, memory access, SERR, and parity 224 * checking on the ATU. 225 */ 226 if (sc->sc_is_host) { 227 preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, 228 PCIR_COMMAND); 229 preg |= PCIM_CMD_MEMEN | 230 PCIM_CMD_BUSMASTEREN | PCIM_CMD_PERRESPEN | 231 PCIM_CMD_SERRESPEN; 232 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 233 PCIR_COMMAND, preg); 234 preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, 235 PCIR_COMMAND); 236 } 237 /* Initialize the bus space tags. */ 238 i80321_io_bs_init(&sc->sc_pci_iot, sc); 239 i80321_mem_bs_init(&sc->sc_pci_memt, sc); 240 intr_enabled = 0; 241 i80321_set_intrmask(); 242 i80321_set_intrsteer(); 243} 244 245 246static __inline uint32_t 247i80321_iintsrc_read(void) 248{ 249 uint32_t iintsrc; 250 251 __asm __volatile("mrc p6, 0, %0, c8, c0, 0" 252 : "=r" (iintsrc)); 253 254 /* 255 * The IINTSRC register shows bits that are active even 256 * if they are masked in INTCTL, so we have to mask them 257 * off with the interrupts we consider enabled. 258 */ 259 return (iintsrc & intr_enabled); 260} 261 262int 263arm_get_irqnb(void *clockframe) 264{ 265 266 return (i80321_iintsrc_read()); 267} 268 269 270