Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
[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
30 #include "pq2ads_pd.h"
31
32 static void init_fcc1_ioports(void);
33 static void init_fcc2_ioports(void);
34
35 static struct fs_mii_bus_info mii_bus_info = {
36         .method                 = fsmii_bitbang,
37         .id                     = 0,
38         .i.bitbang = {
39                 .mdio_port      = fsiop_portc,
40                 .mdio_bit       = 18,
41                 .mdc_port       = fsiop_portc,
42                 .mdc_bit        = 19,
43                 .delay          = 1,
44         },
45 };
46
47 static struct fs_platform_info mpc82xx_fcc1_pdata = {
48         .fs_no          = fsid_fcc1,
49         .cp_page        = CPM_CR_FCC1_PAGE,
50         .cp_block       = CPM_CR_FCC1_SBLOCK,
51         .clk_trx        = (PC_F1RXCLK | PC_F1TXCLK),
52         .clk_route      = CMX1_CLK_ROUTE,
53         .clk_mask       = CMX1_CLK_MASK,
54         .init_ioports   = init_fcc1_ioports,
55
56         .phy_addr       = 0,
57 #ifdef PHY_INTERRUPT
58         .phy_irq        = PHY_INTERRUPT,
59 #else
60         .phy_irq        = -1;
61 #endif
62         .mem_offset     = FCC1_MEM_OFFSET,
63         .bus_info       = &mii_bus_info,
64         .rx_ring        = 32,
65         .tx_ring        = 32,
66         .rx_copybreak   = 240,
67         .use_napi       = 0,
68         .napi_weight    = 17,
69 };
70
71 static struct fs_platform_info mpc82xx_fcc2_pdata = {
72         .fs_no          = fsid_fcc2,
73         .cp_page        = CPM_CR_FCC2_PAGE,
74         .cp_block       = CPM_CR_FCC2_SBLOCK,
75         .clk_trx        = (PC_F2RXCLK | PC_F2TXCLK),
76         .clk_route      = CMX2_CLK_ROUTE,
77         .clk_mask       = CMX2_CLK_MASK,
78         .init_ioports   = init_fcc2_ioports,
79
80         .phy_addr       = 3,
81 #ifdef PHY_INTERRUPT
82         .phy_irq        = PHY_INTERRUPT,
83 #else
84         .phy_irq        = -1;
85 #endif
86         .mem_offset     = FCC2_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 void init_fcc1_ioports(void)
96 {
97         struct io_port *io;
98         u32 tempval;
99         cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
100         u32 *bcsr = ioremap(BCSR_ADDR+4, sizeof(u32));
101
102         io = &immap->im_ioport;
103
104         /* Enable the PHY */
105         clrbits32(bcsr, BCSR1_FETHIEN);
106         setbits32(bcsr, BCSR1_FETH_RST);
107
108         /* FCC1 pins are on port A/C. */
109         /* Configure port A and C pins for FCC1 Ethernet. */
110
111         tempval = in_be32(&io->iop_pdira);
112         tempval &= ~PA1_DIRA0;
113         tempval |= PA1_DIRA1;
114         out_be32(&io->iop_pdira, tempval);
115
116         tempval = in_be32(&io->iop_psora);
117         tempval &= ~PA1_PSORA0;
118         tempval |= PA1_PSORA1;
119         out_be32(&io->iop_psora, tempval);
120
121         setbits32(&io->iop_ppara,PA1_DIRA0 | PA1_DIRA1);
122
123         /* Alter clocks */
124         tempval = PC_F1TXCLK|PC_F1RXCLK;
125
126         clrbits32(&io->iop_psorc, tempval);
127         clrbits32(&io->iop_pdirc, tempval);
128         setbits32(&io->iop_pparc, tempval);
129
130         clrbits32(&immap->im_cpmux.cmx_fcr, CMX1_CLK_MASK);
131         setbits32(&immap->im_cpmux.cmx_fcr, CMX1_CLK_ROUTE);
132         iounmap(bcsr);
133         iounmap(immap);
134 }
135
136 static void init_fcc2_ioports(void)
137 {
138         cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
139         u32 *bcsr = ioremap(BCSR_ADDR+12, sizeof(u32));
140
141         struct io_port *io;
142         u32 tempval;
143
144         immap = cpm2_immr;
145
146         io = &immap->im_ioport;
147
148         /* Enable the PHY */
149         clrbits32(bcsr, BCSR3_FETHIEN2);
150         setbits32(bcsr, BCSR3_FETH2_RST);
151
152         /* FCC2 are port B/C. */
153         /* Configure port A and C pins for FCC2 Ethernet. */
154
155         tempval = in_be32(&io->iop_pdirb);
156         tempval &= ~PB2_DIRB0;
157         tempval |= PB2_DIRB1;
158         out_be32(&io->iop_pdirb, tempval);
159
160         tempval = in_be32(&io->iop_psorb);
161         tempval &= ~PB2_PSORB0;
162         tempval |= PB2_PSORB1;
163         out_be32(&io->iop_psorb, tempval);
164
165         setbits32(&io->iop_pparb,PB2_DIRB0 | PB2_DIRB1);
166
167         tempval = PC_F2RXCLK|PC_F2TXCLK;
168
169         /* Alter clocks */
170         clrbits32(&io->iop_psorc,tempval);
171         clrbits32(&io->iop_pdirc,tempval);
172         setbits32(&io->iop_pparc,tempval);
173
174         clrbits32(&immap->im_cpmux.cmx_fcr, CMX2_CLK_MASK);
175         setbits32(&immap->im_cpmux.cmx_fcr, CMX2_CLK_ROUTE);
176
177         iounmap(bcsr);
178         iounmap(immap);
179 }
180
181
182 static void __init mpc8272ads_fixup_enet_pdata(struct platform_device *pdev,
183                                               int idx)
184 {
185         bd_t* bi = (void*)__res;
186         int fs_no = fsid_fcc1+pdev->id-1;
187
188         mpc82xx_fcc1_pdata.dpram_offset = mpc82xx_fcc2_pdata.dpram_offset = (u32)cpm2_immr->im_dprambase;
189         mpc82xx_fcc1_pdata.fcc_regs_c = mpc82xx_fcc2_pdata.fcc_regs_c = (u32)cpm2_immr->im_fcc_c;
190
191         switch(fs_no) {
192                 case fsid_fcc1:
193                         memcpy(&mpc82xx_fcc1_pdata.macaddr,bi->bi_enetaddr,6);
194                         pdev->dev.platform_data = &mpc82xx_fcc1_pdata;
195                 break;
196                 case fsid_fcc2:
197                         memcpy(&mpc82xx_fcc2_pdata.macaddr,bi->bi_enetaddr,6);
198                         mpc82xx_fcc2_pdata.macaddr[5] ^= 1;
199                         pdev->dev.platform_data = &mpc82xx_fcc2_pdata;
200                 break;
201         }
202 }
203
204 static int mpc8272ads_platform_notify(struct device *dev)
205 {
206         static const struct platform_notify_dev_map dev_map[] = {
207                 {
208                         .bus_id = "fsl-cpm-fcc",
209                         .rtn = mpc8272ads_fixup_enet_pdata
210                 },
211                 {
212                         .bus_id = NULL
213                 }
214         };
215         platform_notify_map(dev_map,dev);
216
217         return 0;
218
219 }
220
221 int __init mpc8272ads_init(void)
222 {
223         printk(KERN_NOTICE "mpc8272ads: Init\n");
224
225         platform_notify = mpc8272ads_platform_notify;
226
227         ppc_sys_device_initfunc();
228
229         ppc_sys_device_disable_all();
230         ppc_sys_device_enable(MPC82xx_CPM_FCC1);
231         ppc_sys_device_enable(MPC82xx_CPM_FCC2);
232
233         return 0;
234 }
235
236 arch_initcall(mpc8272ads_init);