root/arch/mips/generic/init.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. prom_init
  2. plat_get_fdt
  3. plat_fdt_relocated
  4. plat_mem_setup
  5. device_tree_init
  6. apply_mips_fdt_fixups
  7. plat_time_init
  8. arch_init_irq
  9. prom_free_prom_memory

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright (C) 2016 Imagination Technologies
   4  * Author: Paul Burton <paul.burton@mips.com>
   5  */
   6 
   7 #include <linux/clk.h>
   8 #include <linux/clk-provider.h>
   9 #include <linux/clocksource.h>
  10 #include <linux/init.h>
  11 #include <linux/irqchip.h>
  12 #include <linux/of_fdt.h>
  13 
  14 #include <asm/bootinfo.h>
  15 #include <asm/fw/fw.h>
  16 #include <asm/irq_cpu.h>
  17 #include <asm/machine.h>
  18 #include <asm/mips-cps.h>
  19 #include <asm/prom.h>
  20 #include <asm/smp-ops.h>
  21 #include <asm/time.h>
  22 
  23 static __initdata const void *fdt;
  24 static __initdata const struct mips_machine *mach;
  25 static __initdata const void *mach_match_data;
  26 
  27 void __init prom_init(void)
  28 {
  29         plat_get_fdt();
  30         BUG_ON(!fdt);
  31 }
  32 
  33 void __init *plat_get_fdt(void)
  34 {
  35         const struct mips_machine *check_mach;
  36         const struct of_device_id *match;
  37 
  38         if (fdt)
  39                 /* Already set up */
  40                 return (void *)fdt;
  41 
  42         if ((fw_arg0 == -2) && !fdt_check_header((void *)fw_passed_dtb)) {
  43                 /*
  44                  * We booted using the UHI boot protocol, so we have been
  45                  * provided with the appropriate device tree for the board.
  46                  * Make use of it & search for any machine struct based upon
  47                  * the root compatible string.
  48                  */
  49                 fdt = (void *)fw_passed_dtb;
  50 
  51                 for_each_mips_machine(check_mach) {
  52                         match = mips_machine_is_compatible(check_mach, fdt);
  53                         if (match) {
  54                                 mach = check_mach;
  55                                 mach_match_data = match->data;
  56                                 break;
  57                         }
  58                 }
  59         } else if (IS_ENABLED(CONFIG_LEGACY_BOARDS)) {
  60                 /*
  61                  * We weren't booted using the UHI boot protocol, but do
  62                  * support some number of boards with legacy boot protocols.
  63                  * Attempt to find the right one.
  64                  */
  65                 for_each_mips_machine(check_mach) {
  66                         if (!check_mach->detect)
  67                                 continue;
  68 
  69                         if (!check_mach->detect())
  70                                 continue;
  71 
  72                         mach = check_mach;
  73                 }
  74 
  75                 /*
  76                  * If we don't recognise the machine then we can't continue, so
  77                  * die here.
  78                  */
  79                 BUG_ON(!mach);
  80 
  81                 /* Retrieve the machine's FDT */
  82                 fdt = mach->fdt;
  83         }
  84         return (void *)fdt;
  85 }
  86 
  87 #ifdef CONFIG_RELOCATABLE
  88 
  89 void __init plat_fdt_relocated(void *new_location)
  90 {
  91         /*
  92          * reset fdt as the cached value would point to the location
  93          * before relocations happened and update the location argument
  94          * if it was passed using UHI
  95          */
  96         fdt = NULL;
  97 
  98         if (fw_arg0 == -2)
  99                 fw_arg1 = (unsigned long)new_location;
 100 }
 101 
 102 #endif /* CONFIG_RELOCATABLE */
 103 
 104 void __init plat_mem_setup(void)
 105 {
 106         if (mach && mach->fixup_fdt)
 107                 fdt = mach->fixup_fdt(fdt, mach_match_data);
 108 
 109         strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
 110         __dt_setup_arch((void *)fdt);
 111 }
 112 
 113 void __init device_tree_init(void)
 114 {
 115         int err;
 116 
 117         unflatten_and_copy_device_tree();
 118         mips_cpc_probe();
 119 
 120         err = register_cps_smp_ops();
 121         if (err)
 122                 err = register_up_smp_ops();
 123 }
 124 
 125 int __init apply_mips_fdt_fixups(void *fdt_out, size_t fdt_out_size,
 126                                  const void *fdt_in,
 127                                  const struct mips_fdt_fixup *fixups)
 128 {
 129         int err;
 130 
 131         err = fdt_open_into(fdt_in, fdt_out, fdt_out_size);
 132         if (err) {
 133                 pr_err("Failed to open FDT\n");
 134                 return err;
 135         }
 136 
 137         for (; fixups->apply; fixups++) {
 138                 err = fixups->apply(fdt_out);
 139                 if (err) {
 140                         pr_err("Failed to apply FDT fixup \"%s\"\n",
 141                                fixups->description);
 142                         return err;
 143                 }
 144         }
 145 
 146         err = fdt_pack(fdt_out);
 147         if (err)
 148                 pr_err("Failed to pack FDT\n");
 149         return err;
 150 }
 151 
 152 void __init plat_time_init(void)
 153 {
 154         struct device_node *np;
 155         struct clk *clk;
 156 
 157         of_clk_init(NULL);
 158 
 159         if (!cpu_has_counter) {
 160                 mips_hpt_frequency = 0;
 161         } else if (mach && mach->measure_hpt_freq) {
 162                 mips_hpt_frequency = mach->measure_hpt_freq();
 163         } else {
 164                 np = of_get_cpu_node(0, NULL);
 165                 if (!np) {
 166                         pr_err("Failed to get CPU node\n");
 167                         return;
 168                 }
 169 
 170                 clk = of_clk_get(np, 0);
 171                 if (IS_ERR(clk)) {
 172                         pr_err("Failed to get CPU clock: %ld\n", PTR_ERR(clk));
 173                         return;
 174                 }
 175 
 176                 mips_hpt_frequency = clk_get_rate(clk);
 177                 clk_put(clk);
 178 
 179                 switch (boot_cpu_type()) {
 180                 case CPU_20KC:
 181                 case CPU_25KF:
 182                         /* The counter runs at the CPU clock rate */
 183                         break;
 184                 default:
 185                         /* The counter runs at half the CPU clock rate */
 186                         mips_hpt_frequency /= 2;
 187                         break;
 188                 }
 189         }
 190 
 191         timer_probe();
 192 }
 193 
 194 void __init arch_init_irq(void)
 195 {
 196         struct device_node *intc_node;
 197 
 198         intc_node = of_find_compatible_node(NULL, NULL,
 199                                             "mti,cpu-interrupt-controller");
 200         if (!cpu_has_veic && !intc_node)
 201                 mips_cpu_irq_init();
 202         of_node_put(intc_node);
 203 
 204         irqchip_init();
 205 }
 206 
 207 void __init prom_free_prom_memory(void)
 208 {
 209 }

/* [<][>][^][v][top][bottom][index][help] */