Merge git://git.infradead.org/~dwmw2/rbtree-2.6
[linux-2.6] / arch / ppc / platforms / mpc8272ads_setup.c
1 /*
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>
29 #include <linux/fs_uart_pd.h>
30
31 #include "pq2ads_pd.h"
32
33 static void init_fcc1_ioports(void);
34 static void init_fcc2_ioports(void);
35 static void init_scc1_uart_ioports(void);
36 static void init_scc4_uart_ioports(void);
37
38 static 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 };
58
59 static 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
71 static 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
95 static 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
119 static 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
160 static 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
206 static 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
228 static 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
244 static 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
261 static 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
277 static 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",
282                         .rtn = mpc8272ads_fixup_enet_pdata,
283                 },
284                 {
285                         .bus_id = "fsl-cpm-scc:uart",
286                         .rtn = mpc8272ads_fixup_uart_pdata,
287                 },
288                 {
289                         .bus_id = NULL
290                 }
291         };
292         platform_notify_map(dev_map,dev);
293
294         return 0;
295
296 }
297
298 int __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
310         /* 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
323         return 0;
324 }
325
326 /*
327    To prevent confusion, console selection is gross:
328    by 0 assumed SCC1 and by 1 assumed SCC4
329  */
330 struct 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];
338                 pinfo = &mpc8272_uart_pdata[fsid_scc4_uart];
339         } else { /*over SCC1*/
340                 pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC1];
341                 pinfo = &mpc8272_uart_pdata[fsid_scc1_uart];
342         }
343
344         pinfo->uart_clk = bd->bi_intfreq;
345         pdev->dev.platform_data = pinfo;
346         ppc_sys_fixup_mem_resource(pdev, CPM_MAP_ADDR);
347         return NULL;
348 }
349
350 arch_initcall(mpc8272ads_init);