[PATCH] ppc32: Update board-specific code of the CPM UART users

This has the relevant updates/additions to the BSP code so that proper
platform_info struct well be passed to the CPM UART drivers. The changes
covered mpc866ads, mpc885ads and mpc8272ads.

Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/platforms/mpc866ads_setup.c
index ac8fcc6..6ce3b84 100644
--- a/arch/ppc/platforms/mpc866ads_setup.c
+++ b/arch/ppc/platforms/mpc866ads_setup.c
@@ -20,6 +20,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>
@@ -37,6 +38,11 @@
 
 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 +85,28 @@
 	.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 +120,12 @@
 		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 +139,8 @@
 	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 +265,74 @@
 	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[] = {
@@ -244,6 +345,10 @@
 			.rtn = mpc866ads_fixup_scc_enet_pdata,
 		},
 		{
+			.bus_id = "fsl-cpm-smc:uart",
+			.rtn = mpc866ads_fixup_uart_pdata
+		},
+		{
 			.bus_id = NULL
 		}
 	};
@@ -267,7 +372,42 @@
 #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_SMCer
+	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);