blob: abb7154de2c7fcba30125b5b1971da761a2a59df [file] [log] [blame]
Vitaly Bordug42dc75c2006-01-20 22:22:36 +03001/*
2 * arch/ppc/platforms/82xx/pq2ads_pd.c
3 *
4 * MPC82xx Board-specific PlatformDevice descriptions
5 *
6 * 2005 (c) MontaVista Software, Inc.
7 * Vitaly Bordug <vbordug@ru.mvista.com>
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
15#include <linux/init.h>
16#include <linux/module.h>
17#include <linux/device.h>
18#include <linux/ioport.h>
19#include <linux/fs_enet_pd.h>
20#include <linux/platform_device.h>
21
22#include <asm/io.h>
23#include <asm/mpc8260.h>
24#include <asm/cpm2.h>
25#include <asm/immap_cpm2.h>
26#include <asm/irq.h>
27#include <asm/ppc_sys.h>
28#include <asm/ppcboot.h>
Vitaly Bordug4427d6b2006-04-25 20:26:43 +040029#include <linux/fs_uart_pd.h>
Vitaly Bordug42dc75c2006-01-20 22:22:36 +030030
31#include "pq2ads_pd.h"
32
33static void init_fcc1_ioports(void);
34static void init_fcc2_ioports(void);
Vitaly Bordug4427d6b2006-04-25 20:26:43 +040035static void init_scc1_uart_ioports(void);
36static void init_scc4_uart_ioports(void);
37
38static struct fs_uart_platform_info mpc8272_uart_pdata[] = {
39 [fsid_scc1_uart] = {
40 .init_ioports = init_scc1_uart_ioports,
41 .fs_no = fsid_scc1_uart,
42 .brg = 1,
43 .tx_num_fifo = 4,
44 .tx_buf_size = 32,
45 .rx_num_fifo = 4,
46 .rx_buf_size = 32,
47 },
48 [fsid_scc4_uart] = {
49 .init_ioports = init_scc4_uart_ioports,
50 .fs_no = fsid_scc4_uart,
51 .brg = 4,
52 .tx_num_fifo = 4,
53 .tx_buf_size = 32,
54 .rx_num_fifo = 4,
55 .rx_buf_size = 32,
56 },
57};
Vitaly Bordug42dc75c2006-01-20 22:22:36 +030058
59static struct fs_mii_bus_info mii_bus_info = {
60 .method = fsmii_bitbang,
61 .id = 0,
62 .i.bitbang = {
63 .mdio_port = fsiop_portc,
64 .mdio_bit = 18,
65 .mdc_port = fsiop_portc,
66 .mdc_bit = 19,
67 .delay = 1,
68 },
69};
70
71static struct fs_platform_info mpc82xx_fcc1_pdata = {
72 .fs_no = fsid_fcc1,
73 .cp_page = CPM_CR_FCC1_PAGE,
74 .cp_block = CPM_CR_FCC1_SBLOCK,
75 .clk_trx = (PC_F1RXCLK | PC_F1TXCLK),
76 .clk_route = CMX1_CLK_ROUTE,
77 .clk_mask = CMX1_CLK_MASK,
78 .init_ioports = init_fcc1_ioports,
79
80 .phy_addr = 0,
81#ifdef PHY_INTERRUPT
82 .phy_irq = PHY_INTERRUPT,
83#else
84 .phy_irq = -1;
85#endif
86 .mem_offset = FCC1_MEM_OFFSET,
87 .bus_info = &mii_bus_info,
88 .rx_ring = 32,
89 .tx_ring = 32,
90 .rx_copybreak = 240,
91 .use_napi = 0,
92 .napi_weight = 17,
93};
94
95static struct fs_platform_info mpc82xx_fcc2_pdata = {
96 .fs_no = fsid_fcc2,
97 .cp_page = CPM_CR_FCC2_PAGE,
98 .cp_block = CPM_CR_FCC2_SBLOCK,
99 .clk_trx = (PC_F2RXCLK | PC_F2TXCLK),
100 .clk_route = CMX2_CLK_ROUTE,
101 .clk_mask = CMX2_CLK_MASK,
102 .init_ioports = init_fcc2_ioports,
103
104 .phy_addr = 3,
105#ifdef PHY_INTERRUPT
106 .phy_irq = PHY_INTERRUPT,
107#else
108 .phy_irq = -1;
109#endif
110 .mem_offset = FCC2_MEM_OFFSET,
111 .bus_info = &mii_bus_info,
112 .rx_ring = 32,
113 .tx_ring = 32,
114 .rx_copybreak = 240,
115 .use_napi = 0,
116 .napi_weight = 17,
117};
118
119static void init_fcc1_ioports(void)
120{
121 struct io_port *io;
122 u32 tempval;
123 cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
124 u32 *bcsr = ioremap(BCSR_ADDR+4, sizeof(u32));
125
126 io = &immap->im_ioport;
127
128 /* Enable the PHY */
129 clrbits32(bcsr, BCSR1_FETHIEN);
130 setbits32(bcsr, BCSR1_FETH_RST);
131
132 /* FCC1 pins are on port A/C. */
133 /* Configure port A and C pins for FCC1 Ethernet. */
134
135 tempval = in_be32(&io->iop_pdira);
136 tempval &= ~PA1_DIRA0;
137 tempval |= PA1_DIRA1;
138 out_be32(&io->iop_pdira, tempval);
139
140 tempval = in_be32(&io->iop_psora);
141 tempval &= ~PA1_PSORA0;
142 tempval |= PA1_PSORA1;
143 out_be32(&io->iop_psora, tempval);
144
145 setbits32(&io->iop_ppara,PA1_DIRA0 | PA1_DIRA1);
146
147 /* Alter clocks */
148 tempval = PC_F1TXCLK|PC_F1RXCLK;
149
150 clrbits32(&io->iop_psorc, tempval);
151 clrbits32(&io->iop_pdirc, tempval);
152 setbits32(&io->iop_pparc, tempval);
153
154 clrbits32(&immap->im_cpmux.cmx_fcr, CMX1_CLK_MASK);
155 setbits32(&immap->im_cpmux.cmx_fcr, CMX1_CLK_ROUTE);
156 iounmap(bcsr);
157 iounmap(immap);
158}
159
160static void init_fcc2_ioports(void)
161{
162 cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
163 u32 *bcsr = ioremap(BCSR_ADDR+12, sizeof(u32));
164
165 struct io_port *io;
166 u32 tempval;
167
168 immap = cpm2_immr;
169
170 io = &immap->im_ioport;
171
172 /* Enable the PHY */
173 clrbits32(bcsr, BCSR3_FETHIEN2);
174 setbits32(bcsr, BCSR3_FETH2_RST);
175
176 /* FCC2 are port B/C. */
177 /* Configure port A and C pins for FCC2 Ethernet. */
178
179 tempval = in_be32(&io->iop_pdirb);
180 tempval &= ~PB2_DIRB0;
181 tempval |= PB2_DIRB1;
182 out_be32(&io->iop_pdirb, tempval);
183
184 tempval = in_be32(&io->iop_psorb);
185 tempval &= ~PB2_PSORB0;
186 tempval |= PB2_PSORB1;
187 out_be32(&io->iop_psorb, tempval);
188
189 setbits32(&io->iop_pparb,PB2_DIRB0 | PB2_DIRB1);
190
191 tempval = PC_F2RXCLK|PC_F2TXCLK;
192
193 /* Alter clocks */
194 clrbits32(&io->iop_psorc,tempval);
195 clrbits32(&io->iop_pdirc,tempval);
196 setbits32(&io->iop_pparc,tempval);
197
198 clrbits32(&immap->im_cpmux.cmx_fcr, CMX2_CLK_MASK);
199 setbits32(&immap->im_cpmux.cmx_fcr, CMX2_CLK_ROUTE);
200
201 iounmap(bcsr);
202 iounmap(immap);
203}
204
205
206static void __init mpc8272ads_fixup_enet_pdata(struct platform_device *pdev,
207 int idx)
208{
209 bd_t* bi = (void*)__res;
210 int fs_no = fsid_fcc1+pdev->id-1;
211
212 mpc82xx_fcc1_pdata.dpram_offset = mpc82xx_fcc2_pdata.dpram_offset = (u32)cpm2_immr->im_dprambase;
213 mpc82xx_fcc1_pdata.fcc_regs_c = mpc82xx_fcc2_pdata.fcc_regs_c = (u32)cpm2_immr->im_fcc_c;
214
215 switch(fs_no) {
216 case fsid_fcc1:
217 memcpy(&mpc82xx_fcc1_pdata.macaddr,bi->bi_enetaddr,6);
218 pdev->dev.platform_data = &mpc82xx_fcc1_pdata;
219 break;
220 case fsid_fcc2:
221 memcpy(&mpc82xx_fcc2_pdata.macaddr,bi->bi_enetaddr,6);
222 mpc82xx_fcc2_pdata.macaddr[5] ^= 1;
223 pdev->dev.platform_data = &mpc82xx_fcc2_pdata;
224 break;
225 }
226}
227
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400228static void mpc8272ads_fixup_uart_pdata(struct platform_device *pdev,
229 int idx)
230{
231 bd_t *bd = (bd_t *) __res;
232 struct fs_uart_platform_info *pinfo;
233 int num = ARRAY_SIZE(mpc8272_uart_pdata);
234 int id = fs_uart_id_scc2fsid(idx);
235
236 /* no need to alter anything if console */
237 if ((id <= num) && (!pdev->dev.platform_data)) {
238 pinfo = &mpc8272_uart_pdata[id];
239 pinfo->uart_clk = bd->bi_intfreq;
240 pdev->dev.platform_data = pinfo;
241 }
242}
243
244static void init_scc1_uart_ioports(void)
245{
246 cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
247
248 /* SCC1 is only on port D */
249 setbits32(&immap->im_ioport.iop_ppard,0x00000003);
250 clrbits32(&immap->im_ioport.iop_psord,0x00000001);
251 setbits32(&immap->im_ioport.iop_psord,0x00000002);
252 clrbits32(&immap->im_ioport.iop_pdird,0x00000001);
253 setbits32(&immap->im_ioport.iop_pdird,0x00000002);
254
255 /* Wire BRG1 to SCC1 */
256 clrbits32(&immap->im_cpmux.cmx_scr,0x00ffffff);
257
258 iounmap(immap);
259}
260
261static void init_scc4_uart_ioports(void)
262{
263 cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
264
265 setbits32(&immap->im_ioport.iop_ppard,0x00000600);
266 clrbits32(&immap->im_ioport.iop_psord,0x00000600);
267 clrbits32(&immap->im_ioport.iop_pdird,0x00000200);
268 setbits32(&immap->im_ioport.iop_pdird,0x00000400);
269
270 /* Wire BRG4 to SCC4 */
271 clrbits32(&immap->im_cpmux.cmx_scr,0x000000ff);
272 setbits32(&immap->im_cpmux.cmx_scr,0x0000001b);
273
274 iounmap(immap);
275}
276
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300277static int mpc8272ads_platform_notify(struct device *dev)
278{
279 static const struct platform_notify_dev_map dev_map[] = {
280 {
281 .bus_id = "fsl-cpm-fcc",
Vitaly Bordug8e30a9a2006-05-24 21:40:18 +0400282 .rtn = mpc8272ads_fixup_enet_pdata,
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300283 },
284 {
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400285 .bus_id = "fsl-cpm-scc:uart",
Vitaly Bordug8e30a9a2006-05-24 21:40:18 +0400286 .rtn = mpc8272ads_fixup_uart_pdata,
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400287 },
288 {
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300289 .bus_id = NULL
290 }
291 };
292 platform_notify_map(dev_map,dev);
293
294 return 0;
295
296}
297
298int __init mpc8272ads_init(void)
299{
300 printk(KERN_NOTICE "mpc8272ads: Init\n");
301
302 platform_notify = mpc8272ads_platform_notify;
303
304 ppc_sys_device_initfunc();
305
306 ppc_sys_device_disable_all();
307 ppc_sys_device_enable(MPC82xx_CPM_FCC1);
308 ppc_sys_device_enable(MPC82xx_CPM_FCC2);
309
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400310 /* to be ready for console, let's attach pdata here */
311#ifdef CONFIG_SERIAL_CPM_SCC1
312 ppc_sys_device_setfunc(MPC82xx_CPM_SCC1, PPC_SYS_FUNC_UART);
313 ppc_sys_device_enable(MPC82xx_CPM_SCC1);
314
315#endif
316
317#ifdef CONFIG_SERIAL_CPM_SCC4
318 ppc_sys_device_setfunc(MPC82xx_CPM_SCC4, PPC_SYS_FUNC_UART);
319 ppc_sys_device_enable(MPC82xx_CPM_SCC4);
320#endif
321
322
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300323 return 0;
324}
325
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400326/*
327 To prevent confusion, console selection is gross:
328 by 0 assumed SCC1 and by 1 assumed SCC4
329 */
330struct platform_device* early_uart_get_pdev(int index)
331{
332 bd_t *bd = (bd_t *) __res;
333 struct fs_uart_platform_info *pinfo;
334
335 struct platform_device* pdev = NULL;
336 if(index) { /*assume SCC4 here*/
337 pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC4];
Vitaly Bordug8e30a9a2006-05-24 21:40:18 +0400338 pinfo = &mpc8272_uart_pdata[fsid_scc4_uart];
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400339 } else { /*over SCC1*/
340 pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC1];
Vitaly Bordug8e30a9a2006-05-24 21:40:18 +0400341 pinfo = &mpc8272_uart_pdata[fsid_scc1_uart];
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400342 }
343
344 pinfo->uart_clk = bd->bi_intfreq;
345 pdev->dev.platform_data = pinfo;
Vitaly Bordug8e30a9a2006-05-24 21:40:18 +0400346 ppc_sys_fixup_mem_resource(pdev, CPM_MAP_ADDR);
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400347 return NULL;
348}
349
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300350arch_initcall(mpc8272ads_init);