1/* 2 * Wind River SBC8560 setup and early boot code. 3 * 4 * Copyright 2007 Wind River Systems Inc. 5 * 6 * By Paul Gortmaker (see MAINTAINERS for contact information) 7 * 8 * Based largely on the MPC8560ADS support - Copyright 2005 Freescale Inc. 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License as published by the 12 * Free Software Foundation; either version 2 of the License, or (at your 13 * option) any later version. 14 */ 15 16#include <linux/stddef.h> 17#include <linux/kernel.h> 18#include <linux/pci.h> 19#include <linux/kdev_t.h> 20#include <linux/delay.h> 21#include <linux/seq_file.h> 22#include <linux/of_platform.h> 23 24#include <asm/system.h> 25#include <asm/time.h> 26#include <asm/machdep.h> 27#include <asm/pci-bridge.h> 28#include <asm/mpic.h> 29#include <mm/mmu_decl.h> 30#include <asm/udbg.h> 31 32#include <sysdev/fsl_soc.h> 33#include <sysdev/fsl_pci.h> 34 35#ifdef CONFIG_CPM2 36#include <asm/cpm2.h> 37#include <sysdev/cpm2_pic.h> 38#endif 39 40#ifdef CONFIG_CPM2 41 42static void cpm2_cascade(unsigned int irq, struct irq_desc *desc) 43{ 44 int cascade_irq; 45 46 while ((cascade_irq = cpm2_get_irq()) >= 0) 47 generic_handle_irq(cascade_irq); 48 49 desc->chip->eoi(irq); 50} 51 52#endif /* CONFIG_CPM2 */ 53 54static void __init sbc8560_pic_init(void) 55{ 56 struct mpic *mpic; 57 struct resource r; 58 struct device_node *np = NULL; 59#ifdef CONFIG_CPM2 60 int irq; 61#endif 62 63 np = of_find_node_by_type(np, "open-pic"); 64 if (!np) { 65 printk(KERN_ERR "Could not find open-pic node\n"); 66 return; 67 } 68 69 if (of_address_to_resource(np, 0, &r)) { 70 printk(KERN_ERR "Could not map mpic register space\n"); 71 of_node_put(np); 72 return; 73 } 74 75 mpic = mpic_alloc(np, r.start, 76 MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, 77 0, 256, " OpenPIC "); 78 BUG_ON(mpic == NULL); 79 of_node_put(np); 80 81 mpic_init(mpic); 82 83#ifdef CONFIG_CPM2 84 /* Setup CPM2 PIC */ 85 np = of_find_compatible_node(NULL, NULL, "fsl,cpm2-pic"); 86 if (np == NULL) { 87 printk(KERN_ERR "PIC init: can not find fsl,cpm2-pic node\n"); 88 return; 89 } 90 irq = irq_of_parse_and_map(np, 0); 91 92 cpm2_pic_init(np); 93 of_node_put(np); 94 set_irq_chained_handler(irq, cpm2_cascade); 95#endif 96} 97 98/* 99 * Setup the architecture 100 */ 101#ifdef CONFIG_CPM2 102struct cpm_pin { 103 int port, pin, flags; 104}; 105 106static const struct cpm_pin sbc8560_pins[] = { 107 /* SCC1 */ 108 {3, 29, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, 109 {3, 30, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, 110 {3, 31, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, 111 112 /* SCC2 */ 113 {3, 26, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, 114 {3, 27, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, 115 {3, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, 116 117 /* FCC2 */ 118 {1, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, 119 {1, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, 120 {1, 20, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, 121 {1, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, 122 {1, 22, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, 123 {1, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, 124 {1, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, 125 {1, 25, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, 126 {1, 26, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, 127 {1, 27, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, 128 {1, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, 129 {1, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, 130 {1, 30, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, 131 {1, 31, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, 132 {2, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK14 */ 133 {2, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK13 */ 134 135 /* FCC3 */ 136 {1, 4, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, 137 {1, 5, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, 138 {1, 6, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, 139 {1, 7, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, 140 {1, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, 141 {1, 9, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, 142 {1, 10, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, 143 {1, 11, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, 144 {1, 12, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, 145 {1, 13, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, 146 {1, 14, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, 147 {1, 15, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, 148 {1, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, 149 {1, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, 150 {2, 16, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* CLK16 */ 151 {2, 17, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* CLK15 */ 152}; 153 154static void __init init_ioports(void) 155{ 156 int i; 157 158 for (i = 0; i < ARRAY_SIZE(sbc8560_pins); i++) { 159 const struct cpm_pin *pin = &sbc8560_pins[i]; 160 cpm2_set_pin(pin->port, pin->pin, pin->flags); 161 } 162 163 cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_RX); 164 cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_TX); 165 cpm2_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_RX); 166 cpm2_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_TX); 167 cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK13, CPM_CLK_RX); 168 cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK14, CPM_CLK_TX); 169 cpm2_clk_setup(CPM_CLK_FCC3, CPM_CLK15, CPM_CLK_RX); 170 cpm2_clk_setup(CPM_CLK_FCC3, CPM_CLK16, CPM_CLK_TX); 171} 172#endif 173 174static void __init sbc8560_setup_arch(void) 175{ 176#ifdef CONFIG_PCI 177 struct device_node *np; 178#endif 179 180 if (ppc_md.progress) 181 ppc_md.progress("sbc8560_setup_arch()", 0); 182 183#ifdef CONFIG_CPM2 184 cpm2_reset(); 185 init_ioports(); 186#endif 187 188#ifdef CONFIG_PCI 189 for_each_compatible_node(np, "pci", "fsl,mpc8540-pci") 190 fsl_add_bridge(np, 1); 191#endif 192} 193 194static void sbc8560_show_cpuinfo(struct seq_file *m) 195{ 196 uint pvid, svid, phid1; 197 198 pvid = mfspr(SPRN_PVR); 199 svid = mfspr(SPRN_SVR); 200 201 seq_printf(m, "Vendor\t\t: Wind River\n"); 202 seq_printf(m, "PVR\t\t: 0x%x\n", pvid); 203 seq_printf(m, "SVR\t\t: 0x%x\n", svid); 204 205 /* Display cpu Pll setting */ 206 phid1 = mfspr(SPRN_HID1); 207 seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); 208} 209 210static struct of_device_id __initdata of_bus_ids[] = { 211 { .name = "soc", }, 212 { .type = "soc", }, 213 { .name = "cpm", }, 214 { .name = "localbus", }, 215 { .compatible = "simple-bus", }, 216 { .compatible = "gianfar", }, 217 {}, 218}; 219 220static int __init declare_of_platform_devices(void) 221{ 222 of_platform_bus_probe(NULL, of_bus_ids, NULL); 223 224 return 0; 225} 226machine_device_initcall(sbc8560, declare_of_platform_devices); 227 228/* 229 * Called very early, device-tree isn't unflattened 230 */ 231static int __init sbc8560_probe(void) 232{ 233 unsigned long root = of_get_flat_dt_root(); 234 235 return of_flat_dt_is_compatible(root, "SBC8560"); 236} 237 238#ifdef CONFIG_RTC_DRV_M48T59 239static int __init sbc8560_rtc_init(void) 240{ 241 struct device_node *np; 242 struct resource res; 243 struct platform_device *rtc_dev; 244 245 np = of_find_compatible_node(NULL, NULL, "m48t59"); 246 if (np == NULL) { 247 printk("No RTC in DTB. Has it been eaten by wild dogs?\n"); 248 return -ENODEV; 249 } 250 251 of_address_to_resource(np, 0, &res); 252 of_node_put(np); 253 254 printk("Found RTC (m48t59) at i/o 0x%x\n", res.start); 255 256 rtc_dev = platform_device_register_simple("rtc-m48t59", 0, &res, 1); 257 258 if (IS_ERR(rtc_dev)) { 259 printk("Registering sbc8560 RTC device failed\n"); 260 return PTR_ERR(rtc_dev); 261 } 262 263 return 0; 264} 265 266arch_initcall(sbc8560_rtc_init); 267 268#endif /* M48T59 */ 269 270static __u8 __iomem *brstcr; 271 272static int __init sbc8560_bdrstcr_init(void) 273{ 274 struct device_node *np; 275 struct resource res; 276 277 np = of_find_compatible_node(NULL, NULL, "wrs,sbc8560-brstcr"); 278 if (np == NULL) { 279 printk(KERN_WARNING "sbc8560: No board specific RSTCR in DTB.\n"); 280 return -ENODEV; 281 } 282 283 of_address_to_resource(np, 0, &res); 284 285 printk(KERN_INFO "sbc8560: Found BRSTCR at i/o 0x%x\n", res.start); 286 287 brstcr = ioremap(res.start, res.end - res.start); 288 if(!brstcr) 289 printk(KERN_WARNING "sbc8560: ioremap of brstcr failed.\n"); 290 291 of_node_put(np); 292 293 return 0; 294} 295 296arch_initcall(sbc8560_bdrstcr_init); 297 298void sbc8560_rstcr_restart(char * cmd) 299{ 300 local_irq_disable(); 301 if(brstcr) 302 clrbits8(brstcr, 0x80); 303 304 while(1); 305} 306 307define_machine(sbc8560) { 308 .name = "SBC8560", 309 .probe = sbc8560_probe, 310 .setup_arch = sbc8560_setup_arch, 311 .init_IRQ = sbc8560_pic_init, 312 .show_cpuinfo = sbc8560_show_cpuinfo, 313 .get_irq = mpic_get_irq, 314 .restart = sbc8560_rstcr_restart, 315 .calibrate_decr = generic_calibrate_decr, 316 .progress = udbg_progress, 317}; 318