1 /* 2 * SH generic board support, using device tree 3 * 4 * Copyright (C) 2015-2016 Smart Energy Instruments, Inc. 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file "COPYING" in the main directory of this archive 8 * for more details. 9 */ 10 11 #include <linux/of.h> 12 #include <linux/of_fdt.h> 13 #include <linux/clocksource.h> 14 #include <linux/irqchip.h> 15 #include <linux/clk-provider.h> 16 #include <asm/machvec.h> 17 #include <asm/rtc.h> 18 19 #ifdef CONFIG_SMP 20 21 static void dummy_smp_setup(void) 22 { 23 } 24 25 static void dummy_prepare_cpus(unsigned int max_cpus) 26 { 27 } 28 29 static void dummy_start_cpu(unsigned int cpu, unsigned long entry_point) 30 { 31 } 32 33 static unsigned int dummy_smp_processor_id(void) 34 { 35 return 0; 36 } 37 38 static void dummy_send_ipi(unsigned int cpu, unsigned int message) 39 { 40 } 41 42 static struct plat_smp_ops dummy_smp_ops = { 43 .smp_setup = dummy_smp_setup, 44 .prepare_cpus = dummy_prepare_cpus, 45 .start_cpu = dummy_start_cpu, 46 .smp_processor_id = dummy_smp_processor_id, 47 .send_ipi = dummy_send_ipi, 48 .cpu_die = native_cpu_die, 49 .cpu_disable = native_cpu_disable, 50 .play_dead = native_play_dead, 51 }; 52 53 extern const struct of_cpu_method __cpu_method_of_table[]; 54 const struct of_cpu_method __cpu_method_of_table_sentinel 55 __section(__cpu_method_of_table_end); 56 57 static void sh_of_smp_probe(void) 58 { 59 struct device_node *np = 0; 60 const char *method = 0; 61 const struct of_cpu_method *m = __cpu_method_of_table; 62 63 pr_info("SH generic board support: scanning for cpus\n"); 64 65 init_cpu_possible(cpumask_of(0)); 66 67 while ((np = of_find_node_by_type(np, "cpu"))) { 68 const __be32 *cell = of_get_property(np, "reg", NULL); 69 u64 id = -1; 70 if (cell) id = of_read_number(cell, of_n_addr_cells(np)); 71 if (id < NR_CPUS) { 72 if (!method) 73 of_property_read_string(np, "enable-method", &method); 74 set_cpu_possible(id, true); 75 set_cpu_present(id, true); 76 __cpu_number_map[id] = id; 77 __cpu_logical_map[id] = id; 78 } 79 } 80 if (!method) { 81 np = of_find_node_by_name(NULL, "cpus"); 82 of_property_read_string(np, "enable-method", &method); 83 } 84 85 pr_info("CPU enable method: %s\n", method); 86 if (method) 87 for (; m->method; m++) 88 if (!strcmp(m->method, method)) { 89 register_smp_ops(m->ops); 90 return; 91 } 92 93 register_smp_ops(&dummy_smp_ops); 94 } 95 96 #else 97 98 static void sh_of_smp_probe(void) 99 { 100 } 101 102 #endif 103 104 static void noop(void) 105 { 106 } 107 108 static int noopi(void) 109 { 110 return 0; 111 } 112 113 static void __init sh_of_mem_reserve(void) 114 { 115 early_init_fdt_reserve_self(); 116 early_init_fdt_scan_reserved_mem(); 117 } 118 119 static void __init sh_of_time_init(void) 120 { 121 pr_info("SH generic board support: scanning for clocksource devices\n"); 122 timer_probe(); 123 } 124 125 static void __init sh_of_setup(char **cmdline_p) 126 { 127 struct device_node *root; 128 129 #ifdef CONFIG_USE_BUILTIN_DTB 130 unflatten_and_copy_device_tree(); 131 #else 132 unflatten_device_tree(); 133 #endif 134 135 board_time_init = sh_of_time_init; 136 137 sh_mv.mv_name = "Unknown SH model"; 138 root = of_find_node_by_path("/"); 139 if (root) { 140 of_property_read_string(root, "model", &sh_mv.mv_name); 141 of_node_put(root); 142 } 143 144 sh_of_smp_probe(); 145 } 146 147 static int sh_of_irq_demux(int irq) 148 { 149 /* FIXME: eventually this should not be used at all; 150 * the interrupt controller should set_handle_irq(). */ 151 return irq; 152 } 153 154 static void __init sh_of_init_irq(void) 155 { 156 pr_info("SH generic board support: scanning for interrupt controllers\n"); 157 irqchip_init(); 158 } 159 160 static int __init sh_of_clk_init(void) 161 { 162 #ifdef CONFIG_COMMON_CLK 163 /* Disabled pending move to COMMON_CLK framework. */ 164 pr_info("SH generic board support: scanning for clk providers\n"); 165 of_clk_init(NULL); 166 #endif 167 return 0; 168 } 169 170 static struct sh_machine_vector __initmv sh_of_generic_mv = { 171 .mv_setup = sh_of_setup, 172 .mv_name = "devicetree", /* replaced by DT root's model */ 173 .mv_irq_demux = sh_of_irq_demux, 174 .mv_init_irq = sh_of_init_irq, 175 .mv_clk_init = sh_of_clk_init, 176 .mv_mode_pins = noopi, 177 .mv_mem_init = noop, 178 .mv_mem_reserve = sh_of_mem_reserve, 179 }; 180 181 struct sh_clk_ops; 182 183 void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx) 184 { 185 } 186 187 void __init plat_irq_setup(void) 188 { 189 } 190