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