i80321.c revision 139735
1205194Sdelphij/* $NetBSD: i80321.c,v 1.15 2003/10/06 16:06:05 thorpej Exp $ */ 2205194Sdelphij 3205194Sdelphij/*- 4205194Sdelphij * Copyright (c) 2002 Wasabi Systems, Inc. 5205194Sdelphij * All rights reserved. 6205194Sdelphij * 7205194Sdelphij * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8205194Sdelphij * 9205194Sdelphij * Redistribution and use in source and binary forms, with or without 10205194Sdelphij * modification, are permitted provided that the following conditions 11205194Sdelphij * are met: 12205194Sdelphij * 1. Redistributions of source code must retain the above copyright 13205194Sdelphij * notice, this list of conditions and the following disclaimer. 14205194Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 15205194Sdelphij * notice, this list of conditions and the following disclaimer in the 16205194Sdelphij * documentation and/or other materials provided with the distribution. 17205194Sdelphij * 3. All advertising materials mentioning features or use of this software 18205194Sdelphij * must display the following acknowledgement: 19205194Sdelphij * This product includes software developed for the NetBSD Project by 20205194Sdelphij * Wasabi Systems, Inc. 21205194Sdelphij * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22205194Sdelphij * or promote products derived from this software without specific prior 23205194Sdelphij * written permission. 24205194Sdelphij * 25205194Sdelphij * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26205194Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27205194Sdelphij * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28205194Sdelphij * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29205194Sdelphij * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30205194Sdelphij * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31205194Sdelphij * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32205194Sdelphij * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33205194Sdelphij * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34205194Sdelphij * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35205194Sdelphij * POSSIBILITY OF SUCH DAMAGE. 36205194Sdelphij */ 37205194Sdelphij 38205194Sdelphij/* 39205194Sdelphij * Autoconfiguration support for the Intel i80321 I/O Processor. 40205194Sdelphij */ 41205194Sdelphij 42205194Sdelphij#include <sys/cdefs.h> 43205194Sdelphij__FBSDID("$FreeBSD: head/sys/arm/xscale/i80321/i80321.c 139735 2005-01-05 21:58:49Z imp $"); 44205194Sdelphij 45205194Sdelphij#include <sys/param.h> 46205194Sdelphij#include <sys/systm.h> 47205194Sdelphij#include <sys/bus.h> 48205194Sdelphij#include <sys/kernel.h> 49205194Sdelphij#include <sys/module.h> 50205194Sdelphij 51205194Sdelphij#define _ARM32_BUS_DMA_PRIVATE 52205194Sdelphij#include <machine/bus.h> 53205194Sdelphij#include <machine/intr.h> 54205194Sdelphij 55205194Sdelphij#include <arm/xscale/i80321/i80321reg.h> 56205194Sdelphij#include <arm/xscale/i80321/i80321var.h> 57205194Sdelphij#include <arm/xscale/i80321/i80321_intr.h> 58205194Sdelphij 59205194Sdelphij#include <dev/pci/pcireg.h> 60205194Sdelphij 61205194Sdelphijvolatile uint32_t intr_enabled; 62205194Sdelphijuint32_t intr_steer = 0; 63205194Sdelphij/* 64205194Sdelphij * Statically-allocated bus_space stucture used to access the 65205194Sdelphij * i80321's own registers. 66205194Sdelphij */ 67205194Sdelphijstruct bus_space i80321_bs_tag; 68205194Sdelphij 69205194Sdelphij/* 70205194Sdelphij * There can be only one i80321, so we keep a global pointer to 71205194Sdelphij * the softc, so board-specific code can use features of the 72205194Sdelphij * i80321 without having to have a handle on the softc itself. 73205194Sdelphij */ 74205194Sdelphijstruct i80321_softc *i80321_softc; 75205194Sdelphij 76205194Sdelphij/* Built-in devices. */ 77205194Sdelphijstatic const struct iopxs_device { 78205194Sdelphij const char *id_name; 79205194Sdelphij bus_addr_t id_offset; 80205194Sdelphij bus_size_t id_size; 81205194Sdelphij} iopxs_devices[] = { 82205194Sdelphij { "iopaau", VERDE_AAU_BASE, VERDE_AAU_SIZE }, 83205194Sdelphij/* { "iopdma", VERDE_DMA_BASE0, VERDE_DMA_CHSIZE }, */ 84205194Sdelphij/* { "iopdma", VERDE_DMA_BASE1, VERDE_DMA_CHSIZE }, */ 85205194Sdelphij { "iopiic", VERDE_I2C_BASE0, VERDE_I2C_CHSIZE }, 86205194Sdelphij { "iopiic", VERDE_I2C_BASE1, VERDE_I2C_CHSIZE }, 87205194Sdelphij/* { "iopssp", VERDE_SSP_BASE, VERDE_SSP_SIZE }, */ 88205194Sdelphij { "iopmu", VERDE_MU_BASE, VERDE_MU_SIZE }, 89205194Sdelphij { "iopwdog", 0, 0 }, 90205194Sdelphij { NULL, 0, 0 } 91205194Sdelphij}; 92205194Sdelphij 93205194Sdelphij#define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0) 94205194Sdelphij/* 95205194Sdelphij * i80321_attach: 96205194Sdelphij * 97205194Sdelphij * Board-independent attach routine for the i80321. 98205194Sdelphij */ 99205194Sdelphijvoid 100205194Sdelphiji80321_attach(struct i80321_softc *sc) 101205194Sdelphij{ 102205194Sdelphij 103205194Sdelphij i80321_softc = sc; 104205194Sdelphij uint32_t preg; 105205194Sdelphij 106205194Sdelphij /* We expect the Memory Controller to be already sliced off. */ 107205194Sdelphij 108205194Sdelphij /* 109205194Sdelphij * Program the Inbound windows. 110205194Sdelphij */ 111205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR0, 112205194Sdelphij (0xffffffff - (sc->sc_iwin[0].iwin_size - 1)) & 0xffffffc0); 113205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR0, 114205194Sdelphij sc->sc_iwin[0].iwin_xlate); 115205194Sdelphij if (sc->sc_is_host) { 116205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 117205194Sdelphij PCIR_MAPS, sc->sc_iwin[0].iwin_base_lo); 118205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 119205194Sdelphij PCIR_MAPS + 0x04, sc->sc_iwin[0].iwin_base_hi); 120205194Sdelphij } else { 121205194Sdelphij sc->sc_iwin[0].iwin_base_lo = bus_space_read_4(sc->sc_st, 122205194Sdelphij sc->sc_atu_sh, PCIR_MAPS); 123205194Sdelphij sc->sc_iwin[0].iwin_base_hi = bus_space_read_4(sc->sc_st, 124205194Sdelphij sc->sc_atu_sh, PCIR_MAPS + 0x04); 125205194Sdelphij sc->sc_iwin[0].iwin_base_lo = 126205194Sdelphij PCI_MAPREG_MEM_ADDR(sc->sc_iwin[0].iwin_base_lo); 127205194Sdelphij } 128205194Sdelphij 129205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR1, 130205194Sdelphij (0xffffffff - (sc->sc_iwin[1].iwin_size - 1)) & 0xffffffc0); 131205194Sdelphij 132205194Sdelphij /* no xlate for window 1 */ 133205194Sdelphij if (sc->sc_is_host) { 134205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 135205194Sdelphij PCIR_MAPS + 0x08, sc->sc_iwin[1].iwin_base_lo); 136205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 137205194Sdelphij PCIR_MAPS + 0x0c, sc->sc_iwin[1].iwin_base_hi); 138205194Sdelphij } else { 139205194Sdelphij sc->sc_iwin[1].iwin_base_lo = bus_space_read_4(sc->sc_st, 140205194Sdelphij sc->sc_atu_sh, PCIR_MAPS + 0x08); 141205194Sdelphij sc->sc_iwin[1].iwin_base_hi = bus_space_read_4(sc->sc_st, 142205194Sdelphij sc->sc_atu_sh, PCIR_MAPS + 0x0c); 143205194Sdelphij sc->sc_iwin[1].iwin_base_lo = 144205194Sdelphij PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo); 145205194Sdelphij } 146205194Sdelphij 147205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR2, 148205194Sdelphij (0xffffffff - (sc->sc_iwin[2].iwin_size - 1)) & 0xffffffc0); 149205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR2, 150205194Sdelphij sc->sc_iwin[2].iwin_xlate); 151205194Sdelphij 152205194Sdelphij if (sc->sc_is_host) { 153205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 154205194Sdelphij PCIR_MAPS + 0x10, sc->sc_iwin[2].iwin_base_lo); 155205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 156205194Sdelphij PCIR_MAPS + 0x14, sc->sc_iwin[2].iwin_base_hi); 157205194Sdelphij } else { 158205194Sdelphij sc->sc_iwin[2].iwin_base_lo = bus_space_read_4(sc->sc_st, 159205194Sdelphij sc->sc_atu_sh, PCIR_MAPS + 0x10); 160205194Sdelphij sc->sc_iwin[2].iwin_base_hi = bus_space_read_4(sc->sc_st, 161205194Sdelphij sc->sc_atu_sh, PCIR_MAPS + 0x14); 162205194Sdelphij sc->sc_iwin[2].iwin_base_lo = 163205194Sdelphij PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo); 164205194Sdelphij } 165205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR3, 166205194Sdelphij (0xffffffff - (sc->sc_iwin[3].iwin_size - 1)) & 0xffffffc0); 167205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR3, 168205194Sdelphij sc->sc_iwin[3].iwin_xlate); 169205194Sdelphij 170205194Sdelphij if (sc->sc_is_host) { 171205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 172205194Sdelphij ATU_IABAR3, sc->sc_iwin[3].iwin_base_lo); 173205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 174205194Sdelphij ATU_IAUBAR3, sc->sc_iwin[3].iwin_base_hi); 175205194Sdelphij } else { 176205194Sdelphij sc->sc_iwin[3].iwin_base_lo = bus_space_read_4(sc->sc_st, 177205194Sdelphij sc->sc_atu_sh, ATU_IABAR3); 178205194Sdelphij sc->sc_iwin[3].iwin_base_hi = bus_space_read_4(sc->sc_st, 179205194Sdelphij sc->sc_atu_sh, ATU_IAUBAR3); 180205194Sdelphij sc->sc_iwin[3].iwin_base_lo = 181205194Sdelphij PCI_MAPREG_MEM_ADDR(sc->sc_iwin[3].iwin_base_lo); 182205194Sdelphij } 183205194Sdelphij /* 184205194Sdelphij * Mask (disable) the ATU interrupt sources. 185205194Sdelphij * XXX May want to revisit this if we encounter 186205194Sdelphij * XXX an application that wants it. 187205194Sdelphij */ 188205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 189205194Sdelphij ATU_ATUIMR, 190205194Sdelphij ATUIMR_IMW1BU|ATUIMR_ISCEM|ATUIMR_RSCEM|ATUIMR_PST| 191205194Sdelphij ATUIMR_DPE|ATUIMR_P_SERR_ASRT|ATUIMR_PMA|ATUIMR_PTAM| 192205194Sdelphij ATUIMR_PTAT|ATUIMR_PMPE); 193205194Sdelphij 194205194Sdelphij /* 195205194Sdelphij * Program the outbound windows. 196205194Sdelphij */ 197205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 198205194Sdelphij ATU_OIOWTVR, sc->sc_ioout_xlate); 199205194Sdelphij 200205194Sdelphij if (!sc->sc_is_host) { 201205194Sdelphij sc->sc_owin[0].owin_xlate_lo = sc->sc_iwin[1].iwin_base_lo; 202205194Sdelphij sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi; 203205194Sdelphij } 204205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 205205194Sdelphij ATU_OMWTVR0, sc->sc_owin[0].owin_xlate_lo); 206205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 207205194Sdelphij ATU_OUMWTVR0, sc->sc_owin[0].owin_xlate_hi); 208205194Sdelphij 209205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 210205194Sdelphij ATU_OMWTVR1, sc->sc_owin[1].owin_xlate_lo); 211205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 212205194Sdelphij ATU_OUMWTVR1, sc->sc_owin[1].owin_xlate_hi); 213205194Sdelphij 214205194Sdelphij /* 215205194Sdelphij * Set up the ATU configuration register. All we do 216205194Sdelphij * right now is enable Outbound Windows. 217205194Sdelphij */ 218205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUCR, 219205194Sdelphij ATUCR_OUT_EN); 220205194Sdelphij 221205194Sdelphij /* 222205194Sdelphij * Enable bus mastering, memory access, SERR, and parity 223205194Sdelphij * checking on the ATU. 224205194Sdelphij */ 225205194Sdelphij if (sc->sc_is_host) { 226205194Sdelphij preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, 227205194Sdelphij PCIR_COMMAND); 228205194Sdelphij preg |= PCIM_CMD_MEMEN | 229205194Sdelphij PCIM_CMD_BUSMASTEREN | PCIM_CMD_PERRESPEN | 230205194Sdelphij PCIM_CMD_SERRESPEN; 231205194Sdelphij bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 232205194Sdelphij PCIR_COMMAND, preg); 233205194Sdelphij preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, 234205194Sdelphij PCIR_COMMAND); 235205194Sdelphij } 236205194Sdelphij /* Initialize the bus space tags. */ 237205194Sdelphij i80321_io_bs_init(&sc->sc_pci_iot, sc); 238205194Sdelphij i80321_mem_bs_init(&sc->sc_pci_memt, sc); 239205194Sdelphij intr_enabled = 0; 240205194Sdelphij i80321_set_intrmask(); 241205194Sdelphij i80321_set_intrsteer(); 242205194Sdelphij} 243205194Sdelphij 244205194Sdelphij 245205194Sdelphijstatic __inline uint32_t 246205194Sdelphiji80321_iintsrc_read(void) 247205194Sdelphij{ 248205194Sdelphij uint32_t iintsrc; 249205194Sdelphij 250205194Sdelphij __asm __volatile("mrc p6, 0, %0, c8, c0, 0" 251205194Sdelphij : "=r" (iintsrc)); 252205194Sdelphij 253205194Sdelphij /* 254205194Sdelphij * The IINTSRC register shows bits that are active even 255205194Sdelphij * if they are masked in INTCTL, so we have to mask them 256205194Sdelphij * off with the interrupts we consider enabled. 257205194Sdelphij */ 258205194Sdelphij return (iintsrc & intr_enabled); 259205194Sdelphij} 260205194Sdelphij 261205194Sdelphijint 262205194Sdelphijarm_get_irqnb(void *clockframe) 263205194Sdelphij{ 264205194Sdelphij 265205194Sdelphij return (i80321_iintsrc_read()); 266205194Sdelphij} 267205194Sdelphij 268205194Sdelphij 269205194Sdelphij