Merge branch 'master' of /home/sam/kernel/linux-2.6/
[pandora-kernel.git] / arch / ppc / platforms / mpc866ads_setup.c
index ac8fcc6..f19b616 100644 (file)
@@ -11,7 +11,6 @@
  * kind, whether express or implied.
  */
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/param.h>
@@ -20,6 +19,7 @@
 #include <linux/device.h>
 
 #include <linux/fs_enet_pd.h>
+#include <linux/fs_uart_pd.h>
 #include <linux/mii.h>
 
 #include <asm/delay.h>
 
 extern unsigned char __res[];
 
+static void setup_fec1_ioports(void);
+static void setup_scc1_ioports(void);
+static void setup_smc1_ioports(void);
+static void setup_smc2_ioports(void);
+
 static struct fs_mii_bus_info fec_mii_bus_info = {
        .method = fsmii_fec,
        .id = 0,
@@ -79,6 +84,28 @@ static struct fs_platform_info mpc8xx_scc_pdata = {
        .phy_irq = -1,
 
        .bus_info = &scc_mii_bus_info,
+
+};
+
+static struct fs_uart_platform_info mpc866_uart_pdata[] = {
+       [fsid_smc1_uart] = {
+               .brg            = 1,
+               .fs_no          = fsid_smc1_uart,
+               .init_ioports   = setup_smc1_ioports,
+               .tx_num_fifo    = 4,
+               .tx_buf_size    = 32,
+               .rx_num_fifo    = 4,
+               .rx_buf_size    = 32,
+       },
+       [fsid_smc2_uart] = {
+               .brg            = 2,
+               .fs_no          = fsid_smc2_uart,
+               .init_ioports   = setup_smc2_ioports,
+               .tx_num_fifo    = 4,
+               .tx_buf_size    = 32,
+               .rx_num_fifo    = 4,
+               .rx_buf_size    = 32,
+       },
 };
 
 void __init board_init(void)
@@ -92,9 +119,12 @@ void __init board_init(void)
                printk(KERN_CRIT "Could not remap BCSR1\n");
                return;
        }
+
 #ifdef CONFIG_SERIAL_CPM_SMC1
        cp->cp_simode &= ~(0xe0000000 >> 17);   /* brg1 */
        clrbits32(bcsr_io,(0x80000000 >> 7));
+       cp->cp_smc[0].smc_smcm |= (SMCM_RX | SMCM_TX);
+       cp->cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
 #else
        setbits32(bcsr_io,(0x80000000 >> 7));
 
@@ -108,6 +138,8 @@ void __init board_init(void)
        cp->cp_simode &= ~(0xe0000000 >> 1);
        cp->cp_simode |= (0x20000000 >> 1);     /* brg2 */
        clrbits32(bcsr_io,(0x80000000 >> 13));
+       cp->cp_smc[1].smc_smcm |= (SMCM_RX | SMCM_TX);
+       cp->cp_smc[1].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
 #else
        clrbits32(bcsr_io,(0x80000000 >> 13));
        cp->cp_pbpar &= ~(0x00000c00);
@@ -232,6 +264,74 @@ static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
        mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
 }
 
+static void setup_smc1_ioports(void)
+{
+       immap_t *immap = (immap_t *) IMAP_ADDR;
+       unsigned *bcsr_io;
+       unsigned int iobits = 0x000000c0;
+
+       bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+       if (bcsr_io == NULL) {
+               printk(KERN_CRIT "Could not remap BCSR1\n");
+               return;
+       }
+
+       clrbits32(bcsr_io,BCSR1_RS232EN_1);
+       iounmap(bcsr_io);
+
+       setbits32(&immap->im_cpm.cp_pbpar, iobits);
+       clrbits32(&immap->im_cpm.cp_pbdir, iobits);
+       clrbits16(&immap->im_cpm.cp_pbodr, iobits);
+
+}
+
+static void setup_smc2_ioports(void)
+{
+       immap_t *immap = (immap_t *) IMAP_ADDR;
+       unsigned *bcsr_io;
+       unsigned int iobits = 0x00000c00;
+
+       bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+       if (bcsr_io == NULL) {
+               printk(KERN_CRIT "Could not remap BCSR1\n");
+               return;
+       }
+
+       clrbits32(bcsr_io,BCSR1_RS232EN_2);
+
+       iounmap(bcsr_io);
+
+#ifndef CONFIG_SERIAL_CPM_ALT_SMC2
+       setbits32(&immap->im_cpm.cp_pbpar, iobits);
+       clrbits32(&immap->im_cpm.cp_pbdir, iobits);
+       clrbits16(&immap->im_cpm.cp_pbodr, iobits);
+#else
+       setbits16(&immap->im_ioport.iop_papar, iobits);
+       clrbits16(&immap->im_ioport.iop_padir, iobits);
+       clrbits16(&immap->im_ioport.iop_paodr, iobits);
+#endif
+
+}
+
+static void __init mpc866ads_fixup_uart_pdata(struct platform_device *pdev,
+                                              int idx)
+{
+       bd_t *bd = (bd_t *) __res;
+       struct fs_uart_platform_info *pinfo;
+       int num = ARRAY_SIZE(mpc866_uart_pdata);
+
+       int id = fs_uart_id_smc2fsid(idx);
+
+       /* no need to alter anything if console */
+       if ((id <= num) && (!pdev->dev.platform_data)) {
+               pinfo = &mpc866_uart_pdata[id];
+               pinfo->uart_clk = bd->bi_intfreq;
+               pdev->dev.platform_data = pinfo;
+       }
+}
+
 static int mpc866ads_platform_notify(struct device *dev)
 {
        static const struct platform_notify_dev_map dev_map[] = {
@@ -243,6 +343,10 @@ static int mpc866ads_platform_notify(struct device *dev)
                        .bus_id = "fsl-cpm-scc",
                        .rtn = mpc866ads_fixup_scc_enet_pdata,
                },
+               {
+                       .bus_id = "fsl-cpm-smc:uart",
+                       .rtn = mpc866ads_fixup_uart_pdata
+               },
                {
                        .bus_id = NULL
                }
@@ -267,7 +371,42 @@ int __init mpc866ads_init(void)
 #endif
        ppc_sys_device_enable(MPC8xx_CPM_FEC1);
 
+/* Since either of the uarts could be used as console, they need to ready */
+#ifdef CONFIG_SERIAL_CPM_SMC1
+       ppc_sys_device_enable(MPC8xx_CPM_SMC1);
+       ppc_sys_device_setfunc(MPC8xx_CPM_SMC1, PPC_SYS_FUNC_UART);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SMC
+       ppc_sys_device_enable(MPC8xx_CPM_SMC2);
+       ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
+#endif
+
        return 0;
 }
 
+/*
+   To prevent confusion, console selection is gross:
+   by 0 assumed SMC1 and by 1 assumed SMC2
+ */
+struct platform_device* early_uart_get_pdev(int index)
+{
+       bd_t *bd = (bd_t *) __res;
+       struct fs_uart_platform_info *pinfo;
+
+       struct platform_device* pdev = NULL;
+       if(index) { /*assume SMC2 here*/
+               pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC2];
+               pinfo = &mpc866_uart_pdata[1];
+       } else { /*over SMC1*/
+               pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC1];
+               pinfo = &mpc866_uart_pdata[0];
+       }
+
+       pinfo->uart_clk = bd->bi_intfreq;
+       pdev->dev.platform_data = pinfo;
+       ppc_sys_fixup_mem_resource(pdev, IMAP_ADDR);
+       return NULL;
+}
+
 arch_initcall(mpc866ads_init);