diff options
Diffstat (limited to 'arch/powerpc/platforms/52xx/mpc52xx_common.c')
-rw-r--r-- | arch/powerpc/platforms/52xx/mpc52xx_common.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c new file mode 100644 index 00000000000..05b21444127 --- /dev/null +++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c | |||
@@ -0,0 +1,124 @@ | |||
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 | } | ||
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) { | ||
62 | p_ipb_freq = get_property(node, "bus-frequency", NULL); | ||
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 | } | ||
75 | |||
76 | |||
77 | void __init | ||
78 | mpc52xx_setup_cpu(void) | ||
79 | { | ||
80 | struct mpc52xx_cdm __iomem *cdm; | ||
81 | struct mpc52xx_xlb __iomem *xlb; | ||
82 | |||
83 | /* Map zones */ | ||
84 | cdm = mpc52xx_find_and_map("mpc52xx-cdm"); | ||
85 | xlb = mpc52xx_find_and_map("mpc52xx-xlb"); | ||
86 | |||
87 | if (!cdm || !xlb) { | ||
88 | printk(KERN_ERR __FILE__ ": " | ||
89 | "Error while mapping CDM/XLB during mpc52xx_setup_cpu. " | ||
90 | "Expect some abnormal behavior\n"); | ||
91 | goto unmap_regs; | ||
92 | } | ||
93 | |||
94 | /* Use internal 48 Mhz */ | ||
95 | out_8(&cdm->ext_48mhz_en, 0x00); | ||
96 | out_8(&cdm->fd_enable, 0x01); | ||
97 | if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */ | ||
98 | out_be16(&cdm->fd_counters, 0x0001); | ||
99 | else | ||
100 | out_be16(&cdm->fd_counters, 0x5555); | ||
101 | |||
102 | /* Configure the XLB Arbiter priorities */ | ||
103 | out_be32(&xlb->master_pri_enable, 0xff); | ||
104 | out_be32(&xlb->master_priority, 0x11111111); | ||
105 | |||
106 | /* Disable XLB pipelining */ | ||
107 | /* (cfr errate 292. We could do this only just before ATA PIO | ||
108 | transaction and re-enable it afterwards ...) */ | ||
109 | out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS); | ||
110 | |||
111 | /* Unmap zones */ | ||
112 | unmap_regs: | ||
113 | if (cdm) iounmap(cdm); | ||
114 | if (xlb) iounmap(xlb); | ||
115 | } | ||
116 | |||
117 | static int __init | ||
118 | mpc52xx_declare_of_platform_devices(void) | ||
119 | { | ||
120 | /* Find every child of the SOC node and add it to of_platform */ | ||
121 | return of_platform_bus_probe(NULL, NULL, NULL); | ||
122 | } | ||
123 | |||
124 | device_initcall(mpc52xx_declare_of_platform_devices); | ||