BCM1480 HT support
PCI support code for PLX 7250 PCI-X tunnel on BCM91480B BigSur board.
Signed-Off-By: Andy Isaacson <adi@broadcom.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
···11+/*22+ * Copyright (C) 2001,2002,2005 Broadcom Corporation33+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)44+ *55+ * This program is free software; you can redistribute it and/or66+ * modify it under the terms of the GNU General Public License77+ * as published by the Free Software Foundation; either version 288+ * of the License, or (at your option) any later version.99+ *1010+ * This program is distributed in the hope that it will be useful,1111+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1212+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1313+ * GNU General Public License for more details.1414+ *1515+ * You should have received a copy of the GNU General Public License1616+ * along with this program; if not, write to the Free Software1717+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.1818+ */1919+2020+/*2121+ * BCM1480/1455-specific HT support (looking like PCI)2222+ *2323+ * This module provides the glue between Linux's PCI subsystem2424+ * and the hardware. We basically provide glue for accessing2525+ * configuration space, and set up the translation for I/O2626+ * space accesses.2727+ *2828+ * To access configuration space, we use ioremap. In the 32-bit2929+ * kernel, this consumes either 4 or 8 page table pages, and 16MB of3030+ * kernel mapped memory. Hopefully neither of these should be a huge3131+ * problem.3232+ *3333+ */3434+#include <linux/config.h>3535+#include <linux/types.h>3636+#include <linux/pci.h>3737+#include <linux/kernel.h>3838+#include <linux/init.h>3939+#include <linux/mm.h>4040+#include <linux/console.h>4141+#include <linux/tty.h>4242+4343+#include <asm/sibyte/bcm1480_regs.h>4444+#include <asm/sibyte/bcm1480_scd.h>4545+#include <asm/sibyte/board.h>4646+#include <asm/io.h>4747+4848+/*4949+ * Macros for calculating offsets into config space given a device5050+ * structure or dev/fun/reg5151+ */5252+#define CFGOFFSET(bus,devfn,where) (((bus)<<16)+((devfn)<<8)+(where))5353+#define CFGADDR(bus,devfn,where) CFGOFFSET((bus)->number,(devfn),where)5454+5555+static void *ht_cfg_space;5656+5757+#define PCI_BUS_ENABLED 15858+#define PCI_DEVICE_MODE 25959+6060+static int bcm1480ht_bus_status = 0;6161+6262+#define PCI_BRIDGE_DEVICE 06363+#define HT_BRIDGE_DEVICE 16464+6565+/*6666+ * HT's level-sensitive interrupts require EOI, which is generated6767+ * through a 4MB memory-mapped region6868+ */6969+unsigned long ht_eoi_space;7070+7171+/*7272+ * Read/write 32-bit values in config space.7373+ */7474+static inline u32 READCFG32(u32 addr)7575+{7676+ return *(u32 *)(ht_cfg_space + (addr&~3));7777+}7878+7979+static inline void WRITECFG32(u32 addr, u32 data)8080+{8181+ *(u32 *)(ht_cfg_space + (addr & ~3)) = data;8282+}8383+8484+/*8585+ * Some checks before doing config cycles:8686+ * In PCI Device Mode, hide everything on bus 0 except the LDT host8787+ * bridge. Otherwise, access is controlled by bridge MasterEn bits.8888+ */8989+static int bcm1480ht_can_access(struct pci_bus *bus, int devfn)9090+{9191+ u32 devno;9292+9393+ if (!(bcm1480ht_bus_status & (PCI_BUS_ENABLED | PCI_DEVICE_MODE)))9494+ return 0;9595+9696+ if (bus->number == 0) {9797+ devno = PCI_SLOT(devfn);9898+ if (bcm1480ht_bus_status & PCI_DEVICE_MODE)9999+ return 0;100100+ }101101+ return 1;102102+}103103+104104+/*105105+ * Read/write access functions for various sizes of values106106+ * in config space. Return all 1's for disallowed accesses107107+ * for a kludgy but adequate simulation of master aborts.108108+ */109109+110110+static int bcm1480ht_pcibios_read(struct pci_bus *bus, unsigned int devfn,111111+ int where, int size, u32 * val)112112+{113113+ u32 data = 0;114114+115115+ if ((size == 2) && (where & 1))116116+ return PCIBIOS_BAD_REGISTER_NUMBER;117117+ else if ((size == 4) && (where & 3))118118+ return PCIBIOS_BAD_REGISTER_NUMBER;119119+120120+ if (bcm1480ht_can_access(bus, devfn))121121+ data = READCFG32(CFGADDR(bus, devfn, where));122122+ else123123+ data = 0xFFFFFFFF;124124+125125+ if (size == 1)126126+ *val = (data >> ((where & 3) << 3)) & 0xff;127127+ else if (size == 2)128128+ *val = (data >> ((where & 3) << 3)) & 0xffff;129129+ else130130+ *val = data;131131+132132+ return PCIBIOS_SUCCESSFUL;133133+}134134+135135+static int bcm1480ht_pcibios_write(struct pci_bus *bus, unsigned int devfn,136136+ int where, int size, u32 val)137137+{138138+ u32 cfgaddr = CFGADDR(bus, devfn, where);139139+ u32 data = 0;140140+141141+ if ((size == 2) && (where & 1))142142+ return PCIBIOS_BAD_REGISTER_NUMBER;143143+ else if ((size == 4) && (where & 3))144144+ return PCIBIOS_BAD_REGISTER_NUMBER;145145+146146+ if (!bcm1480ht_can_access(bus, devfn))147147+ return PCIBIOS_BAD_REGISTER_NUMBER;148148+149149+ data = READCFG32(cfgaddr);150150+151151+ if (size == 1)152152+ data = (data & ~(0xff << ((where & 3) << 3))) |153153+ (val << ((where & 3) << 3));154154+ else if (size == 2)155155+ data = (data & ~(0xffff << ((where & 3) << 3))) |156156+ (val << ((where & 3) << 3));157157+ else158158+ data = val;159159+160160+ WRITECFG32(cfgaddr, data);161161+162162+ return PCIBIOS_SUCCESSFUL;163163+}164164+165165+static int bcm1480ht_pcibios_get_busno(void)166166+{167167+ return 0;168168+}169169+170170+struct pci_ops bcm1480ht_pci_ops = {171171+ .read = bcm1480ht_pcibios_read,172172+ .write = bcm1480ht_pcibios_write,173173+};174174+175175+static struct resource bcm1480ht_mem_resource = {176176+ .name = "BCM1480 HT MEM",177177+ .start = 0x40000000UL,178178+ .end = 0x5fffffffUL,179179+ .flags = IORESOURCE_MEM,180180+};181181+182182+static struct resource bcm1480ht_io_resource = {183183+ .name = "BCM1480 HT I/O",184184+ .start = 0x00000000UL,185185+ .end = 0x01ffffffUL,186186+ .flags = IORESOURCE_IO,187187+};188188+189189+struct pci_controller bcm1480ht_controller = {190190+ .pci_ops = &bcm1480ht_pci_ops,191191+ .mem_resource = &bcm1480ht_mem_resource,192192+ .io_resource = &bcm1480ht_io_resource,193193+ .index = 1,194194+ .get_busno = bcm1480ht_pcibios_get_busno,195195+};196196+197197+static int __init bcm1480ht_pcibios_init(void)198198+{199199+ uint32_t cmdreg;200200+201201+ ht_cfg_space = ioremap(A_BCM1480_PHYS_HT_CFG_MATCH_BITS, 16*1024*1024);202202+203203+ /*204204+ * See if the PCI bus has been configured by the firmware.205205+ */206206+ cmdreg = READCFG32(CFGOFFSET(0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0),207207+ PCI_COMMAND));208208+ if (!(cmdreg & PCI_COMMAND_MASTER)) {209209+ printk("HT: Skipping HT probe. Bus is not initialized.\n");210210+ iounmap(ht_cfg_space);211211+ return 1; /* XXX */212212+ }213213+ bcm1480ht_bus_status |= PCI_BUS_ENABLED;214214+215215+ ht_eoi_space = (unsigned long)216216+ ioremap(A_BCM1480_PHYS_HT_SPECIAL_MATCH_BYTES,217217+ 4 * 1024 * 1024);218218+219219+ register_pci_controller(&bcm1480ht_controller);220220+221221+ return 0;222222+}223223+224224+arch_initcall(bcm1480ht_pcibios_init);
+11-6
arch/mips/pci/pci.c
···127127 if (!hose->iommu)128128 PCI_DMA_BUS_IS_PHYS = 1;129129130130+ if (hose->get_busno && pci_probe_only)131131+ next_busno = (*hose->get_busno)();132132+130133 bus = pci_scan_bus(next_busno, hose->pci_ops, hose);131134 hose->bus = bus;132135 hose->need_domain_info = need_domain_info;133133- next_busno = bus->subordinate + 1;134134- /* Don't allow 8-bit bus number overflow inside the hose -135135- reserve some space for bridges. */136136- if (next_busno > 224) {137137- next_busno = 0;138138- need_domain_info = 1;136136+ if (bus) {137137+ next_busno = bus->subordinate + 1;138138+ /* Don't allow 8-bit bus number overflow inside the hose -139139+ reserve some space for bridges. */140140+ if (next_busno > 224) {141141+ next_busno = 0;142142+ need_domain_info = 1;143143+ }139144 }140145 continue;141146
+5
include/asm-mips/pci.h
···4040 unsigned int need_domain_info;41414242 int iommu;4343+4444+ /* Optional access methods for reading/writing the bus number4545+ of the PCI controller */4646+ int (*get_busno)(void);4747+ void (*set_busno)(int busno);4348};44494550/*