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