[PATCH 9/16] Supporting of PCI bus for Celleb
Ishizaki Kou
kou.ishizaki at toshiba.co.jp
Wed Nov 15 20:45:32 EST 2006
This patch includes support for pci buses, base of Celleb specific devices,
and etc.
Signed-off-by: Kou Ishizaki <kou.ishizaki at toshiba.co.jp>
---
Index: linux-2.6.19/arch/powerpc/platforms/celleb/ioif.c
diff -u /dev/null linux-2.6.19/arch/powerpc/platforms/celleb/ioif.c:1.1
--- /dev/null Thu Nov 9 18:40:50 2006
+++ linux-2.6.19/arch/powerpc/platforms/celleb/ioif.c Fri Oct 6 16:13:37 2006
@@ -0,0 +1,48 @@
+/*
+ * Celleb IOIF management
+ *
+ * (C) Copyright 2006 TOSHIBA CORPORATION
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bootmem.h>
+
+#include <asm/prom.h>
+#include <asm/iommu.h>
+
+#include "ioif.h"
+
+
+static inline void ioif_setup(struct ioif *ioif, struct device_node *dn)
+{
+ ioif->iommu_table = NULL;
+}
+
+struct ioif *ioif_alloc(struct device_node *dn)
+{
+ struct ioif *ioif;
+
+ if (mem_init_done)
+ ioif = kmalloc(sizeof(struct ioif), GFP_KERNEL);
+ else
+ ioif = alloc_bootmem(sizeof(struct ioif));
+
+ if (ioif)
+ ioif_setup(ioif, dn);
+
+ return ioif;
+}
Index: linux-2.6.19/arch/powerpc/platforms/celleb/ioif.h
diff -u /dev/null linux-2.6.19/arch/powerpc/platforms/celleb/ioif.h:1.1
--- /dev/null Thu Nov 9 18:40:50 2006
+++ linux-2.6.19/arch/powerpc/platforms/celleb/ioif.h Fri Oct 6 16:13:37 2006
@@ -0,0 +1,31 @@
+/*
+ * CBE IOIF description
+ *
+ * (C) Copyright 2006 TOSHIBA CORPORATION
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __CELLEB_IOIF_H__
+#define __CELLEB_IOIF_H__
+
+struct ioif {
+ struct iommu_table *iommu_table;
+};
+
+
+struct ioif *ioif_alloc(struct device_node *dn);
+
+#endif
Index: linux-2.6.19/arch/powerpc/platforms/celleb/celleb_pci.c
diff -u /dev/null linux-2.6.19/arch/powerpc/platforms/celleb/celleb_pci.c:1.2
--- /dev/null Thu Nov 9 18:40:50 2006
+++ linux-2.6.19/arch/powerpc/platforms/celleb/celleb_pci.c Mon Nov 6 20:16:26 2006
@@ -0,0 +1,583 @@
+/*
+ * Support for PCI on Celleb platform.
+ *
+ * (C) Copyright 2006 TOSHIBA CORPORATION
+ *
+ * This code is based on arch/powerpc/kernel/rtas_pci.c:
+ * Copyright (C) 2001 Dave Engebretsen, IBM Corporation
+ * Copyright (C) 2003 Anton Blanchard <anton at au.ibm.com>, IBM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/threads.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/pci_regs.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/iommu.h>
+#include <asm/rtas.h>
+#include <asm/mpic.h>
+#include <asm/ppc-pci.h>
+
+#include "celleb_scc.h"
+#include "interrupt.h"
+#include "ioif.h"
+
+//#define DEBUG
+#undef DEBUG
+
+#define MAX_PCI_DEVICES 32
+#define MAX_PCI_FUNCTIONS 8
+
+
+/* dummy pci configuration area for GbE, .... ,and etc. */
+unsigned char *fake_config[MAX_PCI_DEVICES][MAX_PCI_FUNCTIONS];
+
+unsigned int celleb_config_valid[MAX_PCI_DEVICES];
+unsigned long celleb_iobase[MAX_PCI_DEVICES][MAX_PCI_FUNCTIONS][3];
+unsigned long celleb_iosize[MAX_PCI_DEVICES][MAX_PCI_FUNCTIONS][3];
+
+extern int
+__init celleb_setup_pci_bridge(struct device_node *, struct pci_controller *);
+
+static int
+celleb_dummy_pci_read_config(struct pci_bus *bus,
+ unsigned int devfn,
+ int where, int size, u32 *val)
+{
+
+
+ return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+
+static int
+celleb_dummy_pci_write_config(struct pci_bus *bus,
+ unsigned int devfn,
+ int where, int size, u32 val)
+{
+
+ return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+struct pci_ops celleb_dummy_pci_ops = {
+/* for generic PCI buses/devices */
+ celleb_dummy_pci_read_config,
+ celleb_dummy_pci_write_config
+};
+
+void
+celleb_config_read_fake(unsigned char *config, int where, int size, u32 *val)
+{
+ char *p=config+where;
+ u32 *p32;
+
+ p32 = (u32 *)p;
+
+ switch(size){
+ case 1:
+ *val = (*p32)>>24 & 0xff;
+ break;
+ case 2:
+ *val =(*p32)>>16 & 0xffff;
+ break;
+ case 4:
+ *val =(*p32);
+ break;
+ }
+
+ return;
+
+}
+
+void
+celleb_config_write_fake(unsigned char *config, int where, int size, u32 val)
+{
+ char *p=config+where;
+ int i;
+ char n;
+
+ switch(size){
+ case 1:
+ n = (char)val;
+ *p = n;
+ break;
+ case 2:
+ for(i=0;i<2;i++,p++){
+ n = (char)(val >> (8*(1-i)));
+ *p = n;
+ }
+ break;
+ case 4:
+ for(i=0;i<4;i++,p++){
+ n = (char)(val >> (8*(3-i)));
+ *p = n;
+ }
+ break;
+ }
+ return;
+
+}
+
+static int
+celleb_fake_pci_read_config(struct pci_bus *bus,
+ unsigned int devfn,
+ int where, int size, u32 *val)
+{
+
+ char *config;
+ unsigned int devno = devfn >> 3;
+ unsigned int fn = devfn & 0x7;
+
+#ifdef DEBUG
+ printk(" fake read: bus=0x%x, ", bus->number);
+#endif
+
+ config = fake_config[devno][fn];
+
+#ifdef DEBUG
+ printk("devno=0x%x, where=0x%x, size=0x%x, ",
+ devno, where, size);
+#endif
+ if(!celleb_config_valid[devno] || !config){
+#ifdef DEBUG
+ printk("failed\n");
+#endif
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ celleb_config_read_fake(config, where, size, val);
+
+#ifdef DEBUG
+ printk("val=0x%x\n", *val);
+#endif
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int
+celleb_fake_pci_write_config(struct pci_bus *bus,
+ unsigned int devfn,
+ int where, int size, u32 val)
+{
+
+ char *config;
+ unsigned int devno = devfn >> 3;
+ unsigned int fn = devfn & 0x7;
+
+ config = fake_config[devno][fn];
+
+ if(!celleb_config_valid[devno] || !config){
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ if(val == ~0){
+ int i=(where-PCI_BASE_ADDRESS_0)>>3;
+
+ switch(where){
+ case PCI_BASE_ADDRESS_0:
+ case PCI_BASE_ADDRESS_2:
+ if(size!=4){
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ celleb_config_write_fake(config, where, size,
+ celleb_iosize[devno][fn][i]);
+ return PCIBIOS_SUCCESSFUL;
+ case PCI_BASE_ADDRESS_1:
+ case PCI_BASE_ADDRESS_3:
+ case PCI_BASE_ADDRESS_4:
+ case PCI_BASE_ADDRESS_5:
+ break;
+ default:
+ break;
+ }
+ }
+
+
+ celleb_config_write_fake(config, where, size, val);
+#ifdef DEBUG
+ printk(" fake write: where=%x, size=%d, val=%x\n",
+ where, size, val);
+#endif
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops celleb_fake_pci_ops = {
+ celleb_fake_pci_read_config,
+ celleb_fake_pci_write_config
+};
+
+
+int
+celleb_setup_pci_base_addrs(struct device_node *node,
+ unsigned int devno,
+ unsigned int fn,
+ unsigned int num_base_addr)
+{
+
+ u32 val;
+ unsigned char *config;
+
+ config = fake_config[devno][fn];
+ if(!config){
+ return 1;
+ }
+
+ switch(num_base_addr){
+ case 3: /* FALLTHROUGH */
+ val = (celleb_iobase[devno][fn][2] & 0xfffffff0)
+ | PCI_BASE_ADDRESS_MEM_TYPE_64;
+ celleb_config_write_fake(config, PCI_BASE_ADDRESS_4, 4, val);
+ val = celleb_iobase[devno][fn][2] >> 32;
+ celleb_config_write_fake(config, PCI_BASE_ADDRESS_5, 4, val);
+ case 2: /* FALLTHROUGH */
+ val = (celleb_iobase[devno][fn][1] & 0xfffffff0)
+ | PCI_BASE_ADDRESS_MEM_TYPE_64;
+ celleb_config_write_fake(config, PCI_BASE_ADDRESS_2, 4, val);
+ val = celleb_iobase[devno][fn][1] >> 32;
+ celleb_config_write_fake(config, PCI_BASE_ADDRESS_3, 4, val);
+ case 1:
+ val = (celleb_iobase[devno][fn][0] & 0xfffffff0)
+ | PCI_BASE_ADDRESS_MEM_TYPE_64;
+ celleb_config_write_fake(config, PCI_BASE_ADDRESS_0, 4, val);
+ val = celleb_iobase[devno][fn][0] >> 32;
+ celleb_config_write_fake(config, PCI_BASE_ADDRESS_1, 4, val);
+ break;
+ }
+
+ val = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+ celleb_config_write_fake(config, PCI_COMMAND, 2, val);
+
+ return 0;
+
+}
+
+int __init
+celleb_setup_fake_pci(struct device_node *node)
+{
+ unsigned int rlen, num_base_addr;
+ u32 val;
+ u32 *wi0, *wi1, *wi2, *wi3, *wi4;
+ unsigned int devno, fn;
+ char *config;
+ char *name;
+ unsigned long *li;
+ int size;
+ int i;
+
+
+ name = (char *)get_property(node, "model", &rlen);
+ if(!name){
+ printk("PCI: model property not found.\n");
+ return -1;
+ }
+
+ wi4 = (uint32_t*)get_property(node, "reg", &rlen);
+ if(wi4 == NULL){
+ goto error;
+ }
+ devno = ((wi4[0] >> 8) & 0xff) >> 3;
+ fn = (wi4[0] >> 8) & 0x7;
+
+#ifdef DEBUG
+ printk("PCI: celleb_setup_fake_pci() %s devno=%x fn=%x\n", name, devno, fn);
+#endif
+
+ size = 256;
+ if(mem_init_done)
+ fake_config[devno][fn] = (unsigned char *)kmalloc(size, GFP_KERNEL);
+ else
+ fake_config[devno][fn] = (unsigned char *)alloc_bootmem(size);
+
+ if(fake_config[devno][fn] == NULL){
+ printk(KERN_ERR "PCI: not enough memory for dummy configuration space\n");
+ goto error;
+ }
+
+ config = fake_config[devno][fn];
+ memset(config, 0, size);
+
+ wi0 = (uint32_t*)get_property(node, "device-id", NULL);
+ wi1 = (uint32_t*)get_property(node, "vendor-id", NULL);
+ wi2 = (uint32_t*)get_property(node, "class-code", NULL);
+ wi3 = (uint32_t*)get_property(node, "revision-id", NULL);
+
+ celleb_config_write_fake(config, PCI_DEVICE_ID, 2, wi0[0]&0xffff);
+ celleb_config_write_fake(config, PCI_VENDOR_ID, 2, wi1[0]&0xffff);
+#ifdef DEBUG
+ printk("class-code = 0x%x\n", wi2[0]);
+#endif
+ celleb_config_write_fake(config, PCI_CLASS_PROG, 1, wi2[0]&0xff);
+ celleb_config_write_fake(config, PCI_CLASS_DEVICE, 2,
+ (wi2[0]>>8)&0xffff);
+ celleb_config_write_fake(config, PCI_REVISION_ID, 1, wi3[0]);
+
+ li = (unsigned long *)get_property(node, "toshiba,reg", &rlen);
+
+ if(li){
+ num_base_addr = rlen >> 4 ;
+
+ if(num_base_addr > 3){
+ num_base_addr = 3;
+ }
+
+#ifdef DEBUG
+ printk("PCI: %s: number of base addresses is %d\n", name, num_base_addr);
+#endif
+
+ for(i=0; i < num_base_addr; i++){
+ celleb_iobase[devno][fn][i] = li[i*2];
+ celleb_iosize[devno][fn][i] = li[i*2+1];
+#ifdef DEBUG
+ printk("PCI: base address %d: 0x%lx-0x%lx\n", i, li[i*2], li[i*2+1]);
+#endif
+ }
+
+ }else{
+ printk(KERN_ERR "PCI: No toshiba,reg property\n");
+ goto error;
+ }
+
+ celleb_setup_pci_base_addrs(node, devno, fn, num_base_addr);
+
+
+ li = (unsigned long *)get_property(node, "interrupts", &rlen);
+ val = li[0];
+ celleb_config_write_fake(config, PCI_INTERRUPT_PIN, 1, 1);
+ celleb_config_write_fake(config, PCI_INTERRUPT_LINE, 1, val);
+
+#ifdef DEBUG
+ printk("PCI: %s irq=%ld\n", name, li[0]);
+ for(i=0; i<6; i++){
+ celleb_config_read_fake(config, PCI_BASE_ADDRESS_0+0x4*i, 4, &val);
+ printk("PCI: %s fn=%d base_address_%d=0x%x\n", name, fn, i, val);
+ }
+#endif
+
+
+ celleb_config_write_fake(config, PCI_HEADER_TYPE, 1, PCI_HEADER_TYPE_NORMAL);
+
+ celleb_config_valid[devno] = 1;
+
+ return 0;
+
+error:
+ return 1;
+
+}
+
+
+static void __init celleb_pcibios_fixup(void)
+{
+ struct pci_dev *dev = NULL;
+ struct pci_bus *bus;
+ struct list_head *ln;
+
+ for_each_pci_dev(dev){
+
+ bus = dev->bus;
+
+ if(bus && ppc_md.pci_probe_mode(bus) == PCI_PROBE_NORMAL){
+ continue;
+ }
+
+ pci_read_irq_line(dev);
+
+ }
+
+ list_for_each(ln, &pci_root_buses){
+ bus = pci_bus_b(ln);
+ if(ppc_md.pci_probe_mode(bus) == PCI_PROBE_NORMAL){
+ dev = NULL;
+#if 1 /* XXX: This is for SYSCON workaround */
+ list_for_each_entry(dev, &bus->devices, bus_list){
+ int i;
+ if((dev->class >> 8) != PCI_CLASS_BRIDGE_HOST)
+ continue;
+ for(i = 0; i < PCI_NUM_RESOURCES; i++ ){
+ struct resource *r = NULL;
+ struct resource *root = NULL;
+ r = &dev->resource[i];
+ root = pcibios_select_root(dev, r);
+ if(!(r->flags) || r->parent){
+ continue;
+ }
+ insert_resource(root, r);
+ }
+ }
+#endif
+ pci_bus_assign_resources(bus);
+ pci_enable_bridges(bus);
+ }
+ }
+
+ return;
+
+}
+
+static int
+phb_set_bus_ranges(struct device_node *dev, struct pci_controller *phb)
+{
+ int *bus_range;
+ unsigned int len;
+
+ bus_range = (int *) get_property(dev, "bus-range", &len);
+ if (bus_range == NULL || len < 2 * sizeof(int)) {
+ return 1;
+ }
+
+ phb->first_busno = bus_range[0];
+ phb->last_busno = bus_range[1];
+
+ return 0;
+}
+
+extern struct pci_ops celleb_epci_ops;
+
+int __devinit
+celleb_setup_phb(struct device_node *dev, struct pci_controller *phb)
+{
+
+ const char *name;
+ unsigned int rlen;
+ extern int celleb_setup_epci(struct device_node *, struct pci_controller *);
+ struct device_node *node;
+
+ if (phb_set_bus_ranges(dev, phb))
+ return 1;
+
+ name = get_property(dev, "name", &rlen);
+
+ if(!name){
+ phb->ops = &celleb_dummy_pci_ops;
+ }else if(strcmp(name, "epci") == 0){
+ phb->ops = &celleb_epci_ops;
+ celleb_setup_epci(dev, phb);
+ }else if(strcmp(name, "pci-pseudo") == 0){
+ phb->ops = &celleb_fake_pci_ops;
+ for (node = of_get_next_child(dev, NULL);
+ node != NULL;
+ node = of_get_next_child(dev, node)){
+ celleb_setup_fake_pci(node);
+ }
+
+ }else{
+ phb->ops = &celleb_dummy_pci_ops;
+ }
+
+
+ phb->buid = get_phb_buid(dev);
+
+ return 0;
+}
+
+
+static unsigned int __init init_phbs_ioif_recursive(
+ struct device_node *parent, unsigned int index)
+{
+ struct device_node *node;
+ struct pci_controller *phb;
+ struct ioif *ioif;
+
+ for (node = of_get_next_child(parent, NULL);
+ node != NULL;
+ node = of_get_next_child(parent, node)) {
+
+ if (node->type == NULL)
+ continue;
+
+ if (strcmp(node->type,"pci") == 0 || strcmp(node->type,"pciex") == 0) {
+ phb = pcibios_alloc_controller(node);
+ if (!phb)
+ continue;
+
+ celleb_setup_phb(node, phb);
+ pci_process_bridge_OF_ranges(phb, node, 0);
+ pci_setup_phb_io(phb, index == 0);
+ index++;
+ } else if (strcmp(node->type, "ioif") == 0) {
+ ioif = ioif_alloc(node);
+ if (!ioif)
+ continue;
+ node->data = ioif;
+ index = init_phbs_ioif_recursive(node, index);
+ }
+ }
+
+ return index;
+}
+
+unsigned long __init
+celleb_find_and_init_phbs(void)
+{
+ unsigned int index;
+ unsigned int root_size_cells = 0;
+ struct device_node *root = of_find_node_by_path("/");
+
+ int i;
+
+ for( i=0 ;i<MAX_PCI_DEVICES ; i++){
+ int j, k;
+ celleb_config_valid[i] = 0;
+
+ for( j=0; j<MAX_PCI_FUNCTIONS; j++){
+ fake_config[i][j] = NULL;
+ for(k=0; k<3; k++){
+ celleb_iobase[i][j][k] = 0;
+ celleb_iosize[i][j][k] = 0;
+ }
+ }
+ }
+
+ ppc_md.pcibios_fixup = celleb_pcibios_fixup;
+
+ root_size_cells = prom_n_size_cells(root);
+
+ index = 0;
+
+ init_phbs_ioif_recursive(root, index);
+
+ of_node_put(root);
+ pci_devs_phb_init();
+
+ /*
+ * pci_probe_only and pci_assign_all_buses can be set via properties
+ * in chosen.
+ */
+ if (of_chosen) {
+ int *prop;
+
+ prop = (int *)get_property(of_chosen, "linux,pci-probe-only",
+ NULL);
+ if (prop)
+ pci_probe_only = *prop;
+
+ }
+
+ return 0;
+}
+
Index: linux-2.6.19/arch/powerpc/platforms/celleb/celleb_epci.c
diff -u /dev/null linux-2.6.19/arch/powerpc/platforms/celleb/celleb_epci.c:1.2
--- /dev/null Thu Nov 9 18:40:50 2006
+++ linux-2.6.19/arch/powerpc/platforms/celleb/celleb_epci.c Tue Nov 7 13:51:31 2006
@@ -0,0 +1,583 @@
+/*
+ * Support for Celleb external PCI
+ *
+ * (C) Copyright 2004-2006 TOSHIBA CORPORATION
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/threads.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/pci_regs.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/iommu.h>
+#include <asm/rtas.h>
+#include <asm/mpic.h>
+#include <asm/ppc-pci.h>
+
+#include "celleb_scc.h"
+#include "interrupt.h"
+
+//#define DEBUG
+#undef DEBUG
+
+#define MAX_PCI_DEVICES 32
+#define MAX_PCI_FUNCTIONS 8
+
+#define iob() __asm__ __volatile__("eieio; sync":::"memory")
+
+unsigned int epci_ext_irq=0L;
+unsigned int epci_int_irq=0L;
+
+void celleb_epci_dummy_read(struct pci_dev *dev){
+
+ unsigned long epci_base;
+ struct device_node *node;
+ struct pci_controller *hose;
+ u32 val;
+
+ node = (struct device_node *)dev->bus->sysdata;
+ hose = pci_find_hose_for_OF_device(node);
+
+ if(!hose)
+ return;
+
+ epci_base = (unsigned long)hose->cfg_addr;
+
+ val = in_be32((void *)(epci_base + SCC_EPCI_WATRP));
+
+ return;
+}
+
+static int
+celleb_epci_check_abort(struct pci_controller *hose, unsigned long addr)
+{
+
+ unsigned long reg;
+ unsigned long epci_base;
+ u32 val;
+
+
+ iob();
+ epci_base = (unsigned long)hose->cfg_addr;
+
+ reg = epci_base + PCI_COMMAND;
+ val = in_be32((void *)reg);
+
+ if ( val & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
+ out_be32((void *)reg,
+ (val & 0x0000ffff) |(PCI_STATUS_REC_MASTER_ABORT << 16));
+
+ /* clear PCI Contro0ller error, FRE, PMFE */
+ reg = epci_base + SCC_EPCI_STATUS;
+ out_be32((void *)reg, SCC_EPCI_INT_PAI);
+
+ reg = epci_base + SCC_EPCI_VCSR;
+ val = in_be32((void *)reg) & 0xffff;
+ val |= SCC_EPCI_VCSR_FRE;
+ out_be32((void *)reg, val);
+
+ reg = epci_base + SCC_EPCI_VISTAT;
+ out_be32((void *)reg, SCC_EPCI_VISTAT_PMFE);
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+
+}
+
+int
+celleb_epci_subordinate_read_config(struct pci_controller *hose,
+ int bus, unsigned int devfn,
+ int where, int size, u32 *val)
+{
+
+ unsigned long addr;
+
+ if( !hose->cfg_data )
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+
+ if(where == PCI_INTERRUPT_LINE){
+ *val = irq_create_mapping(NULL, epci_ext_irq);
+ return PCIBIOS_SUCCESSFUL;
+ }else if(where == PCI_INTERRUPT_PIN){
+ *val = 1;
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ /* Clear and Disable Master Abort interrupt */
+ addr = (unsigned long)hose->cfg_addr + PCI_COMMAND;
+ out_be32((void *)addr,
+ (in_be32((void *)addr) | (PCI_STATUS_REC_MASTER_ABORT << 16)));
+
+ /* address for PCI configuration access */
+ addr = (unsigned long)hose->cfg_data +
+ (((bus & 0xff) << 16)
+ | ((devfn & 0xff) << 8)
+ | (where & 0xff)
+ | 0x01000000);
+
+
+ switch(size){
+ case 1:
+ addr &= ~0x3;
+ *val = in_le32((void *)(addr)) >> (8 * (where & 0x3));
+ break;
+ case 2:
+ addr &= ~0x2;
+ *val = in_le32((void *)(addr)) >> (8 * (where & 0x2));
+ break;
+ case 4:
+ *val = in_le32((void *)addr);
+ break;
+ default:
+ //*val = 0;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ }
+
+ return celleb_epci_check_abort(hose, 0);
+}
+
+int
+celleb_epci_subordinate_write_config(struct pci_controller *hose,
+ int bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+
+ unsigned long addr;
+ u32 xval;
+
+ if( !hose->cfg_data )
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /* Clear and Disable Master Abort interrupt */
+ addr = (unsigned long)hose->cfg_addr + PCI_COMMAND;
+ out_be32((void *)addr,
+ (in_be32((void *)addr) | (PCI_STATUS_REC_MASTER_ABORT << 16)));
+
+ /* address for PCI configuration access */
+ addr = (unsigned long)hose->cfg_data +
+ (((bus & 0xff) << 16)
+ | ((devfn & 0xff) << 8)
+ | (where & 0xff)
+ | 0x01000000);
+
+
+ switch(size){
+ case 1:
+ addr &= ~0x3;
+ xval = in_le32((void *)addr);
+ xval = (xval & ~(0xff << (8 * (where & 0x3)))) |
+ ((val & 0xff) << (8 * (where & 0x3)));
+ break;
+ case 2:
+ addr &= ~0x2;
+ xval = in_le32((void *)addr);
+ xval = (xval & ~(0xffff << (8 * (where & 0x2 )))) |
+ ((val & 0xffff) << (8 * (where & 0x2)));
+ break;
+ case 4:
+ xval = val;
+ break;
+ default:
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ }
+
+ out_le32((void *)addr, xval);
+
+ return celleb_epci_check_abort(hose, addr);
+}
+
+int
+celleb_epci_read_config(struct pci_bus *bus,
+ unsigned int devfn,
+ int where, int size, u32 *val)
+{
+
+ unsigned long addr;
+ struct device_node *node;
+ struct pci_controller *hose;
+
+
+ node = (struct device_node *)bus->sysdata;
+ hose = pci_find_hose_for_OF_device(node);
+
+ if( bus->self )
+ return celleb_epci_subordinate_read_config(hose, bus->number, devfn,
+ where, size, val);
+
+
+ if( !hose->cfg_data )
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if(bus->number == hose->first_busno && devfn == 0){
+ /* SYSCON */
+
+ if(where == PCI_INTERRUPT_LINE){
+ *val = irq_create_mapping(NULL, epci_int_irq);
+ return PCIBIOS_SUCCESSFUL;
+ }else if(where == PCI_INTERRUPT_PIN){
+ *val = 1;
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ addr = (unsigned long)hose->cfg_addr + where;
+
+ switch(size){
+ case 1:
+ *val = in_8((u8 *)addr);
+ break;
+ case 2:
+ *val = in_be16((u16 *)addr);
+ break;
+ case 4:
+ *val = in_be32((u32 *)addr);
+ break;
+ default:
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ }else{
+
+ if(where == PCI_INTERRUPT_LINE){
+ *val = irq_create_mapping(NULL, epci_ext_irq);
+ return PCIBIOS_SUCCESSFUL;
+ }else if(where == PCI_INTERRUPT_PIN){
+ *val = 1;
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ /* Clear and Disable Master Abort interrupt */
+ addr = (unsigned long)hose->cfg_addr + PCI_COMMAND;
+ out_be32((void *)addr,
+ (in_be32((void *)addr) | (PCI_STATUS_REC_MASTER_ABORT << 16)));
+
+ /* address for PCI configuration access */
+ addr = (unsigned long)hose->cfg_data + (((devfn & 0xff) << 8) | (where & 0xff));
+
+ switch(size){
+ case 1:
+ addr &= ~0x3;
+ *val = in_le32((void *)addr) >> (8 * (where & 0x3));
+ break;
+ case 2:
+ addr &= ~0x2;
+ *val = in_le32((void *)addr) >> (8 * (where & 0x2));
+ break;
+ case 4:
+ *val = in_le32((void *)addr);
+ break;
+ default:
+ //*val = 0;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ }
+
+#ifdef DEBUG
+ printk(" epci read: addr=0x%lx, devfn=0x%x, where=0x%x, size=0x%x, val=0x%x\n",
+ addr, devfn, where, size, *val);
+#endif
+
+ return celleb_epci_check_abort(hose, 0);
+}
+
+
+int
+celleb_epci_write_config(struct pci_bus *bus,
+ unsigned int devfn,
+ int where, int size, u32 val)
+{
+
+ unsigned long addr;
+ struct device_node *node;
+ struct pci_controller *hose;
+ u32 xval;
+
+ node = (struct device_node *)bus->sysdata;
+ hose = pci_find_hose_for_OF_device(node);
+
+ if( bus->self )
+ return celleb_epci_subordinate_write_config(hose, bus->number, devfn,
+ where, size, val);
+
+
+ if( !hose->cfg_data )
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if(bus->number == hose->first_busno && devfn == 0){
+ /* SYSCON */
+
+ addr = (unsigned long)hose->cfg_addr + where;
+
+ switch(size){
+ case 1:
+ out_8((u8 *)addr, val);
+ break;
+ case 2:
+ out_be16((u16 *)addr, val);
+ break;
+ case 4:
+ out_be32((u32 *)addr, val);
+ break;
+ default:
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ }else{
+ /* Clear and Disable Master Abort interrupt */
+ addr = (unsigned long)hose->cfg_addr + PCI_COMMAND;
+ out_be32((void *)addr,
+ (in_be32((void *)addr) | (PCI_STATUS_REC_MASTER_ABORT << 16)));
+
+ /* address for PCI configuration access */
+ addr = (unsigned long)hose->cfg_data + (((devfn & 0xff) << 8) | (where & 0xff));
+
+
+ switch(size){
+ case 1:
+ addr &= ~0x3;
+ xval = in_le32((void *)addr);
+ xval = (xval & ~(0xff << (8 * (where & 0x3)))) |
+ ((val & 0xff) << (8 * (where & 0x3)));
+ break;
+ case 2:
+ addr &= ~0x2;
+ xval = in_le32((void *)addr);
+ xval = (xval & ~(0xffff << (8 * (where & 0x2 )))) |
+ ((val & 0xffff) << (8 * (where & 0x2)));
+ break;
+ case 4:
+ xval = val;
+ break;
+ default:
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ }
+ out_le32((void *)addr, xval);
+
+ }
+
+ return celleb_epci_check_abort(hose, addr);
+}
+
+struct pci_ops celleb_epci_ops = {
+ celleb_epci_read_config,
+ celleb_epci_write_config,
+};
+
+static int __init celleb_epci_init(struct pci_controller *hose){
+
+ u32 val;
+ unsigned long reg;
+ unsigned long epci_base;
+ int hwres = 0;
+
+ epci_base = (unsigned long)hose->cfg_addr;
+
+ /* PCI core reset(Internal bus and PCI clock) */
+ reg = epci_base + SCC_EPCI_CKCTRL;
+ val = in_be32((void *)reg);
+ if (val == 0x00030101) {
+ hwres = 1;
+ } else {
+ val &= ~(SCC_EPCI_CKCTRL_CRST0 | SCC_EPCI_CKCTRL_CRST1);
+ out_be32((void *)reg, val);
+
+ /* set PCI core clock */
+ val = in_be32((void *)reg);
+ val |= (SCC_EPCI_CKCTRL_OCLKEN | SCC_EPCI_CKCTRL_LCLKEN);
+ out_be32((void *)reg, val);
+
+ /* release PCI core reset (internal bus) */
+ val = in_be32((void *)reg);
+ val |= SCC_EPCI_CKCTRL_CRST0;
+ out_be32((void *)reg, val);
+
+ /* set PCI clock select */
+ reg = epci_base + SCC_EPCI_CLKRST;
+ val = in_be32((void *)reg);
+ val &= ~SCC_EPCI_CLKRST_CKS_MASK;
+ val |= SCC_EPCI_CLKRST_CKS_2;
+ out_be32((void *)reg, val);
+
+ /* set arbiter */
+ reg = epci_base + SCC_EPCI_ABTSET;
+ out_be32((void *)reg, 0x0f1f001f); /* temporary value */
+
+ /* buffer on */
+ reg = epci_base + SCC_EPCI_CLKRST;
+ val = in_be32((void *)reg);
+ val |= SCC_EPCI_CLKRST_BC;
+ out_be32((void *)reg, val);
+
+ /* PCI clock enable */
+ val = in_be32((void *)reg);
+ val |= SCC_EPCI_CLKRST_PCKEN;
+ out_be32((void *)reg, val);
+
+ /* release PCI core reset (all) */
+ reg = epci_base + SCC_EPCI_CKCTRL;
+ val = in_be32((void *)reg);
+ val |= (SCC_EPCI_CKCTRL_CRST0 | SCC_EPCI_CKCTRL_CRST1);
+ out_be32((void *)reg, val);
+
+ /* set base translation registers. (already set by Beat) */
+
+ /* set base address masks. (already set by Beat) */
+ }
+
+ /* release interrupt masks and clear all interrupts*/
+ reg = epci_base + SCC_EPCI_INTSET;
+ out_be32((void *)reg, 0x013f011f); /* all interrupts enable */
+ reg = epci_base + SCC_EPCI_VIENAB;
+ val = SCC_EPCI_VIENAB_PMPEE | SCC_EPCI_VIENAB_PMFEE;
+ out_be32((void *)reg, val);
+ reg = epci_base + SCC_EPCI_STATUS;
+ out_be32((void *)reg, 0xffffffff);
+ reg = epci_base + SCC_EPCI_VISTAT;
+ out_be32((void *)reg, 0xffffffff);
+
+ /* disable PCI->IB address translation */
+ reg = epci_base + SCC_EPCI_VCSR;
+ val = in_be32((void *)reg);
+ val &= ~(SCC_EPCI_VCSR_DR | SCC_EPCI_VCSR_AT | SCC_EPCI_VCSR_SR);
+ out_be32((void *)reg, val);
+
+ /* set base addresses. (no need to set?) */
+
+ /* memory space, bus master enable */
+ reg = epci_base + PCI_COMMAND;
+ val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+ out_be32((void *)reg, val);
+
+ /* endian mode setup */
+ reg = epci_base + SCC_EPCI_ECMODE;
+ //val = 0x00ff03ff;
+ val = 0x00550155;
+ //val = 0x00550000;
+ out_be32((void *)reg, val);
+
+ /* set control option */
+ reg = epci_base + SCC_EPCI_CNTOPT;
+ val = in_be32((void *)reg);
+ val |= SCC_EPCI_CNTOPT_O2PMB;
+ out_be32((void *)reg, val);
+
+ /* XXX: temporay: set registers for address conversion setup */
+ reg = epci_base + SCC_EPCI_CNF10_REG;
+ out_be32((void *)reg, 0x80000008);
+ reg = epci_base + SCC_EPCI_CNF14_REG;
+ out_be32((void *)reg, 0x40000008);
+
+ reg = epci_base + SCC_EPCI_BAM0;
+ out_be32((void *)reg, 0x80000000);
+ reg = epci_base + SCC_EPCI_BAM1;
+ out_be32((void *)reg, 0xe0000000);
+
+ reg = epci_base + SCC_EPCI_PVBAT;
+ out_be32((void *)reg, 0x80000000);
+
+ if (!hwres) {
+ /* release external PCI reset */
+ reg = epci_base + SCC_EPCI_CLKRST;
+ val = in_be32((void *)reg);
+ val |= SCC_EPCI_CLKRST_PCIRST;
+ out_be32((void *)reg, val);
+ }
+
+ return 0;
+
+
+}
+
+int __init
+celleb_setup_epci(struct device_node *node, struct pci_controller *hose)
+{
+
+ unsigned long *li, *li2;
+ unsigned int rlen;
+
+#ifdef DEBUG
+ printk("PCI: celleb_setup_epci()\n");
+#endif
+
+ li = (unsigned long *)get_property(node, "toshiba,reg", &rlen);
+
+ if(!li || ((rlen >> 4) != 4)){
+ printk(KERN_ERR "PCI: No toshiba,reg property\n");
+ goto error;
+ }
+
+ hose->cfg_addr = ioremap(li[0], li[1]);
+ if( !hose->cfg_addr ){
+ goto error;
+ }
+ hose->cfg_data = ioremap(li[4], li[5]);
+ if( !hose->cfg_data ){
+ goto error;
+ }
+
+ li2 = (unsigned long *)get_property(node, "interrupts", &rlen);
+ if( !li2 ){
+ printk(KERN_ERR "PCI: No interrupts property");
+ goto error;
+ }
+ epci_ext_irq = li2[0];
+ epci_int_irq = li2[1];
+
+
+#ifdef DEBUG
+ printk("PCI: epci_ext_irq %x epci_int_irq %x\n", epci_ext_irq, epci_int_irq);
+ printk("PCI: cfg_addr 0x%016lx->0x%016lx + 0x%016lx\n",
+ li[0], (unsigned long)hose->cfg_addr, li[1]);
+ printk("PCI: cfg_data map 0x%016lx->0x%016lx + 0x%016lx\n",
+ li[4], (unsigned long)hose->cfg_data, li[5]);
+#endif
+
+ celleb_epci_init(hose);
+
+
+ return 0;
+
+error:
+
+ if( hose->cfg_addr ){
+ iounmap((void *)hose->cfg_addr);
+ }
+
+ if( hose->cfg_data ){
+ iounmap((void *)hose->cfg_data);
+ }
+ return 1;
+
+}
+
+/* End: celleb_epci.c */
+
+
+
Index: linux-2.6.19/arch/powerpc/platforms/celleb/celleb_scc.h
diff -u /dev/null linux-2.6.19/arch/powerpc/platforms/celleb/celleb_scc.h:1.1
--- /dev/null Thu Nov 9 18:40:50 2006
+++ linux-2.6.19/arch/powerpc/platforms/celleb/celleb_scc.h Fri Oct 6 16:13:37 2006
@@ -0,0 +1,164 @@
+/*
+ * SCC (Super Companion Chip) definitions
+ *
+ * (C) Copyright 2004-2006 TOSHIBA CORPORATION
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CELLEB_SCC_H__
+#define _CELLEB_SCC_H__
+
+
+#define PCI_VENDOR_ID_TOSHIBA_2 0x102f
+#define PCI_DEVICE_ID_TOSHIBA_SCC_PCIEXC_BRIDGE 0x01b0
+#define PCI_DEVICE_ID_TOSHIBA_SCC_EPCI_BRIDGE 0x01b1
+#define PCI_DEVICE_ID_TOSHIBA_SCC_BRIDGE 0x01b2
+#define PCI_DEVICE_ID_TOSHIBA_SCC_GBE 0x01b3
+#define PCI_DEVICE_ID_TOSHIBA_SCC_ATA 0x01b4
+#define PCI_DEVICE_ID_TOSHIBA_SCC_USB2 0x01b5
+#define PCI_DEVICE_ID_TOSHIBA_SCC_USB 0x01b6
+#define PCI_DEVICE_ID_TOSHIBA_SCC_ENCDEC 0x01b7
+
+#define SCC_EPCI_REG 0x0000d000
+
+/* EPCI registers */
+#define SCC_EPCI_CNF10_REG 0x010
+#define SCC_EPCI_CNF14_REG 0x014
+#define SCC_EPCI_CNF18_REG 0x018
+#define SCC_EPCI_PVBAT 0x100
+#define SCC_EPCI_VPMBAT 0x104
+#define SCC_EPCI_VPIBAT 0x108
+#define SCC_EPCI_VCSR 0x110
+#define SCC_EPCI_VIENAB 0x114
+#define SCC_EPCI_VISTAT 0x118
+#define SCC_EPCI_VRDCOUNT 0x124
+#define SCC_EPCI_BAM0 0x12c
+#define SCC_EPCI_BAM1 0x134
+#define SCC_EPCI_BAM2 0x13c
+#define SCC_EPCI_IADR 0x164
+#define SCC_EPCI_CLKRST 0x800
+#define SCC_EPCI_INTSET 0x804
+#define SCC_EPCI_STATUS 0x808
+#define SCC_EPCI_ABTSET 0x80c
+#define SCC_EPCI_WATRP 0x810
+#define SCC_EPCI_DUMMYRADR 0x814
+#define SCC_EPCI_SWRESP 0x818
+#define SCC_EPCI_CNTOPT 0x81c
+#define SCC_EPCI_ECMODE 0xf00
+#define SCC_EPCI_IOM_AC_NUM 5
+#define SCC_EPCI_IOM_ACTE(n) (0xf10 + (n) * 4)
+#define SCC_EPCI_IOT_AC_NUM 4
+#define SCC_EPCI_IOT_ACTE(n) (0xf30 + (n) * 4)
+#define SCC_EPCI_MAEA 0xf50
+#define SCC_EPCI_MAEC 0xf54
+#define SCC_EPCI_CKCTRL 0xff0
+
+/* bits for SCC_EPCI_VCSR */
+#define SCC_EPCI_VCSR_FRE 0x00020000
+#define SCC_EPCI_VCSR_FWE 0x00010000
+#define SCC_EPCI_VCSR_DR 0x00000400
+#define SCC_EPCI_VCSR_SR 0x00000008
+#define SCC_EPCI_VCSR_AT 0x00000004
+
+/* bits for SCC_EPCI_VIENAB/SCC_EPCI_VISTAT */
+#define SCC_EPCI_VISTAT_PMPE 0x00000008
+#define SCC_EPCI_VISTAT_PMFE 0x00000004
+#define SCC_EPCI_VISTAT_PRA 0x00000002
+#define SCC_EPCI_VISTAT_PRD 0x00000001
+#define SCC_EPCI_VISTAT_ALL 0x0000000f
+
+#define SCC_EPCI_VIENAB_PMPEE 0x00000008
+#define SCC_EPCI_VIENAB_PMFEE 0x00000004
+#define SCC_EPCI_VIENAB_PRA 0x00000002
+#define SCC_EPCI_VIENAB_PRD 0x00000001
+#define SCC_EPCI_VIENAB_ALL 0x0000000f
+
+/* bits for SCC_EPCI_CLKRST */
+#define SCC_EPCI_CLKRST_CKS_MASK 0x00030000
+#define SCC_EPCI_CLKRST_CKS_2 0x00000000
+#define SCC_EPCI_CLKRST_CKS_4 0x00010000
+#define SCC_EPCI_CLKRST_CKS_8 0x00020000
+#define SCC_EPCI_CLKRST_PCICRST 0x00000400
+#define SCC_EPCI_CLKRST_BC 0x00000200
+#define SCC_EPCI_CLKRST_PCIRST 0x00000100
+#define SCC_EPCI_CLKRST_PCKEN 0x00000001
+
+/* bits for SCC_EPCI_INTSET/SCC_EPCI_STATUS */
+#define SCC_EPCI_INT_2M 0x01000000
+#define SCC_EPCI_INT_RERR 0x00200000
+#define SCC_EPCI_INT_SERR 0x00100000
+#define SCC_EPCI_INT_PRTER 0x00080000
+#define SCC_EPCI_INT_SER 0x00040000
+#define SCC_EPCI_INT_PER 0x00020000
+#define SCC_EPCI_INT_PAI 0x00010000
+#define SCC_EPCI_INT_1M 0x00000100
+#define SCC_EPCI_INT_PME 0x00000010
+#define SCC_EPCI_INT_INTD 0x00000008
+#define SCC_EPCI_INT_INTC 0x00000004
+#define SCC_EPCI_INT_INTB 0x00000002
+#define SCC_EPCI_INT_INTA 0x00000001
+#define SCC_EPCI_INT_DEVINT 0x0000000f
+#define SCC_EPCI_INT_ALL 0x003f001f
+#define SCC_EPCI_INT_ALLERR 0x003f0000
+
+/* bits for SCC_EPCI_CKCTRL */
+#define SCC_EPCI_CKCTRL_CRST0 0x00010000
+#define SCC_EPCI_CKCTRL_CRST1 0x00020000
+#define SCC_EPCI_CKCTRL_OCLKEN 0x00000100
+#define SCC_EPCI_CKCTRL_LCLKEN 0x00000001
+
+#define SCC_EPCI_IDSEL_AD_TO_SLOT(ad) ((ad) - 10)
+#define SCC_EPCI_MAX_DEVNU SCC_EPCI_IDSEL_AD_TO_SLOT(32)
+
+/* bits for SCC_EPCI_CNTOPT */
+#define SCC_EPCI_CNTOPT_O2PMB 0x00000002
+
+/* PCICFG registers */
+#define SCC_PCICFG_CNFADD 0x00c
+#define SCC_PCICFG_CNFSET 0x010
+#define SCC_PCICFG_CNFWDT 0x014
+#define SCC_PCICFG_CNFRDT 0x018
+#define SCC_PCICFG_CCKCTRL 0xff0
+
+/* bits for SCC_PCICFG_CCKCTRL */
+#define SCC_PCICFG_CCKCTRL_RST 0x00010000
+#define SCC_PCICFG_CCKCTRL_CLKEN 0x00000001
+
+/* bits for SCC_CFG_BUSCLKCTL */
+#define SCC_CFG_BUSCLKCTL_BBUSCLKEN 0x00000010
+#define SCC_CFG_BUSCLKCTL_SBSBUSCLKEN 0x00000008
+#define SCC_CFG_BUSCLKCTL_SBHBUSCLKEN 0x00000004
+#define SCC_CFG_BUSCLKCTL_SBMBUSCLKEN 0x00000002
+#define SCC_CFG_BUSCLKCTL_SBTBUSCLKEN 0x00000001
+
+/* bits for SCC_CFG_BUSRSTCTL */
+#define SCC_CFG_BUSRSTCTL_BBUSRSTEN 0x00000010
+#define SCC_CFG_BUSRSTCTL_SBSBUSRSTEN 0x00000008
+#define SCC_CFG_BUSRSTCTL_SBHBUSRSTEN 0x00000004
+#define SCC_CFG_BUSRSTCTL_SBMBUSRSTEN 0x00000002
+#define SCC_CFG_BUSRSTCTL_SBTBUSRSTEN 0x00000001
+
+/* IPCI device numbers */
+#ifndef EEHREGIONBASE
+#define EEHREGIONBASE 0xa000000000000000ul
+#endif /* EEHREGIONBASE */
+#define REGION_DATA_MASK (~REGION_MASK)
+#define IO_TOKEN_TO_ADDR(token) ((((unsigned long)token)®ION_DATA_MASK)|IOREGIONBASE)
+#define IO_ADDR_TO_TOKEN(token) ((((unsigned long)token)®ION_DATA_MASK)|EEHREGIONBASE)
+#define IS_EEH_REGION(token) ((((unsigned long)token)®ION_MASK)==EEHREGIONBASE)
+
+
+#endif
More information about the Linuxppc-dev
mailing list