1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2012-2015 Panasonic Corporation
4  * Copyright (C) 2015-2016 Socionext Inc.
5  *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
6  */
7 
8 #include <linux/errno.h>
9 #include <linux/io.h>
10 #include <linux/printk.h>
11 
12 #include "init.h"
13 #include "micro-support-card.h"
14 #include "soc-info.h"
15 
16 #define PC0CTRL				0x598000c0
17 
18 #if defined(CONFIG_ARCH_UNIPHIER_LD4) || defined(CONFIG_ARCH_UNIPHIER_SLD8)
uniphier_ld4_sbc_init(void)19 static void uniphier_ld4_sbc_init(void)
20 {
21 	u32 tmp;
22 
23 	/* system bus output enable */
24 	tmp = readl(PC0CTRL);
25 	tmp &= 0xfffffcff;
26 	writel(tmp, PC0CTRL);
27 }
28 #endif
29 
30 #if defined(CONFIG_ARCH_UNIPHIER_PXS2) || \
31     defined(CONFIG_ARCH_UNIPHIER_LD6B) || \
32     defined(CONFIG_ARCH_UNIPHIER_LD11) || \
33     defined(CONFIG_ARCH_UNIPHIER_LD20) || \
34     defined(CONFIG_ARCH_UNIPHIER_PXS3)
uniphier_pxs2_sbc_init(void)35 static void uniphier_pxs2_sbc_init(void)
36 {
37 	/* necessary for ROM boot ?? */
38 	/* system bus output enable */
39 	writel(0x17, PC0CTRL);
40 }
41 #endif
42 
43 #ifdef CONFIG_ARCH_UNIPHIER_LD20
uniphier_ld20_misc_init(void)44 static void uniphier_ld20_misc_init(void)
45 {
46 	/* ES1 errata: increase VDD09 supply to suppress VBO noise */
47 	if (uniphier_get_soc_revision() == 1) {
48 		writel(0x00000003, 0x6184e004);
49 		writel(0x00000100, 0x6184e040);
50 		writel(0x0000b500, 0x6184e024);
51 		writel(0x00000001, 0x6184e000);
52 	}
53 }
54 #endif
55 
56 struct uniphier_initdata {
57 	unsigned int soc_id;
58 	void (*sbc_init)(void);
59 	void (*pll_init)(void);
60 	void (*clk_init)(void);
61 	void (*misc_init)(void);
62 };
63 
64 static const struct uniphier_initdata uniphier_initdata[] = {
65 #if defined(CONFIG_ARCH_UNIPHIER_LD4)
66 	{
67 		.soc_id = UNIPHIER_LD4_ID,
68 		.sbc_init = uniphier_ld4_sbc_init,
69 		.pll_init = uniphier_ld4_pll_init,
70 	},
71 #endif
72 #if defined(CONFIG_ARCH_UNIPHIER_PRO4)
73 	{
74 		.soc_id = UNIPHIER_PRO4_ID,
75 		.pll_init = uniphier_pro4_pll_init,
76 		.clk_init = uniphier_pro4_clk_init,
77 	},
78 #endif
79 #if defined(CONFIG_ARCH_UNIPHIER_SLD8)
80 	{
81 		.soc_id = UNIPHIER_SLD8_ID,
82 		.sbc_init = uniphier_ld4_sbc_init,
83 		.pll_init = uniphier_ld4_pll_init,
84 	},
85 #endif
86 #if defined(CONFIG_ARCH_UNIPHIER_PRO5)
87 	{
88 		.soc_id = UNIPHIER_PRO5_ID,
89 		.clk_init = uniphier_pro5_clk_init,
90 	},
91 #endif
92 #if defined(CONFIG_ARCH_UNIPHIER_PXS2)
93 	{
94 		.soc_id = UNIPHIER_PXS2_ID,
95 		.sbc_init = uniphier_pxs2_sbc_init,
96 		.clk_init = uniphier_pxs2_clk_init,
97 	},
98 #endif
99 #if defined(CONFIG_ARCH_UNIPHIER_LD6B)
100 	{
101 		.soc_id = UNIPHIER_LD6B_ID,
102 		.sbc_init = uniphier_pxs2_sbc_init,
103 		.clk_init = uniphier_pxs2_clk_init,
104 	},
105 #endif
106 #if defined(CONFIG_ARCH_UNIPHIER_LD11)
107 	{
108 		.soc_id = UNIPHIER_LD11_ID,
109 		.sbc_init = uniphier_pxs2_sbc_init,
110 		.pll_init = uniphier_ld11_pll_init,
111 		.clk_init = uniphier_ld11_clk_init,
112 	},
113 #endif
114 #if defined(CONFIG_ARCH_UNIPHIER_LD20)
115 	{
116 		.soc_id = UNIPHIER_LD20_ID,
117 		.sbc_init = uniphier_pxs2_sbc_init,
118 		.pll_init = uniphier_ld20_pll_init,
119 		.clk_init = uniphier_ld20_clk_init,
120 		.misc_init = uniphier_ld20_misc_init,
121 	},
122 #endif
123 #if defined(CONFIG_ARCH_UNIPHIER_PXS3)
124 	{
125 		.soc_id = UNIPHIER_PXS3_ID,
126 		.sbc_init = uniphier_pxs2_sbc_init,
127 		.pll_init = uniphier_pxs3_pll_init,
128 		.clk_init = uniphier_pxs3_clk_init,
129 	},
130 #endif
131 };
UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_initdata,uniphier_initdata)132 UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_initdata, uniphier_initdata)
133 
134 int board_init(void)
135 {
136 	const struct uniphier_initdata *initdata;
137 
138 	led_puts("U0");
139 
140 	initdata = uniphier_get_initdata();
141 	if (!initdata) {
142 		pr_err("unsupported SoC\n");
143 		return -EINVAL;
144 	}
145 
146 	if (initdata->sbc_init)
147 		initdata->sbc_init();
148 
149 	support_card_init();
150 
151 	led_puts("U0");
152 
153 	if (initdata->pll_init)
154 		initdata->pll_init();
155 
156 	led_puts("U1");
157 
158 	if (initdata->clk_init)
159 		initdata->clk_init();
160 
161 	led_puts("U2");
162 
163 	if (initdata->misc_init)
164 		initdata->misc_init();
165 
166 	led_puts("Uboo");
167 
168 	return 0;
169 }
170