Commit | Line | Data |
---|---|---|
29f1530f VB |
1 | /*arch/ppc/platforms/mpc86xads-setup.c |
2 | * | |
3 | * Platform setup for the Freescale mpc86xads board | |
4 | * | |
5 | * Vitaly Bordug <vbordug@ru.mvista.com> | |
6 | * | |
7 | * Copyright 2005 MontaVista Software Inc. | |
8 | * | |
9 | * This file is licensed under the terms of the GNU General Public License | |
10 | * version 2. This program is licensed "as is" without any warranty of any | |
11 | * kind, whether express or implied. | |
12 | */ | |
13 | ||
14 | #include <linux/init.h> | |
15 | #include <linux/module.h> | |
16 | #include <linux/param.h> | |
17 | #include <linux/string.h> | |
18 | #include <linux/ioport.h> | |
19 | #include <linux/device.h> | |
20 | #include <linux/delay.h> | |
21 | #include <linux/root_dev.h> | |
22 | ||
23 | #include <linux/fs_enet_pd.h> | |
24 | #include <linux/fs_uart_pd.h> | |
25 | #include <linux/mii.h> | |
26 | ||
27 | #include <asm/delay.h> | |
28 | #include <asm/io.h> | |
29 | #include <asm/machdep.h> | |
30 | #include <asm/page.h> | |
31 | #include <asm/processor.h> | |
32 | #include <asm/system.h> | |
33 | #include <asm/time.h> | |
34 | #include <asm/ppcboot.h> | |
35 | #include <asm/mpc8xx.h> | |
36 | #include <asm/8xx_immap.h> | |
37 | #include <asm/commproc.h> | |
38 | #include <asm/fs_pd.h> | |
39 | #include <asm/prom.h> | |
40 | ||
41 | extern void cpm_reset(void); | |
42 | extern void mpc8xx_show_cpuinfo(struct seq_file*); | |
43 | extern void mpc8xx_restart(char *cmd); | |
44 | extern void mpc8xx_calibrate_decr(void); | |
45 | extern int mpc8xx_set_rtc_time(struct rtc_time *tm); | |
46 | extern void mpc8xx_get_rtc_time(struct rtc_time *tm); | |
47 | extern void m8xx_pic_init(void); | |
48 | extern unsigned int mpc8xx_get_irq(void); | |
49 | ||
50 | static void init_smc1_uart_ioports(struct fs_uart_platform_info* fpi); | |
51 | static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi); | |
52 | static void init_scc1_ioports(struct fs_platform_info* ptr); | |
53 | ||
54 | void __init mpc86xads_board_setup(void) | |
55 | { | |
56 | cpm8xx_t *cp; | |
57 | unsigned int *bcsr_io; | |
58 | u8 tmpval8; | |
59 | ||
60 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | |
61 | cp = (cpm8xx_t *)immr_map(im_cpm); | |
62 | ||
63 | if (bcsr_io == NULL) { | |
64 | printk(KERN_CRIT "Could not remap BCSR\n"); | |
65 | return; | |
66 | } | |
67 | #ifdef CONFIG_SERIAL_CPM_SMC1 | |
68 | clrbits32(bcsr_io, BCSR1_RS232EN_1); | |
69 | clrbits32(&cp->cp_simode, 0xe0000000 >> 17); /* brg1 */ | |
70 | tmpval8 = in_8(&(cp->cp_smc[0].smc_smcm)) | (SMCM_RX | SMCM_TX); | |
71 | out_8(&(cp->cp_smc[0].smc_smcm), tmpval8); | |
72 | clrbits16(&cp->cp_smc[0].smc_smcmr, SMCMR_REN | SMCMR_TEN); | |
73 | #else | |
74 | setbits32(bcsr_io,BCSR1_RS232EN_1); | |
75 | out_be16(&cp->cp_smc[0].smc_smcmr, 0); | |
76 | out_8(&cp->cp_smc[0].smc_smce, 0); | |
77 | #endif | |
78 | ||
79 | #ifdef CONFIG_SERIAL_CPM_SMC2 | |
80 | clrbits32(bcsr_io,BCSR1_RS232EN_2); | |
81 | clrbits32(&cp->cp_simode, 0xe0000000 >> 1); | |
82 | setbits32(&cp->cp_simode, 0x20000000 >> 1); /* brg2 */ | |
83 | tmpval8 = in_8(&(cp->cp_smc[1].smc_smcm)) | (SMCM_RX | SMCM_TX); | |
84 | out_8(&(cp->cp_smc[1].smc_smcm), tmpval8); | |
85 | clrbits16(&cp->cp_smc[1].smc_smcmr, SMCMR_REN | SMCMR_TEN); | |
86 | ||
87 | init_smc2_uart_ioports(0); | |
88 | #else | |
89 | setbits32(bcsr_io,BCSR1_RS232EN_2); | |
90 | out_be16(&cp->cp_smc[1].smc_smcmr, 0); | |
91 | out_8(&cp->cp_smc[1].smc_smce, 0); | |
92 | #endif | |
93 | immr_unmap(cp); | |
94 | iounmap(bcsr_io); | |
95 | } | |
96 | ||
97 | ||
98 | static void init_fec1_ioports(struct fs_platform_info* ptr) | |
99 | { | |
100 | iop8xx_t *io_port = (iop8xx_t *)immr_map(im_ioport); | |
101 | ||
102 | /* configure FEC1 pins */ | |
103 | ||
104 | setbits16(&io_port->iop_pdpar, 0x1fff); | |
105 | setbits16(&io_port->iop_pddir, 0x1fff); | |
106 | ||
107 | immr_unmap(io_port); | |
108 | } | |
109 | ||
110 | void init_fec_ioports(struct fs_platform_info *fpi) | |
111 | { | |
112 | int fec_no = fs_get_fec_index(fpi->fs_no); | |
113 | ||
114 | switch (fec_no) { | |
115 | case 0: | |
116 | init_fec1_ioports(fpi); | |
117 | break; | |
118 | default: | |
119 | printk(KERN_ERR "init_fec_ioports: invalid FEC number\n"); | |
120 | return; | |
121 | } | |
122 | } | |
123 | ||
124 | static void init_scc1_ioports(struct fs_platform_info* fpi) | |
125 | { | |
126 | unsigned *bcsr_io; | |
127 | iop8xx_t *io_port; | |
128 | cpm8xx_t *cp; | |
129 | ||
130 | bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE); | |
131 | io_port = (iop8xx_t *)immr_map(im_ioport); | |
132 | cp = (cpm8xx_t *)immr_map(im_cpm); | |
133 | ||
134 | if (bcsr_io == NULL) { | |
135 | printk(KERN_CRIT "Could not remap BCSR\n"); | |
136 | return; | |
137 | } | |
138 | ||
139 | /* Configure port A pins for Txd and Rxd. | |
140 | */ | |
141 | setbits16(&io_port->iop_papar, PA_ENET_RXD | PA_ENET_TXD); | |
142 | clrbits16(&io_port->iop_padir, PA_ENET_RXD | PA_ENET_TXD); | |
143 | clrbits16(&io_port->iop_paodr, PA_ENET_TXD); | |
144 | ||
145 | /* Configure port C pins to enable CLSN and RENA. | |
146 | */ | |
147 | clrbits16(&io_port->iop_pcpar, PC_ENET_CLSN | PC_ENET_RENA); | |
148 | clrbits16(&io_port->iop_pcdir, PC_ENET_CLSN | PC_ENET_RENA); | |
149 | setbits16(&io_port->iop_pcso, PC_ENET_CLSN | PC_ENET_RENA); | |
150 | ||
151 | /* Configure port A for TCLK and RCLK. | |
152 | */ | |
153 | setbits16(&io_port->iop_papar, PA_ENET_TCLK | PA_ENET_RCLK); | |
154 | clrbits16(&io_port->iop_padir, PA_ENET_TCLK | PA_ENET_RCLK); | |
155 | clrbits32(&cp->cp_pbpar, PB_ENET_TENA); | |
156 | clrbits32(&cp->cp_pbdir, PB_ENET_TENA); | |
157 | ||
158 | /* Configure Serial Interface clock routing. | |
159 | * First, clear all SCC bits to zero, then set the ones we want. | |
160 | */ | |
161 | clrbits32(&cp->cp_sicr, SICR_ENET_MASK); | |
162 | setbits32(&cp->cp_sicr, SICR_ENET_CLKRT); | |
163 | ||
164 | /* In the original SCC enet driver the following code is placed at | |
165 | the end of the initialization */ | |
166 | setbits32(&cp->cp_pbpar, PB_ENET_TENA); | |
167 | setbits32(&cp->cp_pbdir, PB_ENET_TENA); | |
168 | ||
169 | clrbits32(bcsr_io+1, BCSR1_ETHEN); | |
170 | iounmap(bcsr_io); | |
171 | immr_unmap(cp); | |
172 | immr_unmap(io_port); | |
173 | } | |
174 | ||
175 | void init_scc_ioports(struct fs_platform_info *fpi) | |
176 | { | |
177 | int scc_no = fs_get_scc_index(fpi->fs_no); | |
178 | ||
179 | switch (scc_no) { | |
180 | case 0: | |
181 | init_scc1_ioports(fpi); | |
182 | break; | |
183 | default: | |
184 | printk(KERN_ERR "init_scc_ioports: invalid SCC number\n"); | |
185 | return; | |
186 | } | |
187 | } | |
188 | ||
189 | ||
190 | ||
191 | static void init_smc1_uart_ioports(struct fs_uart_platform_info* ptr) | |
192 | { | |
193 | unsigned *bcsr_io; | |
194 | cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm); | |
195 | ||
196 | setbits32(&cp->cp_pbpar, 0x000000c0); | |
197 | clrbits32(&cp->cp_pbdir, 0x000000c0); | |
198 | clrbits16(&cp->cp_pbodr, 0x00c0); | |
199 | immr_unmap(cp); | |
200 | ||
201 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | |
202 | ||
203 | if (bcsr_io == NULL) { | |
204 | printk(KERN_CRIT "Could not remap BCSR1\n"); | |
205 | return; | |
206 | } | |
207 | clrbits32(bcsr_io,BCSR1_RS232EN_1); | |
208 | iounmap(bcsr_io); | |
209 | } | |
210 | ||
211 | static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi) | |
212 | { | |
213 | unsigned *bcsr_io; | |
214 | cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm); | |
215 | ||
216 | setbits32(&cp->cp_pbpar, 0x00000c00); | |
217 | clrbits32(&cp->cp_pbdir, 0x00000c00); | |
218 | clrbits16(&cp->cp_pbodr, 0x0c00); | |
219 | immr_unmap(cp); | |
220 | ||
221 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | |
222 | ||
223 | if (bcsr_io == NULL) { | |
224 | printk(KERN_CRIT "Could not remap BCSR1\n"); | |
225 | return; | |
226 | } | |
227 | clrbits32(bcsr_io,BCSR1_RS232EN_2); | |
228 | iounmap(bcsr_io); | |
229 | } | |
230 | ||
231 | void init_smc_ioports(struct fs_uart_platform_info *data) | |
232 | { | |
233 | int smc_no = fs_uart_id_fsid2smc(data->fs_no); | |
234 | ||
235 | switch (smc_no) { | |
236 | case 0: | |
237 | init_smc1_uart_ioports(data); | |
238 | data->brg = data->clk_rx; | |
239 | break; | |
240 | case 1: | |
241 | init_smc2_uart_ioports(data); | |
242 | data->brg = data->clk_rx; | |
243 | break; | |
244 | default: | |
245 | printk(KERN_ERR "init_scc_ioports: invalid SCC number\n"); | |
246 | return; | |
247 | } | |
248 | } | |
249 | ||
e2eb6392 | 250 | int platform_device_skip(const char *model, int id) |
29f1530f VB |
251 | { |
252 | return 0; | |
253 | } | |
254 | ||
255 | static void __init mpc86xads_setup_arch(void) | |
256 | { | |
257 | struct device_node *cpu; | |
258 | ||
259 | cpu = of_find_node_by_type(NULL, "cpu"); | |
260 | if (cpu != 0) { | |
261 | const unsigned int *fp; | |
262 | ||
e2eb6392 | 263 | fp = of_get_property(cpu, "clock-frequency", NULL); |
29f1530f VB |
264 | if (fp != 0) |
265 | loops_per_jiffy = *fp / HZ; | |
266 | else | |
267 | loops_per_jiffy = 50000000 / HZ; | |
268 | of_node_put(cpu); | |
269 | } | |
270 | ||
271 | cpm_reset(); | |
272 | ||
273 | mpc86xads_board_setup(); | |
274 | ||
275 | ROOT_DEV = Root_NFS; | |
276 | } | |
277 | ||
278 | static int __init mpc86xads_probe(void) | |
279 | { | |
280 | char *model = of_get_flat_dt_prop(of_get_flat_dt_root(), | |
281 | "model", NULL); | |
282 | if (model == NULL) | |
283 | return 0; | |
284 | if (strcmp(model, "MPC866ADS")) | |
285 | return 0; | |
286 | ||
287 | return 1; | |
288 | } | |
289 | ||
290 | define_machine(mpc86x_ads) { | |
291 | .name = "MPC86x ADS", | |
292 | .probe = mpc86xads_probe, | |
293 | .setup_arch = mpc86xads_setup_arch, | |
294 | .init_IRQ = m8xx_pic_init, | |
295 | .show_cpuinfo = mpc8xx_show_cpuinfo, | |
296 | .get_irq = mpc8xx_get_irq, | |
297 | .restart = mpc8xx_restart, | |
298 | .calibrate_decr = mpc8xx_calibrate_decr, | |
299 | .set_rtc_time = mpc8xx_set_rtc_time, | |
300 | .get_rtc_time = mpc8xx_get_rtc_time, | |
301 | }; |