Commit | Line | Data |
---|---|---|
6065170c GL |
1 | /* |
2 | * | |
3 | * Utility functions for the Freescale MPC52xx. | |
4 | * | |
5 | * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com> | |
6 | * | |
7 | * This file is licensed under the terms of the GNU General Public License | |
8 | * version 2. This program is licensed "as is" without any warranty of any | |
9 | * kind, whether express or implied. | |
10 | * | |
11 | */ | |
12 | ||
13 | #undef DEBUG | |
14 | ||
15 | #include <linux/kernel.h> | |
9fe2e796 | 16 | #include <linux/of_platform.h> |
6065170c GL |
17 | #include <asm/io.h> |
18 | #include <asm/prom.h> | |
6065170c GL |
19 | #include <asm/mpc52xx.h> |
20 | ||
21 | ||
22 | void __iomem * | |
23 | mpc52xx_find_and_map(const char *compatible) | |
24 | { | |
25 | struct device_node *ofn; | |
26 | const u32 *regaddr_p; | |
27 | u64 regaddr64, size64; | |
28 | ||
29 | ofn = of_find_compatible_node(NULL, NULL, compatible); | |
30 | if (!ofn) | |
31 | return NULL; | |
32 | ||
33 | regaddr_p = of_get_address(ofn, 0, &size64, NULL); | |
34 | if (!regaddr_p) { | |
35 | of_node_put(ofn); | |
36 | return NULL; | |
37 | } | |
38 | ||
39 | regaddr64 = of_translate_address(ofn, regaddr_p); | |
40 | ||
41 | of_node_put(ofn); | |
42 | ||
43 | return ioremap((u32)regaddr64, (u32)size64); | |
44 | } | |
d8594d63 | 45 | EXPORT_SYMBOL(mpc52xx_find_and_map); |
6065170c GL |
46 | |
47 | ||
48 | /** | |
49 | * mpc52xx_find_ipb_freq - Find the IPB bus frequency for a device | |
50 | * @node: device node | |
51 | * | |
52 | * Returns IPB bus frequency, or 0 if the bus frequency cannot be found. | |
53 | */ | |
54 | unsigned int | |
55 | mpc52xx_find_ipb_freq(struct device_node *node) | |
56 | { | |
57 | struct device_node *np; | |
58 | const unsigned int *p_ipb_freq = NULL; | |
59 | ||
60 | of_node_get(node); | |
61 | while (node) { | |
e2eb6392 | 62 | p_ipb_freq = of_get_property(node, "bus-frequency", NULL); |
6065170c GL |
63 | if (p_ipb_freq) |
64 | break; | |
65 | ||
66 | np = of_get_parent(node); | |
67 | of_node_put(node); | |
68 | node = np; | |
69 | } | |
70 | if (node) | |
71 | of_node_put(node); | |
72 | ||
73 | return p_ipb_freq ? *p_ipb_freq : 0; | |
74 | } | |
d8594d63 | 75 | EXPORT_SYMBOL(mpc52xx_find_ipb_freq); |
6065170c GL |
76 | |
77 | ||
78 | void __init | |
79 | mpc52xx_setup_cpu(void) | |
80 | { | |
81 | struct mpc52xx_cdm __iomem *cdm; | |
82 | struct mpc52xx_xlb __iomem *xlb; | |
83 | ||
84 | /* Map zones */ | |
e3aba81d GL |
85 | cdm = mpc52xx_find_and_map("mpc5200-cdm"); |
86 | xlb = mpc52xx_find_and_map("mpc5200-xlb"); | |
6065170c GL |
87 | |
88 | if (!cdm || !xlb) { | |
89 | printk(KERN_ERR __FILE__ ": " | |
90 | "Error while mapping CDM/XLB during mpc52xx_setup_cpu. " | |
91 | "Expect some abnormal behavior\n"); | |
92 | goto unmap_regs; | |
93 | } | |
94 | ||
95 | /* Use internal 48 Mhz */ | |
96 | out_8(&cdm->ext_48mhz_en, 0x00); | |
97 | out_8(&cdm->fd_enable, 0x01); | |
98 | if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */ | |
99 | out_be16(&cdm->fd_counters, 0x0001); | |
100 | else | |
101 | out_be16(&cdm->fd_counters, 0x5555); | |
102 | ||
103 | /* Configure the XLB Arbiter priorities */ | |
104 | out_be32(&xlb->master_pri_enable, 0xff); | |
105 | out_be32(&xlb->master_priority, 0x11111111); | |
106 | ||
107 | /* Disable XLB pipelining */ | |
108 | /* (cfr errate 292. We could do this only just before ATA PIO | |
109 | transaction and re-enable it afterwards ...) */ | |
110 | out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS); | |
111 | ||
112 | /* Unmap zones */ | |
113 | unmap_regs: | |
114 | if (cdm) iounmap(cdm); | |
115 | if (xlb) iounmap(xlb); | |
116 | } | |
117 | ||
5c334eed | 118 | void __init |
6065170c GL |
119 | mpc52xx_declare_of_platform_devices(void) |
120 | { | |
121 | /* Find every child of the SOC node and add it to of_platform */ | |
5c334eed SM |
122 | if (of_platform_bus_probe(NULL, NULL, NULL)) |
123 | printk(KERN_ERR __FILE__ ": " | |
124 | "Error while probing of_platform bus\n"); | |
6065170c GL |
125 | } |
126 |