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