Commit | Line | Data |
---|---|---|
6b642531 GL |
1 | /* |
2 | * Freescale Lite5200 board support | |
3 | * | |
4 | * Written by: Grant Likely <grant.likely@secretlab.ca> | |
5 | * | |
6 | * Copyright (C) Secret Lab Technologies Ltd. 2006. All rights reserved. | |
8a56e1ee | 7 | * Copyright 2006 Freescale Semiconductor, Inc. All rights reserved. |
6b642531 GL |
8 | * |
9 | * Description: | |
10 | * This program is free software; you can redistribute it and/or modify it | |
11 | * under the terms of the GNU General Public License as published by the | |
12 | * Free Software Foundation; either version 2 of the License, or (at your | |
13 | * option) any later version. | |
14 | */ | |
15 | ||
16 | #undef DEBUG | |
17 | ||
6b642531 | 18 | #include <linux/init.h> |
6b642531 | 19 | #include <linux/pci.h> |
9fe2e796 | 20 | #include <linux/of.h> |
22ae782f | 21 | #include <linux/of_address.h> |
c1f807ef AV |
22 | #include <linux/root_dev.h> |
23 | #include <linux/initrd.h> | |
6b642531 GL |
24 | #include <asm/time.h> |
25 | #include <asm/io.h> | |
26 | #include <asm/machdep.h> | |
6b642531 | 27 | #include <asm/prom.h> |
6b642531 GL |
28 | #include <asm/mpc52xx.h> |
29 | ||
30 | /* ************************************************************************ | |
31 | * | |
32 | * Setup the architecture | |
33 | * | |
34 | */ | |
35 | ||
66ffbe49 | 36 | /* mpc5200 device tree match tables */ |
ce6d73c9 | 37 | static const struct of_device_id mpc5200_cdm_ids[] __initconst = { |
66ffbe49 GL |
38 | { .compatible = "fsl,mpc5200-cdm", }, |
39 | { .compatible = "mpc5200-cdm", }, | |
40 | {} | |
41 | }; | |
42 | ||
ce6d73c9 | 43 | static const struct of_device_id mpc5200_gpio_ids[] __initconst = { |
66ffbe49 GL |
44 | { .compatible = "fsl,mpc5200-gpio", }, |
45 | { .compatible = "mpc5200-gpio", }, | |
46 | {} | |
47 | }; | |
48 | ||
4de3b992 GL |
49 | /* |
50 | * Fix clock configuration. | |
51 | * | |
52 | * Firmware is supposed to be responsible for this. If you are creating a | |
53 | * new board port, do *NOT* duplicate this code. Fix your boot firmware | |
54 | * to set it correctly in the first place | |
55 | */ | |
6b642531 | 56 | static void __init |
4de3b992 GL |
57 | lite5200_fix_clock_config(void) |
58 | { | |
75ca399e | 59 | struct device_node *np; |
4de3b992 | 60 | struct mpc52xx_cdm __iomem *cdm; |
4de3b992 | 61 | /* Map zones */ |
66ffbe49 | 62 | np = of_find_matching_node(NULL, mpc5200_cdm_ids); |
75ca399e GL |
63 | cdm = of_iomap(np, 0); |
64 | of_node_put(np); | |
4de3b992 GL |
65 | if (!cdm) { |
66 | printk(KERN_ERR "%s() failed; expect abnormal behaviour\n", | |
e48b1b45 | 67 | __func__); |
4de3b992 GL |
68 | return; |
69 | } | |
70 | ||
71 | /* Use internal 48 Mhz */ | |
72 | out_8(&cdm->ext_48mhz_en, 0x00); | |
73 | out_8(&cdm->fd_enable, 0x01); | |
74 | if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */ | |
75 | out_be16(&cdm->fd_counters, 0x0001); | |
76 | else | |
77 | out_be16(&cdm->fd_counters, 0x5555); | |
78 | ||
79 | /* Unmap the regs */ | |
80 | iounmap(cdm); | |
81 | } | |
82 | ||
83 | /* | |
84 | * Fix setting of port_config register. | |
85 | * | |
86 | * Firmware is supposed to be responsible for this. If you are creating a | |
87 | * new board port, do *NOT* duplicate this code. Fix your boot firmware | |
88 | * to set it correctly in the first place | |
89 | */ | |
90 | static void __init | |
91 | lite5200_fix_port_config(void) | |
6b642531 | 92 | { |
75ca399e | 93 | struct device_node *np; |
6b642531 GL |
94 | struct mpc52xx_gpio __iomem *gpio; |
95 | u32 port_config; | |
96 | ||
66ffbe49 | 97 | np = of_find_matching_node(NULL, mpc5200_gpio_ids); |
75ca399e GL |
98 | gpio = of_iomap(np, 0); |
99 | of_node_put(np); | |
6b642531 | 100 | if (!gpio) { |
4de3b992 | 101 | printk(KERN_ERR "%s() failed. expect abnormal behavior\n", |
e48b1b45 | 102 | __func__); |
4de3b992 | 103 | return; |
6b642531 GL |
104 | } |
105 | ||
106 | /* Set port config */ | |
107 | port_config = in_be32(&gpio->port_config); | |
108 | ||
109 | port_config &= ~0x00800000; /* 48Mhz internal, pin is GPIO */ | |
110 | ||
111 | port_config &= ~0x00007000; /* USB port : Differential mode */ | |
112 | port_config |= 0x00001000; /* USB 1 only */ | |
113 | ||
114 | port_config &= ~0x03000000; /* ATA CS is on csb_4/5 */ | |
115 | port_config |= 0x01000000; | |
116 | ||
117 | pr_debug("port_config: old:%x new:%x\n", | |
118 | in_be32(&gpio->port_config), port_config); | |
119 | out_be32(&gpio->port_config, port_config); | |
120 | ||
121 | /* Unmap zone */ | |
6b642531 GL |
122 | iounmap(gpio); |
123 | } | |
124 | ||
2e1ee1f7 | 125 | #ifdef CONFIG_PM |
2e1ee1f7 DP |
126 | static void lite5200_suspend_prepare(void __iomem *mbar) |
127 | { | |
128 | u8 pin = 1; /* GPIO_WKUP_1 (GPIO_PSC2_4) */ | |
129 | u8 level = 0; /* wakeup on low level */ | |
130 | mpc52xx_set_wakeup_gpio(pin, level); | |
131 | ||
132 | /* | |
133 | * power down usb port | |
134 | * this needs to be called before of-ohci suspend code | |
135 | */ | |
ee983079 DP |
136 | |
137 | /* set ports to "power switched" and "powered at the same time" | |
138 | * USB Rh descriptor A: NPS = 0, PSM = 0 */ | |
139 | out_be32(mbar + 0x1048, in_be32(mbar + 0x1048) & ~0x300); | |
140 | /* USB Rh status: LPS = 1 - turn off power */ | |
141 | out_be32(mbar + 0x1050, 0x00000001); | |
2e1ee1f7 DP |
142 | } |
143 | ||
144 | static void lite5200_resume_finish(void __iomem *mbar) | |
145 | { | |
ee983079 DP |
146 | /* USB Rh status: LPSC = 1 - turn on power */ |
147 | out_be32(mbar + 0x1050, 0x00010000); | |
2e1ee1f7 DP |
148 | } |
149 | #endif | |
150 | ||
e3aba81d | 151 | static void __init lite5200_setup_arch(void) |
6b642531 | 152 | { |
6b642531 | 153 | if (ppc_md.progress) |
e3aba81d | 154 | ppc_md.progress("lite5200_setup_arch()", 0); |
6b642531 | 155 | |
c8004a28 GL |
156 | /* Map important registers from the internal memory map */ |
157 | mpc52xx_map_common_devices(); | |
4de3b992 GL |
158 | |
159 | /* Some mpc5200 & mpc5200b related configuration */ | |
160 | mpc5200_setup_xlb_arbiter(); | |
6b642531 | 161 | |
c8004a28 GL |
162 | /* Fix things that firmware should have done. */ |
163 | lite5200_fix_clock_config(); | |
164 | lite5200_fix_port_config(); | |
9dda78b7 | 165 | |
2e1ee1f7 DP |
166 | #ifdef CONFIG_PM |
167 | mpc52xx_suspend.board_suspend_prepare = lite5200_suspend_prepare; | |
168 | mpc52xx_suspend.board_resume_finish = lite5200_resume_finish; | |
ee983079 | 169 | lite5200_pm_init(); |
2e1ee1f7 DP |
170 | #endif |
171 | ||
f584bc65 | 172 | mpc52xx_setup_pci(); |
6b642531 GL |
173 | } |
174 | ||
9597abe0 | 175 | static const char * const board[] __initconst = { |
a4f740cf GL |
176 | "fsl,lite5200", |
177 | "fsl,lite5200b", | |
178 | NULL, | |
179 | }; | |
180 | ||
6b642531 GL |
181 | /* |
182 | * Called very early, MMU is off, device-tree isn't unflattened | |
183 | */ | |
e3aba81d | 184 | static int __init lite5200_probe(void) |
6b642531 | 185 | { |
a4f740cf | 186 | return of_flat_dt_match(of_get_flat_dt_root(), board); |
6b642531 GL |
187 | } |
188 | ||
e3aba81d GL |
189 | define_machine(lite5200) { |
190 | .name = "lite5200", | |
191 | .probe = lite5200_probe, | |
192 | .setup_arch = lite5200_setup_arch, | |
5c334eed | 193 | .init = mpc52xx_declare_of_platform_devices, |
6b642531 GL |
194 | .init_IRQ = mpc52xx_init_irq, |
195 | .get_irq = mpc52xx_get_irq, | |
9dda78b7 | 196 | .restart = mpc52xx_restart, |
6b642531 GL |
197 | .calibrate_decr = generic_calibrate_decr, |
198 | }; |