0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/stddef.h>
0014 #include <linux/kernel.h>
0015 #include <linux/pci.h>
0016 #include <linux/kdev_t.h>
0017 #include <linux/console.h>
0018 #include <linux/delay.h>
0019 #include <linux/irq.h>
0020 #include <linux/seq_file.h>
0021 #include <linux/root_dev.h>
0022 #include <linux/serial.h>
0023 #include <linux/tty.h>
0024 #include <linux/serial_core.h>
0025 #include <linux/of_address.h>
0026 #include <linux/of_irq.h>
0027 #include <linux/of_platform.h>
0028 #include <linux/extable.h>
0029
0030 #include <asm/time.h>
0031 #include <asm/machdep.h>
0032 #include <asm/udbg.h>
0033 #include <asm/tsi108.h>
0034 #include <asm/pci-bridge.h>
0035 #include <asm/reg.h>
0036 #include <mm/mmu_decl.h>
0037 #include <asm/tsi108_irq.h>
0038 #include <asm/tsi108_pci.h>
0039 #include <asm/mpic.h>
0040
0041 #undef DEBUG
0042
0043 #define HOLLY_PCI_CFG_PHYS 0x7c000000
0044
0045 static int holly_exclude_device(struct pci_controller *hose, u_char bus,
0046 u_char devfn)
0047 {
0048 if (bus == 0 && PCI_SLOT(devfn) == 0)
0049 return PCIBIOS_DEVICE_NOT_FOUND;
0050 else
0051 return PCIBIOS_SUCCESSFUL;
0052 }
0053
0054 static void __init holly_remap_bridge(void)
0055 {
0056 u32 lut_val, lut_addr;
0057 int i;
0058
0059 printk(KERN_INFO "Remapping PCI bridge\n");
0060
0061
0062
0063
0064 lut_addr = 0x900;
0065 for (i = 0; i < 31; i++) {
0066 tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x00000201);
0067 lut_addr += 4;
0068 tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x0);
0069 lut_addr += 4;
0070 }
0071
0072
0073 tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x00000241);
0074 lut_addr += 4;
0075 tsi108_write_reg(TSI108_PB_OFFSET + lut_addr, 0x0);
0076
0077
0078 tsi108_write_reg(TSI108_PCI_PFAB_IO_UPPER, 0x0);
0079 tsi108_write_reg(TSI108_PCI_PFAB_IO, 0x1);
0080
0081
0082 tsi108_write_reg(TSI108_PCI_PFAB_BAR0_UPPER, 0x0);
0083 tsi108_write_reg(TSI108_PCI_PFAB_BAR0, 0x7c000000 | 0x01);
0084
0085
0086 tsi108_write_reg(TSI108_PCI_PFAB_MEM32, 0x0);
0087 tsi108_write_reg(TSI108_PCI_PFAB_PFM3, 0x0);
0088 tsi108_write_reg(TSI108_PCI_PFAB_PFM4, 0x0);
0089
0090
0091 tsi108_write_reg(TSI108_PCI_P2O_BAR0_UPPER, 0x0);
0092 tsi108_write_reg(TSI108_PCI_P2O_BAR0, 0xc0000000);
0093
0094
0095 lut_addr = 0x500;
0096 lut_val = 0x00000002;
0097
0098 for (i = 0; i < 32; i++) {
0099 tsi108_write_reg(TSI108_PCI_OFFSET + lut_addr, lut_val);
0100 lut_addr += 4;
0101 tsi108_write_reg(TSI108_PCI_OFFSET + lut_addr, 0x40000000);
0102 lut_addr += 4;
0103 lut_val += 0x02000000;
0104 }
0105 tsi108_write_reg(TSI108_PCI_P2O_PAGE_SIZES, 0x00007900);
0106
0107
0108 tsi108_write_reg(TSI108_PCI_P2O_BAR2_UPPER, 0x0);
0109 tsi108_write_reg(TSI108_PCI_P2O_BAR2, 0x0);
0110 }
0111
0112 static void __init holly_init_pci(void)
0113 {
0114 struct device_node *np;
0115
0116 if (ppc_md.progress)
0117 ppc_md.progress("holly_setup_arch():set_bridge", 0);
0118
0119
0120 holly_remap_bridge();
0121
0122 np = of_find_node_by_type(NULL, "pci");
0123 if (np)
0124 tsi108_setup_pci(np, HOLLY_PCI_CFG_PHYS, 1);
0125
0126 ppc_md.pci_exclude_device = holly_exclude_device;
0127 if (ppc_md.progress)
0128 ppc_md.progress("tsi108: resources set", 0x100);
0129 }
0130
0131 static void __init holly_setup_arch(void)
0132 {
0133 tsi108_csr_vir_base = get_vir_csrbase();
0134
0135 printk(KERN_INFO "PPC750GX/CL Platform\n");
0136 }
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149 static void __init holly_init_IRQ(void)
0150 {
0151 struct mpic *mpic;
0152 #ifdef CONFIG_PCI
0153 unsigned int cascade_pci_irq;
0154 struct device_node *tsi_pci;
0155 struct device_node *cascade_node = NULL;
0156 #endif
0157
0158 mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
0159 MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108,
0160 24, 0,
0161 "Tsi108_PIC");
0162
0163 BUG_ON(mpic == NULL);
0164
0165 mpic_assign_isu(mpic, 0, mpic->paddr + 0x100);
0166
0167 mpic_init(mpic);
0168
0169 #ifdef CONFIG_PCI
0170 tsi_pci = of_find_node_by_type(NULL, "pci");
0171 if (tsi_pci == NULL) {
0172 printk(KERN_ERR "%s: No tsi108 pci node found !\n", __func__);
0173 return;
0174 }
0175
0176 cascade_node = of_find_node_by_type(NULL, "pic-router");
0177 if (cascade_node == NULL) {
0178 printk(KERN_ERR "%s: No tsi108 pci cascade node found !\n", __func__);
0179 return;
0180 }
0181
0182 cascade_pci_irq = irq_of_parse_and_map(tsi_pci, 0);
0183 pr_debug("%s: tsi108 cascade_pci_irq = 0x%x\n", __func__, (u32) cascade_pci_irq);
0184 tsi108_pci_int_init(cascade_node);
0185 irq_set_handler_data(cascade_pci_irq, mpic);
0186 irq_set_chained_handler(cascade_pci_irq, tsi108_irq_cascade);
0187 #endif
0188
0189 tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
0190 }
0191
0192 static void holly_show_cpuinfo(struct seq_file *m)
0193 {
0194 seq_printf(m, "vendor\t\t: IBM\n");
0195 seq_printf(m, "machine\t\t: PPC750 GX/CL\n");
0196 }
0197
0198 static void __noreturn holly_restart(char *cmd)
0199 {
0200 __be32 __iomem *ocn_bar1 = NULL;
0201 unsigned long bar;
0202 struct device_node *bridge = NULL;
0203 const void *prop;
0204 int size;
0205 phys_addr_t addr = 0xc0000000;
0206
0207 local_irq_disable();
0208
0209 bridge = of_find_node_by_type(NULL, "tsi-bridge");
0210 if (bridge) {
0211 prop = of_get_property(bridge, "reg", &size);
0212 addr = of_translate_address(bridge, prop);
0213 }
0214 addr += (TSI108_PB_OFFSET + 0x414);
0215
0216 ocn_bar1 = ioremap(addr, 0x4);
0217
0218
0219
0220 bar = ioread32be(ocn_bar1);
0221 bar |= 2;
0222 iowrite32be(bar, ocn_bar1);
0223 iosync();
0224
0225
0226 mtspr(SPRN_SRR0, 0xfff00100);
0227 mtspr(SPRN_SRR1, MSR_IP);
0228
0229
0230
0231
0232 __asm__ __volatile__("rfi" : : : "memory");
0233
0234
0235 for (;;) ;
0236 }
0237
0238
0239
0240
0241 static int __init holly_probe(void)
0242 {
0243 if (!of_machine_is_compatible("ibm,holly"))
0244 return 0;
0245 return 1;
0246 }
0247
0248 static int ppc750_machine_check_exception(struct pt_regs *regs)
0249 {
0250 const struct exception_table_entry *entry;
0251
0252
0253 if ((entry = search_exception_tables(regs->nip)) != NULL) {
0254 tsi108_clear_pci_cfg_error();
0255 regs_set_recoverable(regs);
0256 regs_set_return_ip(regs, extable_fixup(entry));
0257 return 1;
0258 }
0259 return 0;
0260 }
0261
0262 define_machine(holly){
0263 .name = "PPC750 GX/CL TSI",
0264 .probe = holly_probe,
0265 .setup_arch = holly_setup_arch,
0266 .discover_phbs = holly_init_pci,
0267 .init_IRQ = holly_init_IRQ,
0268 .show_cpuinfo = holly_show_cpuinfo,
0269 .get_irq = mpic_get_irq,
0270 .restart = holly_restart,
0271 .calibrate_decr = generic_calibrate_decr,
0272 .machine_check_exception = ppc750_machine_check_exception,
0273 .progress = udbg_progress,
0274 };