Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
common.c
Go to the documentation of this file.
1 /*
2  * arch/arm/mach-orion5x/common.c
3  *
4  * Core functions for Marvell Orion 5x SoCs
5  *
6  * Maintainer: Tzachi Perelstein <[email protected]>
7  *
8  * This file is licensed under the terms of the GNU General Public
9  * License version 2. This program is licensed "as is" without any
10  * warranty of any kind, whether express or implied.
11  */
12 
13 #include <linux/kernel.h>
14 #include <linux/init.h>
15 #include <linux/platform_device.h>
16 #include <linux/dma-mapping.h>
17 #include <linux/serial_8250.h>
18 #include <linux/mv643xx_i2c.h>
19 #include <linux/ata_platform.h>
20 #include <linux/delay.h>
21 #include <linux/clk-provider.h>
22 #include <net/dsa.h>
23 #include <asm/page.h>
24 #include <asm/setup.h>
25 #include <asm/system_misc.h>
26 #include <asm/timex.h>
27 #include <asm/mach/arch.h>
28 #include <asm/mach/map.h>
29 #include <asm/mach/time.h>
30 #include <mach/bridge-regs.h>
31 #include <mach/hardware.h>
32 #include <mach/orion5x.h>
35 #include <plat/time.h>
36 #include <plat/common.h>
37 #include <plat/addr-map.h>
38 #include "common.h"
39 
40 /*****************************************************************************
41  * I/O Address Mapping
42  ****************************************************************************/
43 static struct map_desc orion5x_io_desc[] __initdata = {
44  {
45  .virtual = (unsigned long) ORION5X_REGS_VIRT_BASE,
47  .length = ORION5X_REGS_SIZE,
48  .type = MT_DEVICE,
49  }, {
50  .virtual = (unsigned long) ORION5X_PCIE_WA_VIRT_BASE,
52  .length = ORION5X_PCIE_WA_SIZE,
53  .type = MT_DEVICE,
54  },
55 };
56 
58 {
59  iotable_init(orion5x_io_desc, ARRAY_SIZE(orion5x_io_desc));
60 }
61 
62 
63 /*****************************************************************************
64  * CLK tree
65  ****************************************************************************/
66 static struct clk *tclk;
67 
68 static void __init clk_init(void)
69 {
70  tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT,
71  orion5x_tclk);
72 
73  orion_clkdev_init(tclk);
74 }
75 
76 /*****************************************************************************
77  * EHCI0
78  ****************************************************************************/
80 {
83 }
84 
85 
86 /*****************************************************************************
87  * EHCI1
88  ****************************************************************************/
90 {
92 }
93 
94 
95 /*****************************************************************************
96  * GE00
97  ****************************************************************************/
99 {
100  orion_ge00_init(eth_data,
104 }
105 
106 
107 /*****************************************************************************
108  * Ethernet switch
109  ****************************************************************************/
111 {
112  orion_ge00_switch_init(d, irq);
113 }
114 
115 
116 /*****************************************************************************
117  * I2C
118  ****************************************************************************/
120 {
122 
123 }
124 
125 
126 /*****************************************************************************
127  * SATA
128  ****************************************************************************/
130 {
132 }
133 
134 
135 /*****************************************************************************
136  * SPI
137  ****************************************************************************/
139 {
141 }
142 
143 
144 /*****************************************************************************
145  * UART0
146  ****************************************************************************/
148 {
150  IRQ_ORION5X_UART0, tclk);
151 }
152 
153 /*****************************************************************************
154  * UART1
155  ****************************************************************************/
157 {
159  IRQ_ORION5X_UART1, tclk);
160 }
161 
162 /*****************************************************************************
163  * XOR engine
164  ****************************************************************************/
166 {
168  ORION5X_XOR_PHYS_BASE + 0x200,
170 }
171 
172 /*****************************************************************************
173  * Cryptographic Engines and Security Accelerator (CESA)
174  ****************************************************************************/
175 static void __init orion5x_crypto_init(void)
176 {
180 }
181 
182 /*****************************************************************************
183  * Watchdog
184  ****************************************************************************/
186 {
187  orion_wdt_init();
188 }
189 
190 
191 /*****************************************************************************
192  * Time handling
193  ****************************************************************************/
195 {
197 
198  /*
199  * Some Orion5x devices allocate their coherent buffers from atomic
200  * context. Increase size of atomic coherent pool to make sure such
201  * the allocations won't fail.
202  */
203  init_dma_coherent_pool_size(SZ_1M);
204 }
205 
207 
209 {
210  u32 dev, rev;
211 
212  orion5x_pcie_id(&dev, &rev);
213  if (dev == MV88F6183_DEV_ID &&
214  (readl(MPP_RESET_SAMPLE) & 0x00000200) == 0)
215  return 133333333;
216 
217  return 166666667;
218 }
219 
220 static void __init orion5x_timer_init(void)
221 {
222  orion5x_tclk = orion5x_find_tclk();
223 
225  IRQ_ORION5X_BRIDGE, orion5x_tclk);
226 }
227 
229  .init = orion5x_timer_init,
230 };
231 
232 
233 /*****************************************************************************
234  * General
235  ****************************************************************************/
236 /*
237  * Identify device ID and rev from PCIe configuration header space '0'.
238  */
239 static void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name)
240 {
241  orion5x_pcie_id(dev, rev);
242 
243  if (*dev == MV88F5281_DEV_ID) {
244  if (*rev == MV88F5281_REV_D2) {
245  *dev_name = "MV88F5281-D2";
246  } else if (*rev == MV88F5281_REV_D1) {
247  *dev_name = "MV88F5281-D1";
248  } else if (*rev == MV88F5281_REV_D0) {
249  *dev_name = "MV88F5281-D0";
250  } else {
251  *dev_name = "MV88F5281-Rev-Unsupported";
252  }
253  } else if (*dev == MV88F5182_DEV_ID) {
254  if (*rev == MV88F5182_REV_A2) {
255  *dev_name = "MV88F5182-A2";
256  } else {
257  *dev_name = "MV88F5182-Rev-Unsupported";
258  }
259  } else if (*dev == MV88F5181_DEV_ID) {
260  if (*rev == MV88F5181_REV_B1) {
261  *dev_name = "MV88F5181-Rev-B1";
262  } else if (*rev == MV88F5181L_REV_A1) {
263  *dev_name = "MV88F5181L-Rev-A1";
264  } else {
265  *dev_name = "MV88F5181(L)-Rev-Unsupported";
266  }
267  } else if (*dev == MV88F6183_DEV_ID) {
268  if (*rev == MV88F6183_REV_B0) {
269  *dev_name = "MV88F6183-Rev-B0";
270  } else {
271  *dev_name = "MV88F6183-Rev-Unsupported";
272  }
273  } else {
274  *dev_name = "Device-Unknown";
275  }
276 }
277 
279 {
280  char *dev_name;
281  u32 dev, rev;
282 
283  orion5x_id(&dev, &rev, &dev_name);
284  printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, orion5x_tclk);
285 
286  /*
287  * Setup Orion address map
288  */
290 
291  /* Setup root of clk tree */
292  clk_init();
293 
294  /*
295  * Don't issue "Wait for Interrupt" instruction if we are
296  * running on D0 5281 silicon.
297  */
298  if (dev == MV88F5281_DEV_ID && rev == MV88F5281_REV_D0) {
299  printk(KERN_INFO "Orion: Applying 5281 D0 WFI workaround.\n");
300  disable_hlt();
301  }
302 
303  /*
304  * The 5082/5181l/5182/6082/6082l/6183 have crypto
305  * while 5180n/5181/5281 don't have crypto.
306  */
307  if ((dev == MV88F5181_DEV_ID && rev >= MV88F5181L_REV_A0) ||
308  dev == MV88F5182_DEV_ID || dev == MV88F6183_DEV_ID)
309  orion5x_crypto_init();
310 
311  /*
312  * Register watchdog driver
313  */
315 }
316 
317 void orion5x_restart(char mode, const char *cmd)
318 {
319  /*
320  * Enable and issue soft reset
321  */
322  orion5x_setbits(RSTOUTn_MASK, (1 << 2));
324  mdelay(200);
326 }
327 
328 /*
329  * Many orion-based systems have buggy bootloader implementations.
330  * This is a common fixup for bogus memory tags.
331  */
332 void __init tag_fixup_mem32(struct tag *t, char **from,
333  struct meminfo *meminfo)
334 {
335  for (; t->hdr.size; t = tag_next(t))
336  if (t->hdr.tag == ATAG_MEM &&
337  (!t->u.mem.size || t->u.mem.size & ~PAGE_MASK ||
338  t->u.mem.start & ~PAGE_MASK)) {
340  "Clearing invalid memory bank %dKB@0x%08x\n",
341  t->u.mem.size / 1024, t->u.mem.start);
342  t->hdr.tag = 0;
343  }
344 }