ARM: imx6: report soc info via soc device
[deliverable/linux.git] / arch / arm / mach-imx / mach-imx6q.c
1 /*
2 * Copyright 2011-2013 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13 #include <linux/clk.h>
14 #include <linux/clkdev.h>
15 #include <linux/cpu.h>
16 #include <linux/delay.h>
17 #include <linux/export.h>
18 #include <linux/init.h>
19 #include <linux/io.h>
20 #include <linux/irq.h>
21 #include <linux/irqchip.h>
22 #include <linux/of.h>
23 #include <linux/of_address.h>
24 #include <linux/of_irq.h>
25 #include <linux/of_platform.h>
26 #include <linux/opp.h>
27 #include <linux/phy.h>
28 #include <linux/reboot.h>
29 #include <linux/regmap.h>
30 #include <linux/micrel_phy.h>
31 #include <linux/mfd/syscon.h>
32 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
33 #include <asm/mach/arch.h>
34 #include <asm/mach/map.h>
35 #include <asm/system_misc.h>
36
37 #include "common.h"
38 #include "cpuidle.h"
39 #include "hardware.h"
40
41 static void imx6q_restart(enum reboot_mode mode, const char *cmd)
42 {
43 struct device_node *np;
44 void __iomem *wdog_base;
45
46 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-wdt");
47 wdog_base = of_iomap(np, 0);
48 if (!wdog_base)
49 goto soft;
50
51 imx_src_prepare_restart();
52
53 /* enable wdog */
54 writew_relaxed(1 << 2, wdog_base);
55 /* write twice to ensure the request will not get ignored */
56 writew_relaxed(1 << 2, wdog_base);
57
58 /* wait for reset to assert ... */
59 mdelay(500);
60
61 pr_err("Watchdog reset failed to assert reset\n");
62
63 /* delay to allow the serial port to show the message */
64 mdelay(50);
65
66 soft:
67 /* we'll take a jump through zero as a poor second */
68 soft_restart(0);
69 }
70
71 /* For imx6q sabrelite board: set KSZ9021RN RGMII pad skew */
72 static int ksz9021rn_phy_fixup(struct phy_device *phydev)
73 {
74 if (IS_BUILTIN(CONFIG_PHYLIB)) {
75 /* min rx data delay */
76 phy_write(phydev, MICREL_KSZ9021_EXTREG_CTRL,
77 0x8000 | MICREL_KSZ9021_RGMII_RX_DATA_PAD_SCEW);
78 phy_write(phydev, MICREL_KSZ9021_EXTREG_DATA_WRITE, 0x0000);
79
80 /* max rx/tx clock delay, min rx/tx control delay */
81 phy_write(phydev, MICREL_KSZ9021_EXTREG_CTRL,
82 0x8000 | MICREL_KSZ9021_RGMII_CLK_CTRL_PAD_SCEW);
83 phy_write(phydev, MICREL_KSZ9021_EXTREG_DATA_WRITE, 0xf0f0);
84 phy_write(phydev, MICREL_KSZ9021_EXTREG_CTRL,
85 MICREL_KSZ9021_RGMII_CLK_CTRL_PAD_SCEW);
86 }
87
88 return 0;
89 }
90
91 static void mmd_write_reg(struct phy_device *dev, int device, int reg, int val)
92 {
93 phy_write(dev, 0x0d, device);
94 phy_write(dev, 0x0e, reg);
95 phy_write(dev, 0x0d, (1 << 14) | device);
96 phy_write(dev, 0x0e, val);
97 }
98
99 static int ksz9031rn_phy_fixup(struct phy_device *dev)
100 {
101 /*
102 * min rx data delay, max rx/tx clock delay,
103 * min rx/tx control delay
104 */
105 mmd_write_reg(dev, 2, 4, 0);
106 mmd_write_reg(dev, 2, 5, 0);
107 mmd_write_reg(dev, 2, 8, 0x003ff);
108
109 return 0;
110 }
111
112 static int ar8031_phy_fixup(struct phy_device *dev)
113 {
114 u16 val;
115
116 /* To enable AR8031 output a 125MHz clk from CLK_25M */
117 phy_write(dev, 0xd, 0x7);
118 phy_write(dev, 0xe, 0x8016);
119 phy_write(dev, 0xd, 0x4007);
120
121 val = phy_read(dev, 0xe);
122 val &= 0xffe3;
123 val |= 0x18;
124 phy_write(dev, 0xe, val);
125
126 /* introduce tx clock delay */
127 phy_write(dev, 0x1d, 0x5);
128 val = phy_read(dev, 0x1e);
129 val |= 0x0100;
130 phy_write(dev, 0x1e, val);
131
132 return 0;
133 }
134
135 #define PHY_ID_AR8031 0x004dd074
136
137 static void __init imx6q_enet_phy_init(void)
138 {
139 if (IS_BUILTIN(CONFIG_PHYLIB)) {
140 phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK,
141 ksz9021rn_phy_fixup);
142 phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK,
143 ksz9031rn_phy_fixup);
144 phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff,
145 ar8031_phy_fixup);
146 }
147 }
148
149 static void __init imx6q_1588_init(void)
150 {
151 struct regmap *gpr;
152
153 gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
154 if (!IS_ERR(gpr))
155 regmap_update_bits(gpr, IOMUXC_GPR1,
156 IMX6Q_GPR1_ENET_CLK_SEL_MASK,
157 IMX6Q_GPR1_ENET_CLK_SEL_ANATOP);
158 else
159 pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n");
160
161 }
162
163 static void __init imx6q_init_machine(void)
164 {
165 struct device *parent;
166
167 imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q",
168 imx_get_soc_revision());
169
170 parent = imx_soc_device_init();
171 if (parent == NULL)
172 pr_warn("failed to initialize soc device\n");
173
174 imx6q_enet_phy_init();
175
176 of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
177
178 imx_anatop_init();
179 imx6q_pm_init();
180 imx6q_1588_init();
181 }
182
183 #define OCOTP_CFG3 0x440
184 #define OCOTP_CFG3_SPEED_SHIFT 16
185 #define OCOTP_CFG3_SPEED_1P2GHZ 0x3
186
187 static void __init imx6q_opp_check_1p2ghz(struct device *cpu_dev)
188 {
189 struct device_node *np;
190 void __iomem *base;
191 u32 val;
192
193 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ocotp");
194 if (!np) {
195 pr_warn("failed to find ocotp node\n");
196 return;
197 }
198
199 base = of_iomap(np, 0);
200 if (!base) {
201 pr_warn("failed to map ocotp\n");
202 goto put_node;
203 }
204
205 val = readl_relaxed(base + OCOTP_CFG3);
206 val >>= OCOTP_CFG3_SPEED_SHIFT;
207 if ((val & 0x3) != OCOTP_CFG3_SPEED_1P2GHZ)
208 if (opp_disable(cpu_dev, 1200000000))
209 pr_warn("failed to disable 1.2 GHz OPP\n");
210
211 put_node:
212 of_node_put(np);
213 }
214
215 static void __init imx6q_opp_init(void)
216 {
217 struct device_node *np;
218 struct device *cpu_dev = get_cpu_device(0);
219
220 if (!cpu_dev) {
221 pr_warn("failed to get cpu0 device\n");
222 return;
223 }
224 np = of_node_get(cpu_dev->of_node);
225 if (!np) {
226 pr_warn("failed to find cpu0 node\n");
227 return;
228 }
229
230 if (of_init_opp_table(cpu_dev)) {
231 pr_warn("failed to init OPP table\n");
232 goto put_node;
233 }
234
235 imx6q_opp_check_1p2ghz(cpu_dev);
236
237 put_node:
238 of_node_put(np);
239 }
240
241 static struct platform_device imx6q_cpufreq_pdev = {
242 .name = "imx6q-cpufreq",
243 };
244
245 static void __init imx6q_init_late(void)
246 {
247 /*
248 * WAIT mode is broken on TO 1.0 and 1.1, so there is no point
249 * to run cpuidle on them.
250 */
251 if (imx_get_soc_revision() > IMX_CHIP_REVISION_1_1)
252 imx6q_cpuidle_init();
253
254 if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) {
255 imx6q_opp_init();
256 platform_device_register(&imx6q_cpufreq_pdev);
257 }
258 }
259
260 static void __init imx6q_map_io(void)
261 {
262 debug_ll_io_init();
263 imx_scu_map_io();
264 }
265
266 static void __init imx6q_init_irq(void)
267 {
268 imx_init_revision_from_anatop();
269 imx_init_l2cache();
270 imx_src_init();
271 imx_gpc_init();
272 irqchip_init();
273 }
274
275 static const char *imx6q_dt_compat[] __initdata = {
276 "fsl,imx6dl",
277 "fsl,imx6q",
278 NULL,
279 };
280
281 DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)")
282 .smp = smp_ops(imx_smp_ops),
283 .map_io = imx6q_map_io,
284 .init_irq = imx6q_init_irq,
285 .init_machine = imx6q_init_machine,
286 .init_late = imx6q_init_late,
287 .dt_compat = imx6q_dt_compat,
288 .restart = imx6q_restart,
289 MACHINE_END
This page took 0.036097 seconds and 5 git commands to generate.