1/* 2 * Copyright 2008 DENX Software Engineering GmbH 3 * Author: Heiko Schocher <hs@denx.de> 4 * 5 * Description: 6 * Keymile KMETER1 board specific routines. 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 */ 13 14#include <linux/stddef.h> 15#include <linux/kernel.h> 16#include <linux/init.h> 17#include <linux/errno.h> 18#include <linux/reboot.h> 19#include <linux/pci.h> 20#include <linux/kdev_t.h> 21#include <linux/major.h> 22#include <linux/console.h> 23#include <linux/delay.h> 24#include <linux/seq_file.h> 25#include <linux/root_dev.h> 26#include <linux/initrd.h> 27#include <linux/of_platform.h> 28#include <linux/of_device.h> 29 30#include <asm/system.h> 31#include <asm/atomic.h> 32#include <asm/time.h> 33#include <asm/io.h> 34#include <asm/machdep.h> 35#include <asm/ipic.h> 36#include <asm/irq.h> 37#include <asm/prom.h> 38#include <asm/udbg.h> 39#include <sysdev/fsl_soc.h> 40#include <sysdev/fsl_pci.h> 41#include <asm/qe.h> 42#include <asm/qe_ic.h> 43 44#include "mpc83xx.h" 45 46#define SVR_REV(svr) (((svr) >> 0) & 0xFFFF) /* Revision field */ 47/* ************************************************************************ 48 * 49 * Setup the architecture 50 * 51 */ 52static void __init kmeter1_setup_arch(void) 53{ 54 struct device_node *np; 55 56 if (ppc_md.progress) 57 ppc_md.progress("kmeter1_setup_arch()", 0); 58 59#ifdef CONFIG_PCI 60 for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") 61 mpc83xx_add_bridge(np); 62#endif 63 64#ifdef CONFIG_QUICC_ENGINE 65 qe_reset(); 66 67 np = of_find_node_by_name(NULL, "par_io"); 68 if (np != NULL) { 69 par_io_init(np); 70 of_node_put(np); 71 72 for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;) 73 par_io_of_config(np); 74 } 75 76 np = of_find_compatible_node(NULL, "network", "ucc_geth"); 77 if (np != NULL) { 78 uint svid; 79 80 /* handle mpc8360ea rev.2.1 erratum 2: RGMII Timing */ 81 svid = mfspr(SPRN_SVR); 82 if (SVR_REV(svid) == 0x0021) { 83 struct device_node *np_par; 84 struct resource res; 85 void __iomem *base; 86 int ret; 87 88 np_par = of_find_node_by_name(NULL, "par_io"); 89 if (np_par == NULL) { 90 printk(KERN_WARNING "%s couldn;t find par_io node\n", 91 __func__); 92 return; 93 } 94 /* Map Parallel I/O ports registers */ 95 ret = of_address_to_resource(np_par, 0, &res); 96 if (ret) { 97 printk(KERN_WARNING "%s couldn;t map par_io registers\n", 98 __func__); 99 return; 100 } 101 base = ioremap(res.start, res.end - res.start + 1); 102 103 /* 104 * IMMR + 0x14A8[4:5] = 11 (clk delay for UCC 2) 105 * IMMR + 0x14A8[18:19] = 11 (clk delay for UCC 1) 106 */ 107 setbits32((base + 0xa8), 0x0c003000); 108 109 /* 110 * IMMR + 0x14AC[20:27] = 10101010 111 * (data delay for both UCC's) 112 */ 113 clrsetbits_be32((base + 0xac), 0xff0, 0xaa0); 114 iounmap(base); 115 of_node_put(np_par); 116 } 117 of_node_put(np); 118 } 119#endif /* CONFIG_QUICC_ENGINE */ 120} 121 122static struct of_device_id kmeter_ids[] = { 123 { .type = "soc", }, 124 { .compatible = "soc", }, 125 { .compatible = "simple-bus", }, 126 { .type = "qe", }, 127 { .compatible = "fsl,qe", }, 128 {}, 129}; 130 131static int __init kmeter_declare_of_platform_devices(void) 132{ 133 /* Publish the QE devices */ 134 of_platform_bus_probe(NULL, kmeter_ids, NULL); 135 136 return 0; 137} 138machine_device_initcall(kmeter1, kmeter_declare_of_platform_devices); 139 140static void __init kmeter1_init_IRQ(void) 141{ 142 struct device_node *np; 143 144 np = of_find_compatible_node(NULL, NULL, "fsl,pq2pro-pic"); 145 if (!np) { 146 np = of_find_node_by_type(NULL, "ipic"); 147 if (!np) 148 return; 149 } 150 151 ipic_init(np, 0); 152 153 /* Initialize the default interrupt mapping priorities, 154 * in case the boot rom changed something on us. 155 */ 156 ipic_set_default_priority(); 157 of_node_put(np); 158 159#ifdef CONFIG_QUICC_ENGINE 160 np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic"); 161 if (!np) { 162 np = of_find_node_by_type(NULL, "qeic"); 163 if (!np) 164 return; 165 } 166 qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic); 167 of_node_put(np); 168#endif /* CONFIG_QUICC_ENGINE */ 169} 170 171/* 172 * Called very early, MMU is off, device-tree isn't unflattened 173 */ 174static int __init kmeter1_probe(void) 175{ 176 unsigned long root = of_get_flat_dt_root(); 177 178 return of_flat_dt_is_compatible(root, "keymile,KMETER1"); 179} 180 181define_machine(kmeter1) { 182 .name = "KMETER1", 183 .probe = kmeter1_probe, 184 .setup_arch = kmeter1_setup_arch, 185 .init_IRQ = kmeter1_init_IRQ, 186 .get_irq = ipic_get_irq, 187 .restart = mpc83xx_restart, 188 .time_init = mpc83xx_time_init, 189 .calibrate_decr = generic_calibrate_decr, 190 .progress = udbg_progress, 191}; 192