summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorVitaly Bordug <vbordug@ru.mvista.com>2006-09-21 22:38:05 +0400
committerVitaly Bordug <vbordug@ru.mvista.com>2006-09-21 22:38:05 +0400
commitd3465c921f79cfef0a4a8ceeeef9a3721bbbb57d (patch)
tree73d602a02efd3f358990dcfa9231131e69318d3b /arch
parentfc8e50e349aa722d9f97ed9ba30e324ede8fa408 (diff)
downloadop-kernel-dev-d3465c921f79cfef0a4a8ceeeef9a3721bbbb57d.zip
op-kernel-dev-d3465c921f79cfef0a4a8ceeeef9a3721bbbb57d.tar.gz
POWERPC: overhaul with cpm2_map mechanism
Incorporating the new way of cpm2 immr access, introduced in the previous patch, into CPM2 peripheral devices (fs_enet and cpm_uart). Both ppc and powerpc approved working( real actions taken in powerpc only, ppc just has a wrapper to keep init stuff consistent). Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ads.c109
-rw-r--r--arch/powerpc/sysdev/cpm2_common.c90
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c7
-rw-r--r--arch/ppc/platforms/mpc8272ads_setup.c8
-rw-r--r--arch/ppc/platforms/mpc866ads_setup.c8
-rw-r--r--arch/ppc/platforms/mpc885ads_setup.c10
6 files changed, 170 insertions, 62 deletions
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index 7ebfe74..28070e7 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -33,6 +33,7 @@
#include "mpc85xx.h"
#ifdef CONFIG_CPM2
+#include <linux/fs_enet_pd.h>
#include <asm/cpm2.h>
#include <sysdev/cpm2_pic.h>
#include <asm/fs_pd.h>
@@ -146,70 +147,81 @@ void __init mpc85xx_ads_pic_init(void)
* Setup the architecture
*/
#ifdef CONFIG_CPM2
-static void init_fcc_ioports(void)
+void init_fcc_ioports(struct fs_platform_info *fpi)
{
- struct immap *immap;
- struct io_port *io;
+ struct io_port *io = cpm2_map(im_ioport);
+ int fcc_no = fs_get_fcc_index(fpi->fs_no);
+ int target;
u32 tempval;
- immap = cpm2_immr;
-
- io = &immap->im_ioport;
- /* FCC2/3 are on the ports B/C. */
- tempval = in_be32(&io->iop_pdirb);
- tempval &= ~PB2_DIRB0;
- tempval |= PB2_DIRB1;
- out_be32(&io->iop_pdirb, tempval);
-
- tempval = in_be32(&io->iop_psorb);
- tempval &= ~PB2_PSORB0;
- tempval |= PB2_PSORB1;
- out_be32(&io->iop_psorb, tempval);
-
- tempval = in_be32(&io->iop_pparb);
- tempval |= (PB2_DIRB0 | PB2_DIRB1);
- out_be32(&io->iop_pparb, tempval);
-
- tempval = in_be32(&io->iop_pdirb);
- tempval &= ~PB3_DIRB0;
- tempval |= PB3_DIRB1;
- out_be32(&io->iop_pdirb, tempval);
-
- tempval = in_be32(&io->iop_psorb);
- tempval &= ~PB3_PSORB0;
- tempval |= PB3_PSORB1;
- out_be32(&io->iop_psorb, tempval);
-
- tempval = in_be32(&io->iop_pparb);
- tempval |= (PB3_DIRB0 | PB3_DIRB1);
- out_be32(&io->iop_pparb, tempval);
-
- tempval = in_be32(&io->iop_pdirc);
- tempval |= PC3_DIRC1;
- out_be32(&io->iop_pdirc, tempval);
-
- tempval = in_be32(&io->iop_pparc);
- tempval |= PC3_DIRC1;
- out_be32(&io->iop_pparc, tempval);
+ switch(fcc_no) {
+ case 1:
+ tempval = in_be32(&io->iop_pdirb);
+ tempval &= ~PB2_DIRB0;
+ tempval |= PB2_DIRB1;
+ out_be32(&io->iop_pdirb, tempval);
+
+ tempval = in_be32(&io->iop_psorb);
+ tempval &= ~PB2_PSORB0;
+ tempval |= PB2_PSORB1;
+ out_be32(&io->iop_psorb, tempval);
+
+ tempval = in_be32(&io->iop_pparb);
+ tempval |= (PB2_DIRB0 | PB2_DIRB1);
+ out_be32(&io->iop_pparb, tempval);
+
+ target = CPM_CLK_FCC2;
+ break;
+ case 2:
+ tempval = in_be32(&io->iop_pdirb);
+ tempval &= ~PB3_DIRB0;
+ tempval |= PB3_DIRB1;
+ out_be32(&io->iop_pdirb, tempval);
+
+ tempval = in_be32(&io->iop_psorb);
+ tempval &= ~PB3_PSORB0;
+ tempval |= PB3_PSORB1;
+ out_be32(&io->iop_psorb, tempval);
+
+ tempval = in_be32(&io->iop_pparb);
+ tempval |= (PB3_DIRB0 | PB3_DIRB1);
+ out_be32(&io->iop_pparb, tempval);
+
+ tempval = in_be32(&io->iop_pdirc);
+ tempval |= PC3_DIRC1;
+ out_be32(&io->iop_pdirc, tempval);
+
+ tempval = in_be32(&io->iop_pparc);
+ tempval |= PC3_DIRC1;
+ out_be32(&io->iop_pparc, tempval);
+
+ target = CPM_CLK_FCC3;
+ break;
+ default:
+ printk(KERN_ERR "init_fcc_ioports: invalid FCC number\n");
+ return;
+ }
/* Port C has clocks...... */
tempval = in_be32(&io->iop_psorc);
- tempval &= ~(CLK_TRX);
+ tempval &= ~(PC_CLK(fpi->clk_rx - 8) | PC_CLK(fpi->clk_tx - 8));
out_be32(&io->iop_psorc, tempval);
tempval = in_be32(&io->iop_pdirc);
- tempval &= ~(CLK_TRX);
+ tempval &= ~(PC_CLK(fpi->clk_rx - 8) | PC_CLK(fpi->clk_tx - 8));
out_be32(&io->iop_pdirc, tempval);
tempval = in_be32(&io->iop_pparc);
- tempval |= (CLK_TRX);
+ tempval |= (PC_CLK(fpi->clk_rx - 8) | PC_CLK(fpi->clk_tx - 8));
out_be32(&io->iop_pparc, tempval);
+ cpm2_unmap(io);
+
/* Configure Serial Interface clock routing.
- * First, clear all FCC bits to zero,
+ * First, clear FCC bits to zero,
* then set the ones we want.
*/
- immap->im_cpmux.cmx_fcr &= ~(CPMUX_CLK_MASK);
- immap->im_cpmux.cmx_fcr |= CPMUX_CLK_ROUTE;
+ cpm2_clk_setup(target, fpi->clk_rx, CPM_CLK_RX);
+ cpm2_clk_setup(target, fpi->clk_tx, CPM_CLK_TX);
}
#endif
@@ -237,7 +249,6 @@ static void __init mpc85xx_ads_setup_arch(void)
#ifdef CONFIG_CPM2
cpm2_reset();
- init_fcc_ioports();
#endif
#ifdef CONFIG_PCI
diff --git a/arch/powerpc/sysdev/cpm2_common.c b/arch/powerpc/sysdev/cpm2_common.c
index 73376f9..ec26599 100644
--- a/arch/powerpc/sysdev/cpm2_common.c
+++ b/arch/powerpc/sysdev/cpm2_common.c
@@ -130,6 +130,96 @@ cpm2_fastbrg(uint brg, uint rate, int div16)
cpm2_unmap(bp);
}
+int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode)
+{
+ int ret = 0;
+ int shift;
+ int i, bits = 0;
+ cpmux_t *im_cpmux;
+ u32 *reg;
+ u32 mask = 7;
+ u8 clk_map [24][3] = {
+ {CPM_CLK_FCC1, CPM_BRG5, 0},
+ {CPM_CLK_FCC1, CPM_BRG6, 1},
+ {CPM_CLK_FCC1, CPM_BRG7, 2},
+ {CPM_CLK_FCC1, CPM_BRG8, 3},
+ {CPM_CLK_FCC1, CPM_CLK9, 4},
+ {CPM_CLK_FCC1, CPM_CLK10, 5},
+ {CPM_CLK_FCC1, CPM_CLK11, 6},
+ {CPM_CLK_FCC1, CPM_CLK12, 7},
+ {CPM_CLK_FCC2, CPM_BRG5, 0},
+ {CPM_CLK_FCC2, CPM_BRG6, 1},
+ {CPM_CLK_FCC2, CPM_BRG7, 2},
+ {CPM_CLK_FCC2, CPM_BRG8, 3},
+ {CPM_CLK_FCC2, CPM_CLK13, 4},
+ {CPM_CLK_FCC2, CPM_CLK14, 5},
+ {CPM_CLK_FCC2, CPM_CLK15, 6},
+ {CPM_CLK_FCC2, CPM_CLK16, 7},
+ {CPM_CLK_FCC3, CPM_BRG5, 0},
+ {CPM_CLK_FCC3, CPM_BRG6, 1},
+ {CPM_CLK_FCC3, CPM_BRG7, 2},
+ {CPM_CLK_FCC3, CPM_BRG8, 3},
+ {CPM_CLK_FCC3, CPM_CLK13, 4},
+ {CPM_CLK_FCC3, CPM_CLK14, 5},
+ {CPM_CLK_FCC3, CPM_CLK15, 6},
+ {CPM_CLK_FCC3, CPM_CLK16, 7}
+ };
+
+ im_cpmux = cpm2_map(im_cpmux);
+
+ switch (target) {
+ case CPM_CLK_SCC1:
+ reg = &im_cpmux->cmx_scr;
+ shift = 24;
+ case CPM_CLK_SCC2:
+ reg = &im_cpmux->cmx_scr;
+ shift = 16;
+ break;
+ case CPM_CLK_SCC3:
+ reg = &im_cpmux->cmx_scr;
+ shift = 8;
+ break;
+ case CPM_CLK_SCC4:
+ reg = &im_cpmux->cmx_scr;
+ shift = 0;
+ break;
+ case CPM_CLK_FCC1:
+ reg = &im_cpmux->cmx_fcr;
+ shift = 24;
+ break;
+ case CPM_CLK_FCC2:
+ reg = &im_cpmux->cmx_fcr;
+ shift = 16;
+ break;
+ case CPM_CLK_FCC3:
+ reg = &im_cpmux->cmx_fcr;
+ shift = 8;
+ break;
+ default:
+ printk(KERN_ERR "cpm2_clock_setup: invalid clock target\n");
+ return -EINVAL;
+ }
+
+ if (mode == CPM_CLK_RX)
+ shift +=3;
+
+ for (i=0; i<24; i++) {
+ if (clk_map[i][0] == target && clk_map[i][1] == clock) {
+ bits = clk_map[i][2];
+ break;
+ }
+ }
+ if (i == sizeof(clk_map)/3)
+ ret = -EINVAL;
+
+ bits <<= shift;
+ mask <<= shift;
+ out_be32(reg, (in_be32(reg) & ~mask) | bits);
+
+ cpm2_unmap(im_cpmux);
+ return ret;
+}
+
/*
* dpalloc / dpfree bits.
*/
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 0b8a03c..4e72bb9 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -36,6 +36,7 @@
#include <mm/mmu_decl.h>
#include <asm/cpm2.h>
+extern void init_fcc_ioports(struct fs_platform_info*);
static phys_addr_t immrbase = -1;
phys_addr_t get_immrbase(void)
@@ -630,6 +631,9 @@ static int __init fs_enet_of_init(void)
goto unreg;
}
+ fs_enet_data.clk_rx = *((u32 *) get_property(np, "rx-clock", NULL));
+ fs_enet_data.clk_tx = *((u32 *) get_property(np, "tx-clock", NULL));
+
if (strstr(model, "FCC")) {
int fcc_index = fs_get_fcc_index(*id);
@@ -646,6 +650,7 @@ static int __init fs_enet_of_init(void)
snprintf((char*)&bus_id[(*id)], BUS_ID_SIZE, "%x:%02x",
(u32)res.start, fs_enet_data.phy_addr);
fs_enet_data.bus_id = (char*)&bus_id[(*id)];
+ fs_enet_data.init_ioports = init_fcc_ioports;
}
of_node_put(phy);
@@ -717,6 +722,8 @@ static int __init cpm_uart_of_init(void)
cpm_uart_data.tx_buf_size = 32;
cpm_uart_data.rx_num_fifo = 4;
cpm_uart_data.rx_buf_size = 32;
+ cpm_uart_data.clk_rx = *((u32 *) get_property(np, "rx-clock", NULL));
+ cpm_uart_data.clk_tx = *((u32 *) get_property(np, "tx-clock", NULL));
ret =
platform_device_add_data(cpm_uart_dev, &cpm_uart_data,
diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/platforms/mpc8272ads_setup.c
index 2a35fe2..d5d36c3 100644
--- a/arch/ppc/platforms/mpc8272ads_setup.c
+++ b/arch/ppc/platforms/mpc8272ads_setup.c
@@ -103,7 +103,7 @@ static struct fs_platform_info mpc82xx_enet_pdata[] = {
},
};
-static void init_fcc1_ioports(void)
+static void init_fcc1_ioports(struct fs_platform_info*)
{
struct io_port *io;
u32 tempval;
@@ -144,7 +144,7 @@ static void init_fcc1_ioports(void)
iounmap(immap);
}
-static void init_fcc2_ioports(void)
+static void init_fcc2_ioports(struct fs_platform_info*)
{
cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
u32 *bcsr = ioremap(BCSR_ADDR+12, sizeof(u32));
@@ -229,7 +229,7 @@ static void mpc8272ads_fixup_uart_pdata(struct platform_device *pdev,
}
}
-static void init_scc1_uart_ioports(void)
+static void init_scc1_uart_ioports(struct fs_uart_platform_info*)
{
cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
@@ -246,7 +246,7 @@ static void init_scc1_uart_ioports(void)
iounmap(immap);
}
-static void init_scc4_uart_ioports(void)
+static void init_scc4_uart_ioports(struct fs_uart_platform_info*)
{
cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/platforms/mpc866ads_setup.c
index e12cece..5f130dc 100644
--- a/arch/ppc/platforms/mpc866ads_setup.c
+++ b/arch/ppc/platforms/mpc866ads_setup.c
@@ -137,7 +137,7 @@ void __init board_init(void)
iounmap(bcsr_io);
}
-static void setup_fec1_ioports(void)
+static void setup_fec1_ioports(struct fs_platform_info*)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
@@ -145,7 +145,7 @@ static void setup_fec1_ioports(void)
setbits16(&immap->im_ioport.iop_pddir, 0x1fff);
}
-static void setup_scc1_ioports(void)
+static void setup_scc1_ioports(struct fs_platform_info*)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
unsigned *bcsr_io;
@@ -194,7 +194,7 @@ static void setup_scc1_ioports(void)
}
-static void setup_smc1_ioports(void)
+static void setup_smc1_ioports(struct fs_uart_platform_info*)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
unsigned *bcsr_io;
@@ -216,7 +216,7 @@ static void setup_smc1_ioports(void)
}
-static void setup_smc2_ioports(void)
+static void setup_smc2_ioports(struct fs_uart_platform_info*)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
unsigned *bcsr_io;
diff --git a/arch/ppc/platforms/mpc885ads_setup.c b/arch/ppc/platforms/mpc885ads_setup.c
index 5dfa4e6..bf388ed 100644
--- a/arch/ppc/platforms/mpc885ads_setup.c
+++ b/arch/ppc/platforms/mpc885ads_setup.c
@@ -161,7 +161,7 @@ void __init board_init(void)
#endif
}
-static void setup_fec1_ioports(void)
+static void setup_fec1_ioports(struct fs_platform_info*)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
@@ -181,7 +181,7 @@ static void setup_fec1_ioports(void)
clrbits32(&immap->im_cpm.cp_cptr, 0x00000100);
}
-static void setup_fec2_ioports(void)
+static void setup_fec2_ioports(struct fs_platform_info*)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
@@ -193,7 +193,7 @@ static void setup_fec2_ioports(void)
clrbits32(&immap->im_cpm.cp_cptr, 0x00000080);
}
-static void setup_scc3_ioports(void)
+static void setup_scc3_ioports(struct fs_platform_info*)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
unsigned *bcsr_io;
@@ -315,7 +315,7 @@ static void __init mpc885ads_fixup_scc_enet_pdata(struct platform_device *pdev,
mpc885ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
}
-static void setup_smc1_ioports(void)
+static void setup_smc1_ioports(struct fs_uart_platform_info*)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
unsigned *bcsr_io;
@@ -335,7 +335,7 @@ static void setup_smc1_ioports(void)
clrbits16(&immap->im_cpm.cp_pbodr, iobits);
}
-static void setup_smc2_ioports(void)
+static void setup_smc2_ioports(struct fs_uart_platform_info*)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
unsigned *bcsr_io;
OpenPOWER on IntegriCloud