1 /* 2 * Copyright (C) 2012-2015 Panasonic Corporation 3 * Copyright (C) 2015-2016 Socionext Inc. 4 * Author: Masahiro Yamada <yamada.masahiro@socionext.com> 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <common.h> 10 #include <libfdt.h> 11 #include <linux/io.h> 12 13 #include "init.h" 14 #include "micro-support-card.h" 15 #include "sg-regs.h" 16 #include "soc-info.h" 17 18 DECLARE_GLOBAL_DATA_PTR; 19 20 static void uniphier_setup_xirq(void) 21 { 22 const void *fdt = gd->fdt_blob; 23 int soc_node, aidet_node; 24 const u32 *val; 25 unsigned long aidet_base; 26 u32 tmp; 27 28 soc_node = fdt_path_offset(fdt, "/soc"); 29 if (soc_node < 0) 30 return; 31 32 aidet_node = fdt_subnode_offset_namelen(fdt, soc_node, "aidet", 5); 33 if (aidet_node < 0) 34 return; 35 36 val = fdt_getprop(fdt, aidet_node, "reg", NULL); 37 if (!val) 38 return; 39 40 aidet_base = fdt32_to_cpu(*val); 41 42 tmp = readl(aidet_base + 8); /* AIDET DETCONFR2 */ 43 tmp |= 0x00ff0000; /* Set XIRQ0-7 low active */ 44 writel(tmp, aidet_base + 8); 45 46 tmp = readl(0x55000090); /* IRQCTL */ 47 tmp |= 0x000000ff; 48 writel(tmp, 0x55000090); 49 } 50 51 #ifdef CONFIG_ARCH_UNIPHIER_LD11 52 static void uniphier_ld11_misc_init(void) 53 { 54 sg_set_pinsel(149, 14, 8, 4); /* XIRQ0 -> XIRQ0 */ 55 sg_set_iectrl(149); 56 sg_set_pinsel(153, 14, 8, 4); /* XIRQ4 -> XIRQ4 */ 57 sg_set_iectrl(153); 58 } 59 #endif 60 61 #ifdef CONFIG_ARCH_UNIPHIER_LD20 62 static void uniphier_ld20_misc_init(void) 63 { 64 sg_set_pinsel(149, 14, 8, 4); /* XIRQ0 -> XIRQ0 */ 65 sg_set_iectrl(149); 66 sg_set_pinsel(153, 14, 8, 4); /* XIRQ4 -> XIRQ4 */ 67 sg_set_iectrl(153); 68 69 /* ES1 errata: increase VDD09 supply to suppress VBO noise */ 70 if (uniphier_get_soc_revision() == 1) { 71 writel(0x00000003, 0x6184e004); 72 writel(0x00000100, 0x6184e040); 73 writel(0x0000b500, 0x6184e024); 74 writel(0x00000001, 0x6184e000); 75 } 76 77 cci500_init(2); 78 } 79 #endif 80 81 struct uniphier_initdata { 82 enum uniphier_soc_id soc_id; 83 bool nand_2cs; 84 void (*sbc_init)(void); 85 void (*pll_init)(void); 86 void (*clk_init)(void); 87 void (*misc_init)(void); 88 }; 89 90 struct uniphier_initdata uniphier_initdata[] = { 91 #if defined(CONFIG_ARCH_UNIPHIER_SLD3) 92 { 93 .soc_id = SOC_UNIPHIER_SLD3, 94 .nand_2cs = true, 95 .sbc_init = uniphier_sbc_init_admulti, 96 .pll_init = uniphier_sld3_pll_init, 97 .clk_init = uniphier_ld4_clk_init, 98 }, 99 #endif 100 #if defined(CONFIG_ARCH_UNIPHIER_LD4) 101 { 102 .soc_id = SOC_UNIPHIER_LD4, 103 .nand_2cs = true, 104 .sbc_init = uniphier_ld4_sbc_init, 105 .pll_init = uniphier_ld4_pll_init, 106 .clk_init = uniphier_ld4_clk_init, 107 }, 108 #endif 109 #if defined(CONFIG_ARCH_UNIPHIER_PRO4) 110 { 111 .soc_id = SOC_UNIPHIER_PRO4, 112 .nand_2cs = false, 113 .sbc_init = uniphier_sbc_init_savepin, 114 .pll_init = uniphier_pro4_pll_init, 115 .clk_init = uniphier_pro4_clk_init, 116 }, 117 #endif 118 #if defined(CONFIG_ARCH_UNIPHIER_SLD8) 119 { 120 .soc_id = SOC_UNIPHIER_SLD8, 121 .nand_2cs = true, 122 .sbc_init = uniphier_ld4_sbc_init, 123 .pll_init = uniphier_ld4_pll_init, 124 .clk_init = uniphier_ld4_clk_init, 125 }, 126 #endif 127 #if defined(CONFIG_ARCH_UNIPHIER_PRO5) 128 { 129 .soc_id = SOC_UNIPHIER_PRO5, 130 .nand_2cs = true, 131 .sbc_init = uniphier_sbc_init_savepin, 132 .clk_init = uniphier_pro5_clk_init, 133 }, 134 #endif 135 #if defined(CONFIG_ARCH_UNIPHIER_PXS2) 136 { 137 .soc_id = SOC_UNIPHIER_PXS2, 138 .nand_2cs = true, 139 .sbc_init = uniphier_pxs2_sbc_init, 140 .clk_init = uniphier_pxs2_clk_init, 141 }, 142 #endif 143 #if defined(CONFIG_ARCH_UNIPHIER_LD6B) 144 { 145 .soc_id = SOC_UNIPHIER_LD6B, 146 .nand_2cs = true, 147 .sbc_init = uniphier_pxs2_sbc_init, 148 .clk_init = uniphier_pxs2_clk_init, 149 }, 150 #endif 151 #if defined(CONFIG_ARCH_UNIPHIER_LD11) 152 { 153 .soc_id = SOC_UNIPHIER_LD11, 154 .nand_2cs = false, 155 .sbc_init = uniphier_ld11_sbc_init, 156 .pll_init = uniphier_ld11_pll_init, 157 .clk_init = uniphier_ld11_clk_init, 158 .misc_init = uniphier_ld11_misc_init, 159 }, 160 #endif 161 #if defined(CONFIG_ARCH_UNIPHIER_LD20) 162 { 163 .soc_id = SOC_UNIPHIER_LD20, 164 .nand_2cs = false, 165 .sbc_init = uniphier_ld11_sbc_init, 166 .pll_init = uniphier_ld20_pll_init, 167 .misc_init = uniphier_ld20_misc_init, 168 }, 169 #endif 170 }; 171 172 static struct uniphier_initdata *uniphier_get_initdata( 173 enum uniphier_soc_id soc_id) 174 { 175 int i; 176 177 for (i = 0; i < ARRAY_SIZE(uniphier_initdata); i++) { 178 if (uniphier_initdata[i].soc_id == soc_id) 179 return &uniphier_initdata[i]; 180 } 181 182 return NULL; 183 } 184 185 int board_init(void) 186 { 187 struct uniphier_initdata *initdata; 188 enum uniphier_soc_id soc_id; 189 int ret; 190 191 led_puts("U0"); 192 193 soc_id = uniphier_get_soc_type(); 194 initdata = uniphier_get_initdata(soc_id); 195 if (!initdata) { 196 pr_err("unsupported board\n"); 197 return -EINVAL; 198 } 199 200 initdata->sbc_init(); 201 202 support_card_init(); 203 204 led_puts("U0"); 205 206 if (IS_ENABLED(CONFIG_NAND_DENALI)) { 207 ret = uniphier_pin_init(initdata->nand_2cs ? 208 "nand2cs_grp" : "nand_grp"); 209 if (ret) 210 pr_err("failed to init NAND pins\n"); 211 } 212 213 led_puts("U1"); 214 215 if (initdata->pll_init) 216 initdata->pll_init(); 217 218 led_puts("U2"); 219 220 if (initdata->clk_init) 221 initdata->clk_init(); 222 223 led_puts("U3"); 224 225 if (initdata->misc_init) 226 initdata->misc_init(); 227 228 led_puts("U4"); 229 230 uniphier_setup_xirq(); 231 232 led_puts("U5"); 233 234 support_card_late_init(); 235 236 led_puts("U6"); 237 238 #ifdef CONFIG_ARM64 239 uniphier_smp_kick_all_cpus(); 240 #endif 241 242 led_puts("Uboo"); 243 244 return 0; 245 } 246