LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 5/6] [RFC] POWERPC cpm2: get rid of remapping the whole immr
From: Vitaly Bordug @ 2006-08-12  0:10 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20060812000655.6186.42738.stgit@localhost.localdomain>


The stuff below cleans up the code attempting to remap the whole cpm2_immr
early, as well as places happily assuming that fact. This is more like the 2.4
legacy stuff, and is at least confusing and unclear now.

To keep the world comfortable, a new mechanism is introduced: before accessing
specific immr register/register set, one needs to map it, using cpm2_map(<reg>),
for instance, access to CPM command register will look like
	volatile cpm_cpm2_t *cp = cpm2_map(im_cpm);
keeping the code clear, yet without "already defined somewhere" cpm2_immr.

So far, unmapping code is not implemented, but it's not a big deal to add it, 
if the whole idea makes sense.

Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
---

 arch/powerpc/sysdev/cpm2_common.c       |   19 +++--
 arch/powerpc/sysdev/cpm2_pic.c          |   28 +++----
 arch/powerpc/sysdev/cpm2_pic.h          |    2 
 arch/powerpc/sysdev/fsl_soc.c           |    2 
 drivers/serial/cpm_uart/cpm_uart_cpm2.c |  130 +++++++++++++++++++++----------
 drivers/serial/cpm_uart/cpm_uart_cpm2.h |    2 
 include/asm-powerpc/fs_pd.h             |   18 ++++
 include/asm-ppc/cpm2.h                  |    4 +
 include/asm-ppc/fs_pd.h                 |    4 +
 9 files changed, 145 insertions(+), 64 deletions(-)

diff --git a/arch/powerpc/sysdev/cpm2_common.c b/arch/powerpc/sysdev/cpm2_common.c
index 1161970..ea1a7bf 100644
--- a/arch/powerpc/sysdev/cpm2_common.c
+++ b/arch/powerpc/sysdev/cpm2_common.c
@@ -44,6 +44,7 @@ cpm_cpm2_t	*cpmp;		/* Pointer to comm pr
  * the communication processor devices.
  */
 cpm2_map_t *cpm2_immr;
+intctl_cpm2_t *cpm2_intctl;
 
 #define CPM_MAP_SIZE	(0x40000)	/* 256k - the PQ3 reserve this amount
 					   of space for CPM as it is larger
@@ -53,6 +54,7 @@ void
 cpm2_reset(void)
 {
 	cpm2_immr = (cpm2_map_t *)ioremap(CPM_MAP_ADDR, CPM_MAP_SIZE);
+	cpm2_intctl = cpm2_map(im_intctl);
 
 	/* Reclaim the DP memory for our use.
 	 */
@@ -87,14 +89,16 @@ cpm_setbrg(uint brg, uint rate)
 	/* This is good enough to get SMCs running.....
 	*/
 	if (brg < 4) {
-		bp = (uint *)&cpm2_immr->im_brgc1;
+		bp = cpm2_map_size(im_brgc1, 16);
 	}
 	else {
-		bp = (uint *)&cpm2_immr->im_brgc5;
+		bp = cpm2_map_size(im_brgc5, 16);
 		brg -= 4;
 	}
 	bp += brg;
 	*bp = ((BRG_UART_CLK / rate) << 1) | CPM_BRG_EN;
+
+	cpm2_unmap(bp);
 }
 
 /* This function is used to set high speed synchronous baud rate
@@ -106,16 +110,18 @@ cpm2_fastbrg(uint brg, uint rate, int di
 	volatile uint	*bp;
 
 	if (brg < 4) {
-		bp = (uint *)&cpm2_immr->im_brgc1;
+		bp = cpm2_map_size(im_brgc1, 16);
 	}
 	else {
-		bp = (uint *)&cpm2_immr->im_brgc5;
+		bp = cpm2_map_size(im_brgc5, 16);
 		brg -= 4;
 	}
 	bp += brg;
 	*bp = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
 	if (div16)
 		*bp |= CPM_BRG_DIV16;
+
+	cpm2_unmap(bp);
 }
 
 /*
@@ -126,11 +132,14 @@ static spinlock_t cpm_dpmem_lock;
  * until the memory subsystem goes up... */
 static rh_block_t cpm_boot_dpmem_rh_block[16];
 static rh_info_t cpm_dpmem_info;
+static u8* im_dprambase;
 
 static void cpm2_dpinit(void)
 {
 	spin_lock_init(&cpm_dpmem_lock);
 
+	im_dprambase = ioremap(CPM_MAP_ADDR, CPM_DATAONLY_BASE + CPM_DATAONLY_SIZE);
+
 	/* initialize the info header */
 	rh_init(&cpm_dpmem_info, 1,
 			sizeof(cpm_boot_dpmem_rh_block) /
@@ -199,6 +208,6 @@ EXPORT_SYMBOL(cpm_dpdump);
 
 void *cpm_dpram_addr(uint offset)
 {
-	return (void *)&cpm2_immr->im_dprambase[offset];
+	return (void *)(im_dprambase + offset);
 }
 EXPORT_SYMBOL(cpm_dpram_addr);
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c
index ec9df31..845a08b 100644
--- a/arch/powerpc/sysdev/cpm2_pic.c
+++ b/arch/powerpc/sysdev/cpm2_pic.c
@@ -76,7 +76,7 @@ static void cpm2_mask_irq(unsigned int i
 	bit = irq_to_siubit[irq_nr];
 	word = irq_to_siureg[irq_nr];
 
-	simr = &(cpm2_immr->im_intctl.ic_simrh);
+	simr = &(cpm2_intctl->ic_simrh);
 	ppc_cached_irq_mask[word] &= ~(1 << bit);
 	simr[word] = ppc_cached_irq_mask[word];
 }
@@ -91,7 +91,7 @@ static void cpm2_unmask_irq(unsigned int
 	bit = irq_to_siubit[irq_nr];
 	word = irq_to_siureg[irq_nr];
 
-	simr = &(cpm2_immr->im_intctl.ic_simrh);
+	simr = &(cpm2_intctl->ic_simrh);
 	ppc_cached_irq_mask[word] |= 1 << bit;
 	simr[word] = ppc_cached_irq_mask[word];
 }
@@ -106,8 +106,8 @@ static void cpm2_mask_and_ack(unsigned i
 	bit = irq_to_siubit[irq_nr];
 	word = irq_to_siureg[irq_nr];
 
-	simr = &(cpm2_immr->im_intctl.ic_simrh);
-	sipnr = &(cpm2_immr->im_intctl.ic_sipnrh);
+	simr = &(cpm2_intctl->ic_simrh);
+	sipnr = &(cpm2_intctl->ic_sipnrh);
 	ppc_cached_irq_mask[word] &= ~(1 << bit);
 	simr[word] = ppc_cached_irq_mask[word];
 	sipnr[word] = 1 << bit;
@@ -125,7 +125,7 @@ static void cpm2_end_irq(unsigned int ir
 		bit = irq_to_siubit[irq_nr];
 		word = irq_to_siureg[irq_nr];
 
-		simr = &(cpm2_immr->im_intctl.ic_simrh);
+		simr = &(cpm2_intctl->ic_simrh);
 		ppc_cached_irq_mask[word] |= 1 << bit;
 		simr[word] = ppc_cached_irq_mask[word];
 		/*
@@ -152,7 +152,7 @@ int cpm2_get_irq(struct pt_regs *regs)
 
         /* For CPM2, read the SIVEC register and shift the bits down
          * to get the irq number.         */
-        bits = cpm2_immr->im_intctl.ic_sivec;
+        bits = cpm2_intctl->ic_sivec;
         irq = bits >> 26;
 
 	if (irq == 0)
@@ -223,26 +223,26 @@ void cpm2_pic_init(struct device_node *n
 
 	/* Mask out everything */
 
-	cpm2_immr->im_intctl.ic_simrh = 0x00000000;
-	cpm2_immr->im_intctl.ic_simrl = 0x00000000;
+	cpm2_intctl->ic_simrh = 0x00000000;
+	cpm2_intctl->ic_simrl = 0x00000000;
 
 	wmb();
 
 	/* Ack everything */
-	cpm2_immr->im_intctl.ic_sipnrh = 0xffffffff;
-	cpm2_immr->im_intctl.ic_sipnrl = 0xffffffff;
+	cpm2_intctl->ic_sipnrh = 0xffffffff;
+	cpm2_intctl->ic_sipnrl = 0xffffffff;
 	wmb();
 
 	/* Dummy read of the vector */
-	i = cpm2_immr->im_intctl.ic_sivec;
+	i = cpm2_intctl->ic_sivec;
 	rmb();
 
 	/* Initialize the default interrupt mapping priorities,
 	 * in case the boot rom changed something on us.
 	 */
-	cpm2_immr->im_intctl.ic_sicr = 0;
-	cpm2_immr->im_intctl.ic_scprrh = 0x05309770;
-	cpm2_immr->im_intctl.ic_scprrl = 0x05309770;
+	cpm2_intctl->ic_sicr = 0;
+	cpm2_intctl->ic_scprrh = 0x05309770;
+	cpm2_intctl->ic_scprrl = 0x05309770;
 
 	/* create a legacy host */
 	if (node)
diff --git a/arch/powerpc/sysdev/cpm2_pic.h b/arch/powerpc/sysdev/cpm2_pic.h
index 436cca7..d63e45d 100644
--- a/arch/powerpc/sysdev/cpm2_pic.h
+++ b/arch/powerpc/sysdev/cpm2_pic.h
@@ -1,6 +1,8 @@
 #ifndef _PPC_KERNEL_CPM2_H
 #define _PPC_KERNEL_CPM2_H
 
+extern intctl_cpm2_t *cpm2_intctl;
+
 extern int cpm2_get_irq(struct pt_regs *regs);
 
 extern void cpm2_pic_init(struct device_node*);
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 7f4ed40..cff9bf7 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -622,7 +622,7 @@ static int __init fs_enet_of_init(void)
 		if (strstr(model, "FCC")) {
 			int fcc_index = fs_get_fcc_index(*id);
 
-			fs_enet_data.dpram_offset = (u32)cpm2_immr->im_dprambase;
+			fs_enet_data.dpram_offset = (u32)cpm_dpram_addr(0);
 			fs_enet_data.rx_ring = 32;
 			fs_enet_data.tx_ring = 32;
 			fs_enet_data.rx_copybreak = 240;
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index 02b9ef9..b691d3e 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -51,8 +51,9 @@ #include "cpm_uart.h"
 
 void cpm_line_cr_cmd(int line, int cmd)
 {
-	volatile cpm_cpm2_t *cp = cpmp;
 	ulong val;
+	volatile cpm_cpm2_t *cp = cpm2_map(im_cpm);
+
 
 	switch (line) {
 	case UART_SMC1:
@@ -85,11 +86,14 @@ void cpm_line_cr_cmd(int line, int cmd)
 	}
 	cp->cp_cpcr = val;
 	while (cp->cp_cpcr & CPM_CR_FLG) ;
+
+	cpm2_unmap(cp);
 }
 
 void smc1_lineif(struct uart_cpm_port *pinfo)
 {
-	volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+	volatile iop_cpm2_t *io = cpm2_map(im_ioport);
+	volatile cpmux_t *cpmux = cpm2_map(im_cpmux);
 
 	/* SMC1 is only on port D */
 	io->iop_ppard |= 0x00c00000;
@@ -98,13 +102,17 @@ void smc1_lineif(struct uart_cpm_port *p
 	io->iop_psord &= ~0x00c00000;
 
 	/* Wire BRG1 to SMC1 */
-	cpm2_immr->im_cpmux.cmx_smr &= 0x0f;
+	cpmux->cmx_smr &= 0x0f;
 	pinfo->brg = 1;
+
+	cpm2_unmap(cpmux);
+	cpm2_unmap(io);
 }
 
 void smc2_lineif(struct uart_cpm_port *pinfo)
 {
-	volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+	volatile iop_cpm2_t *io = cpm2_map(im_ioport);
+	volatile cpmux_t *cpmux = cpm2_map(im_cpmux);
 
 	/* SMC2 is only on port A */
 	io->iop_ppara |= 0x00c00000;
@@ -113,13 +121,17 @@ void smc2_lineif(struct uart_cpm_port *p
 	io->iop_psora &= ~0x00c00000;
 
 	/* Wire BRG2 to SMC2 */
-	cpm2_immr->im_cpmux.cmx_smr &= 0xf0;
+	cpmux->cmx_smr &= 0xf0;
 	pinfo->brg = 2;
+
+	cpm2_unmap(cpmux);
+	cpm2_unmap(io);
 }
 
 void scc1_lineif(struct uart_cpm_port *pinfo)
 {
-	volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+	volatile iop_cpm2_t *io = cpm2_map(im_ioport);
+	volatile cpmux_t *cpmux = cpm2_map(im_cpmux);
 
 	/* Use Port D for SCC1 instead of other functions.  */
 	io->iop_ppard |= 0x00000003;
@@ -129,9 +141,12 @@ void scc1_lineif(struct uart_cpm_port *p
 	io->iop_pdird |= 0x00000002;	/* Tx */
 
 	/* Wire BRG1 to SCC1 */
-	cpm2_immr->im_cpmux.cmx_scr &= 0x00ffffff;
-	cpm2_immr->im_cpmux.cmx_scr |= 0x00000000;
+	cpmux->cmx_scr &= 0x00ffffff;
+	cpmux->cmx_scr |= 0x00000000;
 	pinfo->brg = 1;
+
+	cpm2_unmap(cpmux);
+	cpm2_unmap(io);
 }
 
 void scc2_lineif(struct uart_cpm_port *pinfo)
@@ -144,43 +159,57 @@ void scc2_lineif(struct uart_cpm_port *p
 	 * be supported in a sane fashion.
 	 */
 #ifndef CONFIG_STX_GP3
-	volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+	volatile iop_cpm2_t *io = cpm2_map(im_ioport);
+	volatile cpmux_t *cpmux = cpm2_map(im_cpmux);
+
 	io->iop_pparb |= 0x008b0000;
 	io->iop_pdirb |= 0x00880000;
 	io->iop_psorb |= 0x00880000;
 	io->iop_pdirb &= ~0x00030000;
 	io->iop_psorb &= ~0x00030000;
 #endif
-	cpm2_immr->im_cpmux.cmx_scr &= 0xff00ffff;
-	cpm2_immr->im_cpmux.cmx_scr |= 0x00090000;
+	cpmux->cmx_scr &= 0xff00ffff;
+	cpmux->cmx_scr |= 0x00090000;
 	pinfo->brg = 2;
+
+	cpm2_unmap(cpmux);
+	cpm2_unmap(io);
 }
 
 void scc3_lineif(struct uart_cpm_port *pinfo)
 {
-	volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+	volatile iop_cpm2_t *io = cpm2_map(im_ioport);
+	volatile cpmux_t *cpmux = cpm2_map(im_cpmux);
+
 	io->iop_pparb |= 0x008b0000;
 	io->iop_pdirb |= 0x00880000;
 	io->iop_psorb |= 0x00880000;
 	io->iop_pdirb &= ~0x00030000;
 	io->iop_psorb &= ~0x00030000;
-	cpm2_immr->im_cpmux.cmx_scr &= 0xffff00ff;
-	cpm2_immr->im_cpmux.cmx_scr |= 0x00001200;
+	cpmux->cmx_scr &= 0xffff00ff;
+	cpmux->cmx_scr |= 0x00001200;
 	pinfo->brg = 3;
+
+	cpm2_unmap(cpmux);
+	cpm2_unmap(io);
 }
 
 void scc4_lineif(struct uart_cpm_port *pinfo)
 {
-	volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+	volatile iop_cpm2_t *io = cpm2_map(im_ioport);
+	volatile cpmux_t *cpmux = cpm2_map(im_cpmux);
 
 	io->iop_ppard |= 0x00000600;
 	io->iop_psord &= ~0x00000600;	/* Tx/Rx */
 	io->iop_pdird &= ~0x00000200;	/* Rx */
 	io->iop_pdird |= 0x00000400;	/* Tx */
 
-	cpm2_immr->im_cpmux.cmx_scr &= 0xffffff00;
-	cpm2_immr->im_cpmux.cmx_scr |= 0x0000001b;
+	cpmux->cmx_scr &= 0xffffff00;
+	cpmux->cmx_scr |= 0x0000001b;
 	pinfo->brg = 4;
+
+	cpm2_unmap(cpmux);
+	cpm2_unmap(io);
 }
 
 /*
@@ -255,16 +284,23 @@ void cpm_uart_freebuf(struct uart_cpm_po
 /* Setup any dynamic params in the uart desc */
 int cpm_uart_init_portdesc(void)
 {
+#if defined(CONFIG_SERIAL_CPM_SMC1) || defined(CONFIG_SERIAL_CPM_SMC2)
+	u32 addr;
+#endif
 	pr_debug("CPM uart[-]:init portdesc\n");
 
 	cpm_uart_nr = 0;
 #ifdef CONFIG_SERIAL_CPM_SMC1
-	cpm_uart_ports[UART_SMC1].smcp = (smc_t *) & cpm2_immr->im_smc[0];
-	cpm_uart_ports[UART_SMC1].smcup =
-	    (smc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SMC1];
-	*(u16 *)(&cpm2_immr->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
+	cpm_uart_ports[UART_SMC1].smcp = (smc_t *) cpm2_map(im_smc[0]);
 	cpm_uart_ports[UART_SMC1].port.mapbase =
-	    (unsigned long)&cpm2_immr->im_smc[0];
+	    (unsigned long)cpm_uart_ports[UART_SMC1].smcp;
+
+	cpm_uart_ports[UART_SMC1].smcup =
+	    (smc_uart_t *) cpm2_map_size(im_dprambase[PROFF_SMC1], PROFF_SMC_SIZE);
+	addr = (u16 *)cpm2_map_size(im_dprambase[PROFF_SMC1_BASE], 2);
+	*addr = PROFF_SMC1;
+	cpm2_unmap(addr);
+
 	cpm_uart_ports[UART_SMC1].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
 	cpm_uart_ports[UART_SMC1].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
 	cpm_uart_ports[UART_SMC1].port.uartclk = uart_clock();
@@ -272,12 +308,16 @@ #ifdef CONFIG_SERIAL_CPM_SMC1
 #endif
 
 #ifdef CONFIG_SERIAL_CPM_SMC2
-	cpm_uart_ports[UART_SMC2].smcp = (smc_t *) & cpm2_immr->im_smc[1];
-	cpm_uart_ports[UART_SMC2].smcup =
-	    (smc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SMC2];
-	*(u16 *)(&cpm2_immr->im_dprambase[PROFF_SMC2_BASE]) = PROFF_SMC2;
+	cpm_uart_ports[UART_SMC2].smcp = (smc_t *) cpm2_map(im_smc[1]);
 	cpm_uart_ports[UART_SMC2].port.mapbase =
-	    (unsigned long)&cpm2_immr->im_smc[1];
+	    (unsigned long)cpm_uart_ports[UART_SMC2].smcp;
+
+	cpm_uart_ports[UART_SMC2].smcup =
+	    (smc_uart_t *) cpm2_map_size(im_dprambase[PROFF_SMC2], PROFF_SMC_SIZE);
+	addr = (u16 *)cpm2_map_size(im_dprambase[PROFF_SMC2_BASE], 2);
+	*addr = PROFF_SMC2;
+	cpm2_unmap(addr);
+
 	cpm_uart_ports[UART_SMC2].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
 	cpm_uart_ports[UART_SMC2].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
 	cpm_uart_ports[UART_SMC2].port.uartclk = uart_clock();
@@ -285,11 +325,12 @@ #ifdef CONFIG_SERIAL_CPM_SMC2
 #endif
 
 #ifdef CONFIG_SERIAL_CPM_SCC1
-	cpm_uart_ports[UART_SCC1].sccp = (scc_t *) & cpm2_immr->im_scc[0];
-	cpm_uart_ports[UART_SCC1].sccup =
-	    (scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC1];
+	cpm_uart_ports[UART_SCC1].sccp = (scc_t *) cpm2_map(im_scc[0]);
 	cpm_uart_ports[UART_SCC1].port.mapbase =
-	    (unsigned long)&cpm2_immr->im_scc[0];
+	    (unsigned long)cpm_uart_ports[UART_SCC1].sccp;
+	cpm_uart_ports[UART_SCC1].sccup =
+	    (scc_uart_t *) cpm2_map_size(im_dprambase[PROFF_SCC1], PROFF_SCC_SIZE);
+
 	cpm_uart_ports[UART_SCC1].sccp->scc_sccm &=
 	    ~(UART_SCCM_TX | UART_SCCM_RX);
 	cpm_uart_ports[UART_SCC1].sccp->scc_gsmrl &=
@@ -299,11 +340,12 @@ #ifdef CONFIG_SERIAL_CPM_SCC1
 #endif
 
 #ifdef CONFIG_SERIAL_CPM_SCC2
-	cpm_uart_ports[UART_SCC2].sccp = (scc_t *) & cpm2_immr->im_scc[1];
-	cpm_uart_ports[UART_SCC2].sccup =
-	    (scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC2];
+	cpm_uart_ports[UART_SCC2].sccp = (scc_t *) cpm2_map(im_scc[1]);
 	cpm_uart_ports[UART_SCC2].port.mapbase =
-	    (unsigned long)&cpm2_immr->im_scc[1];
+	    (unsigned long)cpm_uart_ports[UART_SCC2].sccp;
+	cpm_uart_ports[UART_SCC2].sccup =
+	    (scc_uart_t *) cpm2_map_size(im_dprambase[PROFF_SCC2], PROFF_SCC_SIZE);
+
 	cpm_uart_ports[UART_SCC2].sccp->scc_sccm &=
 	    ~(UART_SCCM_TX | UART_SCCM_RX);
 	cpm_uart_ports[UART_SCC2].sccp->scc_gsmrl &=
@@ -313,11 +355,12 @@ #ifdef CONFIG_SERIAL_CPM_SCC2
 #endif
 
 #ifdef CONFIG_SERIAL_CPM_SCC3
-	cpm_uart_ports[UART_SCC3].sccp = (scc_t *) & cpm2_immr->im_scc[2];
-	cpm_uart_ports[UART_SCC3].sccup =
-	    (scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC3];
+	cpm_uart_ports[UART_SCC3].sccp = (scc_t *) cpm2_map(im_scc[2]);
 	cpm_uart_ports[UART_SCC3].port.mapbase =
-	    (unsigned long)&cpm2_immr->im_scc[2];
+	    (unsigned long)cpm_uart_ports[UART_SCC3].sccp;
+	cpm_uart_ports[UART_SCC3].sccup =
+	    (scc_uart_t *) cpm2_map_size(im_dprambase[PROFF_SCC3], PROFF_SCC_SIZE);
+
 	cpm_uart_ports[UART_SCC3].sccp->scc_sccm &=
 	    ~(UART_SCCM_TX | UART_SCCM_RX);
 	cpm_uart_ports[UART_SCC3].sccp->scc_gsmrl &=
@@ -327,11 +370,12 @@ #ifdef CONFIG_SERIAL_CPM_SCC3
 #endif
 
 #ifdef CONFIG_SERIAL_CPM_SCC4
-	cpm_uart_ports[UART_SCC4].sccp = (scc_t *) & cpm2_immr->im_scc[3];
-	cpm_uart_ports[UART_SCC4].sccup =
-	    (scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC4];
+	cpm_uart_ports[UART_SCC4].sccp = (scc_t *) cpm2_map(im_scc[3]);
 	cpm_uart_ports[UART_SCC4].port.mapbase =
-	    (unsigned long)&cpm2_immr->im_scc[3];
+	    (unsigned long)cpm_uart_ports[UART_SCC4].sccp;
+	cpm_uart_ports[UART_SCC4].sccup =
+	    (scc_uart_t *) cpm2_map_size(im_dprambase[PROFF_SCC4], PROFF_SCC_SIZE);
+
 	cpm_uart_ports[UART_SCC4].sccp->scc_sccm &=
 	    ~(UART_SCCM_TX | UART_SCCM_RX);
 	cpm_uart_ports[UART_SCC4].sccp->scc_gsmrl &=
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.h b/drivers/serial/cpm_uart/cpm_uart_cpm2.h
index 4793fec..a663300 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.h
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.h
@@ -40,6 +40,6 @@ static inline void cpm_set_smc_fcr(volat
 	up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
 }
 
-#define DPRAM_BASE	((unsigned char *)&cpm2_immr->im_dprambase[0])
+#define DPRAM_BASE	((unsigned char *)cpm_dpram_addr(0))
 
 #endif
diff --git a/include/asm-powerpc/fs_pd.h b/include/asm-powerpc/fs_pd.h
index d530f68..3d0e819 100644
--- a/include/asm-powerpc/fs_pd.h
+++ b/include/asm-powerpc/fs_pd.h
@@ -11,6 +11,7 @@
 
 #ifndef FS_PD_H
 #define FS_PD_H
+#include <asm/cpm2.h>
 #include <sysdev/fsl_soc.h>
 #include <asm/time.h>
 
@@ -24,4 +25,21 @@ static inline int uart_clock(void)
         return ppc_proc_freq;
 }
 
+#define cpm2_map(member)						\
+({									\
+	u32 offset = offsetof(cpm2_map_t, member);			\
+	void *addr = ioremap (CPM_MAP_ADDR + offset,			\
+			      sizeof( ((cpm2_map_t*)0)->member));	\
+	addr;								\
+})
+
+#define cpm2_map_size(member, size)					\
+({									\
+	u32 offset = offsetof(cpm2_map_t, member);			\
+	void *addr = ioremap (CPM_MAP_ADDR + offset, size);		\
+	addr;								\
+})
+
+#define cpm2_unmap(addr)	iounmap(addr)
+
 #endif
diff --git a/include/asm-ppc/cpm2.h b/include/asm-ppc/cpm2.h
index 876974e..bd6623a 100644
--- a/include/asm-ppc/cpm2.h
+++ b/include/asm-ppc/cpm2.h
@@ -177,6 +177,10 @@ #define PROFF_RAND		((uint)0x8af8)
 #define PROFF_I2C_BASE		((uint)0x8afc)
 #define PROFF_IDMA4_BASE	((uint)0x8afe)
 
+#define PROFF_SCC_SIZE		((uint)0x100)
+#define PROFF_FCC_SIZE		((uint)0x100)
+#define PROFF_SMC_SIZE		((uint)64)
+
 /* The SMCs are relocated to any of the first eight DPRAM pages.
  * We will fix these at the first locations of DPRAM, until we
  * get some microcode patches :-).
diff --git a/include/asm-ppc/fs_pd.h b/include/asm-ppc/fs_pd.h
index eed7778..8691327 100644
--- a/include/asm-ppc/fs_pd.h
+++ b/include/asm-ppc/fs_pd.h
@@ -29,4 +29,8 @@ static inline int uart_clock(void)
 	return (((bd_t *) __res)->bi_intfreq);
 }
 
+#define cpm2_map(member)	(&cpm2_immr->member)
+#define cpm2_map_size(member, size)	(&cpm2_immr->member)
+#define cpm2_unmap(addr)        do {} while(0)
+
 #endif

^ permalink raw reply related

* [PATCH 6/6] [RFC] POWERPC: generic CPM2 peripherals rehaul with cpm2_map mechanism
From: Vitaly Bordug @ 2006-08-12  0:10 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20060812000655.6186.42738.stgit@localhost.localdomain>


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>
---

 arch/powerpc/platforms/85xx/mpc85xx_ads.c |  109 ++++++++++++++++-------------
 arch/powerpc/sysdev/cpm2_common.c         |   90 ++++++++++++++++++++++++
 arch/powerpc/sysdev/fsl_soc.c             |   10 +++
 arch/ppc/platforms/mpc8272ads_setup.c     |    8 +-
 arch/ppc/platforms/mpc866ads_setup.c      |    8 +-
 arch/ppc/platforms/mpc885ads_setup.c      |   10 +--
 drivers/net/fs_enet/fs_enet-main.c        |    2 -
 drivers/serial/cpm_uart/cpm_uart_core.c   |    4 +
 include/asm-ppc/cpm2.h                    |   53 ++++++++++++++
 include/linux/fs_enet_pd.h                |   10 ++-
 include/linux/fs_uart_pd.h                |    4 +
 11 files changed, 239 insertions(+), 69 deletions(-)

diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index 974e035..52be63a 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -292,71 +292,84 @@ #endif
 /*
  * Setup the architecture
  */
-static void init_fcc_ioports(void)
+#ifdef CONFIG_CPM2
+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
 
 static void __init mpc85xx_ads_setup_arch(void)
 {
diff --git a/arch/powerpc/sysdev/cpm2_common.c b/arch/powerpc/sysdev/cpm2_common.c
index ea1a7bf..8558c63 100644
--- a/arch/powerpc/sysdev/cpm2_common.c
+++ b/arch/powerpc/sysdev/cpm2_common.c
@@ -124,6 +124,96 @@ cpm2_fastbrg(uint brg, uint rate, int di
 	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 cff9bf7..7878613 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -34,7 +34,11 @@ #include <asm/time.h>
 #include <asm/prom.h>
 #include <sysdev/fsl_soc.h>
 #include <mm/mmu_decl.h>
+#ifdef CONFIG_CPM2
+#include <asm/cpm2.h>
+#endif
 
+extern void init_fcc_ioports(struct fs_platform_info*);
 static phys_addr_t immrbase = -1;
 
 phys_addr_t get_immrbase(void)
@@ -619,6 +623,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);
 
@@ -635,6 +642,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);
@@ -706,6 +714,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_e
 	},
 };
 
-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(
 	}
 }
 
-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 @@ #endif
 	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 @@ #endif
 #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_e
 	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;
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index df62506..f358ee6 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -971,7 +971,7 @@ static struct net_device *fs_init_instan
 	dev_set_drvdata(dev, ndev);
 	fep->fpi = fpi;
 	if (fpi->init_ioports)
-		fpi->init_ioports();
+		fpi->init_ioports((struct fs_platform_info *)fpi);
 
 #ifdef CONFIG_FS_ENET_HAS_FEC
 	if (fs_get_fec_index(fpi->fs_no) >= 0)
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index dfa06b6..24613a6 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -1180,7 +1180,7 @@ static int __init cpm_uart_console_setup
 		pdata = pdev->dev.platform_data;
 		if (pdata)
 			if (pdata->init_ioports)
-    	                	pdata->init_ioports();
+    	                	pdata->init_ioports(pdata);
 
 		cpm_uart_drv_get_platform_data(pdev, 1);
 	}
@@ -1269,7 +1269,7 @@ static int cpm_uart_drv_probe(struct dev
 		return ret;
 
 	if (pdata->init_ioports)
-                pdata->init_ioports();
+                pdata->init_ioports(pdata);
 
 	ret = uart_add_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port);
 
diff --git a/include/asm-ppc/cpm2.h b/include/asm-ppc/cpm2.h
index bd6623a..220cc2d 100644
--- a/include/asm-ppc/cpm2.h
+++ b/include/asm-ppc/cpm2.h
@@ -1196,5 +1196,58 @@ #define FCC1_MEM_OFFSET FCC_MEM_OFFSET(0
 #define FCC2_MEM_OFFSET FCC_MEM_OFFSET(1)
 #define FCC3_MEM_OFFSET FCC_MEM_OFFSET(2)
 
+/* Clocks and GRG's */
+
+enum cpm_clk_dir {
+	CPM_CLK_RX,
+	CPM_CLK_TX,
+	CPM_CLK_RTX
+};
+
+enum cpm_clk_target {
+	CPM_CLK_SCC1,
+	CPM_CLK_SCC2,
+	CPM_CLK_SCC3,
+	CPM_CLK_SCC4,
+	CPM_CLK_FCC1,
+	CPM_CLK_FCC2,
+	CPM_CLK_FCC3
+};
+
+enum cpm_clk {
+	CPM_CLK_NONE = 0,
+	CPM_BRG1,	/* Baud Rate Generator  1 */
+	CPM_BRG2,	/* Baud Rate Generator  2 */
+	CPM_BRG3,	/* Baud Rate Generator  3 */
+	CPM_BRG4,	/* Baud Rate Generator  4 */
+	CPM_BRG5,	/* Baud Rate Generator  5 */
+	CPM_BRG6,	/* Baud Rate Generator  6 */
+	CPM_BRG7,	/* Baud Rate Generator  7 */
+	CPM_BRG8,	/* Baud Rate Generator  8 */
+	CPM_CLK1,	/* Clock  1 */
+	CPM_CLK2,	/* Clock  2 */
+	CPM_CLK3,	/* Clock  3 */
+	CPM_CLK4,	/* Clock  4 */
+	CPM_CLK5,	/* Clock  5 */
+	CPM_CLK6,	/* Clock  6 */
+	CPM_CLK7,	/* Clock  7 */
+	CPM_CLK8,	/* Clock  8 */
+	CPM_CLK9,	/* Clock  9 */
+	CPM_CLK10,	/* Clock 10 */
+	CPM_CLK11,	/* Clock 11 */
+	CPM_CLK12,	/* Clock 12 */
+	CPM_CLK13,	/* Clock 13 */
+	CPM_CLK14,	/* Clock 14 */
+	CPM_CLK15,	/* Clock 15 */
+	CPM_CLK16,	/* Clock 16 */
+	CPM_CLK17,	/* Clock 17 */
+	CPM_CLK18,	/* Clock 18 */
+	CPM_CLK19,	/* Clock 19 */
+	CPM_CLK20,	/* Clock 20 */
+	CPM_CLK_DUMMY
+};
+
+extern int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode);
+
 #endif /* __CPM2__ */
 #endif /* __KERNEL__ */
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
index 74ed35a..9322235 100644
--- a/include/linux/fs_enet_pd.h
+++ b/include/linux/fs_enet_pd.h
@@ -87,18 +87,20 @@ struct fs_mii_bb_platform_info {
 };
 
 struct fs_platform_info {
-	
-	void(*init_ioports)(void);
+
+	void(*init_ioports)(struct fs_platform_info *);
 	/* device specific information */
 	int fs_no;		/* controller index            */
 
 	u32 cp_page;		/* CPM page */
 	u32 cp_block;		/* CPM sblock */
-	
+
 	u32 clk_trx;		/* some stuff for pins & mux configuration*/
+	u32 clk_rx;
+	u32 clk_tx;
 	u32 clk_route;
 	u32 clk_mask;
-	
+
 	u32 mem_offset;
 	u32 dpram_offset;
 	u32 fcc_regs_c;
diff --git a/include/linux/fs_uart_pd.h b/include/linux/fs_uart_pd.h
index f597512..a99a020 100644
--- a/include/linux/fs_uart_pd.h
+++ b/include/linux/fs_uart_pd.h
@@ -46,7 +46,7 @@ static inline int fs_uart_id_fsid2smc(in
 }
 
 struct fs_uart_platform_info {
-        void(*init_ioports)(void);
+        void(*init_ioports)(struct fs_uart_platform_info *);
 	/* device specific information */
 	int fs_no;		/* controller index */
 	u32 uart_clk;
@@ -55,6 +55,8 @@ struct fs_uart_platform_info {
 	u8 rx_num_fifo;
 	u8 rx_buf_size;
 	u8 brg;
+	u8 clk_rx;
+	u8 clk_tx;
 };
 
 #endif

^ permalink raw reply related

* [PATCH 3/6] POWERPC: move the generic cpm2 stuff to the powerpc
From: Vitaly Bordug @ 2006-08-12  0:10 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20060812000655.6186.42738.stgit@localhost.localdomain>


This moves the cpm2 common code and PIC stuff to the powerpc. Most of the files
were just copied from ppc/, with minor tuning to make it compile, and, subsequently, work.

Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
---

 arch/powerpc/lib/Makefile         |    5 +
 arch/powerpc/sysdev/Makefile      |    7 +
 arch/powerpc/sysdev/cpm2_common.c |  204 +++++++++++++++++++++++++++++
 arch/powerpc/sysdev/cpm2_pic.c    |  256 +++++++++++++++++++++++++++++++++++++
 arch/powerpc/sysdev/cpm2_pic.h    |    8 +
 include/asm-ppc/cpm2.h            |    6 +
 6 files changed, 484 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 336dd19..460cea0 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -20,3 +20,8 @@ ifeq ($(CONFIG_PPC64),y)
 obj-$(CONFIG_SMP)	+= locks.o
 obj-$(CONFIG_DEBUG_KERNEL) += sstep.o
 endif
+
+# Temporary hack until we have migrated to asm-powerpc
+ifeq ($(ARCH),powerpc)
+obj-$(CONFIG_CPM2)	+= rheap.o
+endif
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index cebfae2..0f44f06 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -16,4 +16,9 @@ obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pc
 
 ifeq ($(CONFIG_PPC_MERGE),y)
 obj-$(CONFIG_PPC_I8259)		+= i8259.o
- endif
+endif
+
+# Temporary hack until we have migrated to asm-powerpc
+ifeq ($(ARCH),powerpc)
+obj-$(CONFIG_CPM2)		+= cpm2_common.o cpm2_pic.o
+endif
diff --git a/arch/powerpc/sysdev/cpm2_common.c b/arch/powerpc/sysdev/cpm2_common.c
new file mode 100644
index 0000000..1161970
--- /dev/null
+++ b/arch/powerpc/sysdev/cpm2_common.c
@@ -0,0 +1,204 @@
+/*
+ * General Purpose functions for the global management of the
+ * 8260 Communication Processor Module.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
+ *	2.3.99 Updates
+ * 
+ * 2006 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ * 	Merged to arch/powerpc from arch/ppc/syslib/cpm2_common.c 
+ *
+ * In addition to the individual control of the communication
+ * channels, there are a few functions that globally affect the
+ * communication processor.
+ *
+ * Buffer descriptors must be allocated from the dual ported memory
+ * space.  The allocator for that is here.  When the communication
+ * process is reset, we reclaim the memory available.  There is
+ * currently no deallocator for this memory.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mpc8260.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/cpm2.h>
+#include <asm/rheap.h>
+#include <asm/fs_pd.h>
+
+#include <sysdev/fsl_soc.h>
+
+static void cpm2_dpinit(void);
+cpm_cpm2_t	*cpmp;		/* Pointer to comm processor space */
+
+/* We allocate this here because it is used almost exclusively for
+ * the communication processor devices.
+ */
+cpm2_map_t *cpm2_immr;
+
+#define CPM_MAP_SIZE	(0x40000)	/* 256k - the PQ3 reserve this amount
+					   of space for CPM as it is larger
+					   than on PQ2 */
+
+void
+cpm2_reset(void)
+{
+	cpm2_immr = (cpm2_map_t *)ioremap(CPM_MAP_ADDR, CPM_MAP_SIZE);
+
+	/* Reclaim the DP memory for our use.
+	 */
+	cpm2_dpinit();
+
+	/* Tell everyone where the comm processor resides.
+	 */
+	cpmp = &cpm2_immr->im_cpm;
+}
+
+/* Set a baud rate generator.  This needs lots of work.  There are
+ * eight BRGs, which can be connected to the CPM channels or output
+ * as clocks.  The BRGs are in two different block of internal
+ * memory mapped space.
+ * The baud rate clock is the system clock divided by something.
+ * It was set up long ago during the initial boot phase and is
+ * is given to us.
+ * Baud rate clocks are zero-based in the driver code (as that maps
+ * to port numbers).  Documentation uses 1-based numbering.
+ */
+#define BRG_INT_CLK	(get_brgfreq())
+#define BRG_UART_CLK	(BRG_INT_CLK/16)
+
+/* This function is used by UARTS, or anything else that uses a 16x
+ * oversampled clock.
+ */
+void
+cpm_setbrg(uint brg, uint rate)
+{
+	volatile uint	*bp;
+
+	/* This is good enough to get SMCs running.....
+	*/
+	if (brg < 4) {
+		bp = (uint *)&cpm2_immr->im_brgc1;
+	}
+	else {
+		bp = (uint *)&cpm2_immr->im_brgc5;
+		brg -= 4;
+	}
+	bp += brg;
+	*bp = ((BRG_UART_CLK / rate) << 1) | CPM_BRG_EN;
+}
+
+/* This function is used to set high speed synchronous baud rate
+ * clocks.
+ */
+void
+cpm2_fastbrg(uint brg, uint rate, int div16)
+{
+	volatile uint	*bp;
+
+	if (brg < 4) {
+		bp = (uint *)&cpm2_immr->im_brgc1;
+	}
+	else {
+		bp = (uint *)&cpm2_immr->im_brgc5;
+		brg -= 4;
+	}
+	bp += brg;
+	*bp = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
+	if (div16)
+		*bp |= CPM_BRG_DIV16;
+}
+
+/*
+ * dpalloc / dpfree bits.
+ */
+static spinlock_t cpm_dpmem_lock;
+/* 16 blocks should be enough to satisfy all requests
+ * until the memory subsystem goes up... */
+static rh_block_t cpm_boot_dpmem_rh_block[16];
+static rh_info_t cpm_dpmem_info;
+
+static void cpm2_dpinit(void)
+{
+	spin_lock_init(&cpm_dpmem_lock);
+
+	/* initialize the info header */
+	rh_init(&cpm_dpmem_info, 1,
+			sizeof(cpm_boot_dpmem_rh_block) /
+			sizeof(cpm_boot_dpmem_rh_block[0]),
+			cpm_boot_dpmem_rh_block);
+
+	/* Attach the usable dpmem area */
+	/* XXX: This is actually crap. CPM_DATAONLY_BASE and
+	 * CPM_DATAONLY_SIZE is only a subset of the available dpram. It
+	 * varies with the processor and the microcode patches activated.
+	 * But the following should be at least safe.
+	 */
+	rh_attach_region(&cpm_dpmem_info, (void *)CPM_DATAONLY_BASE,
+			CPM_DATAONLY_SIZE);
+}
+
+/* This function returns an index into the DPRAM area.
+ */
+uint cpm_dpalloc(uint size, uint align)
+{
+	void *start;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cpm_dpmem_lock, flags);
+	cpm_dpmem_info.alignment = align;
+	start = rh_alloc(&cpm_dpmem_info, size, "commproc");
+	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+
+	return (uint)start;
+}
+EXPORT_SYMBOL(cpm_dpalloc);
+
+int cpm_dpfree(uint offset)
+{
+	int ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cpm_dpmem_lock, flags);
+	ret = rh_free(&cpm_dpmem_info, (void *)offset);
+	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(cpm_dpfree);
+
+/* not sure if this is ever needed */
+uint cpm_dpalloc_fixed(uint offset, uint size, uint align)
+{
+	void *start;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cpm_dpmem_lock, flags);
+	cpm_dpmem_info.alignment = align;
+	start = rh_alloc_fixed(&cpm_dpmem_info, (void *)offset, size, "commproc");
+	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+
+	return (uint)start;
+}
+EXPORT_SYMBOL(cpm_dpalloc_fixed);
+
+void cpm_dpdump(void)
+{
+	rh_dump(&cpm_dpmem_info);
+}
+EXPORT_SYMBOL(cpm_dpdump);
+
+void *cpm_dpram_addr(uint offset)
+{
+	return (void *)&cpm2_immr->im_dprambase[offset];
+}
+EXPORT_SYMBOL(cpm_dpram_addr);
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c
new file mode 100644
index 0000000..ec9df31
--- /dev/null
+++ b/arch/powerpc/sysdev/cpm2_pic.c
@@ -0,0 +1,256 @@
+/*
+ * Platform information definitions.
+ * 
+ * Copied from arch/ppc/syslib/cpm2_pic.c with minor subsequent updates
+ * to make in work in arch/powerpc/. Original (c) belongs to Dan Malek AFAIK. 
+ * 
+ * 2006 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+         
+/* The CPM2 internal interrupt controller.  It is usually
+ * the only interrupt controller.
+ * There are two 32-bit registers (high/low) for up to 64
+ * possible interrupts.
+ *
+ * Now, the fun starts.....Interrupt Numbers DO NOT MAP
+ * in a simple arithmetic fashion to mask or pending registers.
+ * That is, interrupt 4 does not map to bit position 4.
+ * We create two tables, indexed by vector number, to indicate
+ * which register to use and which bit in the register to use.
+ */
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/irq.h>
+
+#include <asm/immap_cpm2.h>
+#include <asm/mpc8260.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+
+#include "cpm2_pic.h"
+
+static struct device_node *cpm2_pic_node;
+static struct irq_host *cpm2_pic_host;
+#define NR_MASK_WORDS   ((NR_IRQS + 31) / 32)
+static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
+
+static	u_char	irq_to_siureg[] = {
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* bit numbers do not match the docs, these are precomputed so the bit for
+ * a given irq is (1 << irq_to_siubit[irq]) */
+static	u_char	irq_to_siubit[] = {
+	 0, 15, 14, 13, 12, 11, 10,  9,
+	 8,  7,  6,  5,  4,  3,  2,  1,
+	 2,  1,  0, 14, 13, 12, 11, 10,
+	 9,  8,  7,  6,  5,  4,  3,  0,
+	31, 30, 29, 28, 27, 26, 25, 24,
+	23, 22, 21, 20, 19, 18, 17, 16,
+	16, 17, 18, 19, 20, 21, 22, 23,
+	24, 25, 26, 27, 28, 29, 30, 31,
+};
+
+static void cpm2_mask_irq(unsigned int irq_nr)
+{
+	int	bit, word;
+	volatile uint	*simr;
+
+	irq_nr -= CPM_IRQ_OFFSET;
+
+	bit = irq_to_siubit[irq_nr];
+	word = irq_to_siureg[irq_nr];
+
+	simr = &(cpm2_immr->im_intctl.ic_simrh);
+	ppc_cached_irq_mask[word] &= ~(1 << bit);
+	simr[word] = ppc_cached_irq_mask[word];
+}
+
+static void cpm2_unmask_irq(unsigned int irq_nr)
+{
+	int	bit, word;
+	volatile uint	*simr;
+
+	irq_nr -= CPM_IRQ_OFFSET;
+
+	bit = irq_to_siubit[irq_nr];
+	word = irq_to_siureg[irq_nr];
+
+	simr = &(cpm2_immr->im_intctl.ic_simrh);
+	ppc_cached_irq_mask[word] |= 1 << bit;
+	simr[word] = ppc_cached_irq_mask[word];
+}
+
+static void cpm2_mask_and_ack(unsigned int irq_nr)
+{
+	int	bit, word;
+	volatile uint	*simr, *sipnr;
+
+	irq_nr -= CPM_IRQ_OFFSET;
+
+	bit = irq_to_siubit[irq_nr];
+	word = irq_to_siureg[irq_nr];
+
+	simr = &(cpm2_immr->im_intctl.ic_simrh);
+	sipnr = &(cpm2_immr->im_intctl.ic_sipnrh);
+	ppc_cached_irq_mask[word] &= ~(1 << bit);
+	simr[word] = ppc_cached_irq_mask[word];
+	sipnr[word] = 1 << bit;
+}
+
+static void cpm2_end_irq(unsigned int irq_nr)
+{
+	int	bit, word;
+	volatile uint	*simr;
+
+	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
+			&& irq_desc[irq_nr].action) {
+
+		irq_nr -= CPM_IRQ_OFFSET;
+		bit = irq_to_siubit[irq_nr];
+		word = irq_to_siureg[irq_nr];
+
+		simr = &(cpm2_immr->im_intctl.ic_simrh);
+		ppc_cached_irq_mask[word] |= 1 << bit;
+		simr[word] = ppc_cached_irq_mask[word];
+		/*
+		 * Work around large numbers of spurious IRQs on PowerPC 82xx
+		 * systems.
+		 */
+		mb();
+	}
+}
+
+static struct irq_chip cpm2_pic = {
+	.typename = " CPM2 SIU ",
+	.enable = cpm2_unmask_irq,
+	.disable = cpm2_mask_irq,
+	.unmask = cpm2_unmask_irq,
+	.mask_ack = cpm2_mask_and_ack,
+	.end = cpm2_end_irq,
+};
+
+int cpm2_get_irq(struct pt_regs *regs)
+{
+	int irq;
+        unsigned long bits;
+
+        /* For CPM2, read the SIVEC register and shift the bits down
+         * to get the irq number.         */
+        bits = cpm2_immr->im_intctl.ic_sivec;
+        irq = bits >> 26;
+
+	if (irq == 0)
+		return(-1);
+	return irq+CPM_IRQ_OFFSET;
+}
+
+static int cpm2_pic_host_match(struct irq_host *h, struct device_node *node)
+{
+	return cpm2_pic_node == NULL || cpm2_pic_node == node;
+}
+
+static int cpm2_pic_host_map(struct irq_host *h, unsigned int virq,
+			  irq_hw_number_t hw)
+{
+	pr_debug("cpm2_pic_host_map(%d, 0x%lx)\n", virq, hw);
+
+	get_irq_desc(virq)->status |= IRQ_LEVEL;
+	set_irq_chip_and_handler(virq, &cpm2_pic, handle_level_irq);
+	return 0;
+}
+
+static void cpm2_host_unmap(struct irq_host *h, unsigned int virq)
+{
+	/* Make sure irq is masked in hardware */
+	cpm2_mask_irq(virq);
+
+	/* remove chip and handler */
+	set_irq_chip_and_handler(virq, NULL, NULL);
+}
+
+static int cpm2_pic_host_xlate(struct irq_host *h, struct device_node *ct,
+			    u32 *intspec, unsigned int intsize,
+			    irq_hw_number_t *out_hwirq, unsigned int *out_flags)
+{
+	static unsigned char map_cpm2_senses[4] = {
+		IRQ_TYPE_LEVEL_LOW,
+		IRQ_TYPE_LEVEL_HIGH,
+		IRQ_TYPE_EDGE_FALLING,
+		IRQ_TYPE_EDGE_RISING,
+	};
+
+	*out_hwirq = intspec[0];
+	if (intsize > 1 && intspec[1] < 4)
+		*out_flags = map_cpm2_senses[intspec[1]];
+	else
+		*out_flags = IRQ_TYPE_NONE;
+
+	return 0;
+}
+
+
+static struct irq_host_ops cpm2_pic_host_ops = {
+	.match = cpm2_pic_host_match,
+	.map = cpm2_pic_host_map,
+	.unmap = cpm2_host_unmap,
+	.xlate = cpm2_pic_host_xlate,
+};
+
+
+void cpm2_pic_init(struct device_node *node)
+{
+	int i;
+
+	/* Clear the CPM IRQ controller, in case it has any bits set
+	 * from the bootloader
+	 */
+
+	/* Mask out everything */
+
+	cpm2_immr->im_intctl.ic_simrh = 0x00000000;
+	cpm2_immr->im_intctl.ic_simrl = 0x00000000;
+
+	wmb();
+
+	/* Ack everything */
+	cpm2_immr->im_intctl.ic_sipnrh = 0xffffffff;
+	cpm2_immr->im_intctl.ic_sipnrl = 0xffffffff;
+	wmb();
+
+	/* Dummy read of the vector */
+	i = cpm2_immr->im_intctl.ic_sivec;
+	rmb();
+
+	/* Initialize the default interrupt mapping priorities,
+	 * in case the boot rom changed something on us.
+	 */
+	cpm2_immr->im_intctl.ic_sicr = 0;
+	cpm2_immr->im_intctl.ic_scprrh = 0x05309770;
+	cpm2_immr->im_intctl.ic_scprrl = 0x05309770;
+
+	/* create a legacy host */
+	if (node)
+		cpm2_pic_node = of_node_get(node);
+
+	cpm2_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 64, &cpm2_pic_host_ops, 64);
+	if (cpm2_pic_host == NULL) {
+		printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");
+		return;
+	}
+}
diff --git a/arch/powerpc/sysdev/cpm2_pic.h b/arch/powerpc/sysdev/cpm2_pic.h
new file mode 100644
index 0000000..436cca7
--- /dev/null
+++ b/arch/powerpc/sysdev/cpm2_pic.h
@@ -0,0 +1,8 @@
+#ifndef _PPC_KERNEL_CPM2_H
+#define _PPC_KERNEL_CPM2_H
+
+extern int cpm2_get_irq(struct pt_regs *regs);
+
+extern void cpm2_pic_init(struct device_node*);
+
+#endif /* _PPC_KERNEL_CPM2_H */
diff --git a/include/asm-ppc/cpm2.h b/include/asm-ppc/cpm2.h
index f6a7ff0..876974e 100644
--- a/include/asm-ppc/cpm2.h
+++ b/include/asm-ppc/cpm2.h
@@ -42,6 +42,8 @@ #define CPM_CR_IDMA3_SBLOCK	(0x16)
 #define CPM_CR_IDMA4_SBLOCK	(0x17)
 #define CPM_CR_MCC1_SBLOCK	(0x1c)
 
+#define CPM_CR_FCC_SBLOCK(x)	(x + 0x10)
+
 #define CPM_CR_SCC1_PAGE	(0x00)
 #define CPM_CR_SCC2_PAGE	(0x01)
 #define CPM_CR_SCC3_PAGE	(0x02)
@@ -62,6 +64,8 @@ #define CPM_CR_IDMA4_PAGE	(0x0a)
 #define CPM_CR_MCC1_PAGE	(0x07)
 #define CPM_CR_MCC2_PAGE	(0x08)
 
+#define CPM_CR_FCC_PAGE(x)	(x + 0x04)
+
 /* Some opcodes (there are more...later)
 */
 #define CPM_CR_INIT_TRX		((ushort)0x0000)
@@ -1186,7 +1190,7 @@ #define PC3_DIRC1	(PC3_TXDAT)
 #define FCC_MEM_OFFSET(x) (CPM_FCC_SPECIAL_BASE + (x*128))
 #define FCC1_MEM_OFFSET FCC_MEM_OFFSET(0)
 #define FCC2_MEM_OFFSET FCC_MEM_OFFSET(1)
-#define FCC2_MEM_OFFSET FCC_MEM_OFFSET(2)
+#define FCC3_MEM_OFFSET FCC_MEM_OFFSET(2)
 
 #endif /* __CPM2__ */
 #endif /* __KERNEL__ */

^ permalink raw reply related

* [PATCH 1/6] POWERPC: CPM2 SoC support to fsl_soc.c
From: Vitaly Bordug @ 2006-08-12  0:10 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20060812000655.6186.42738.stgit@localhost.localdomain>


This patch contains necessary modifications to support the CPM2 SoC peripherals. 
For the time being, those are fs_enet Ethernet driver and cpm_uart serial. 
Written initially to support mpc8560, it also suites to the part of the large PQ2
(more specifically, mpc8260) family.

Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
---

 arch/powerpc/sysdev/fsl_soc.c |  265 ++++++++++++++++++++++++++++++++++++++++-
 arch/powerpc/sysdev/fsl_soc.h |    2 
 2 files changed, 262 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 4a6aa64..7f4ed40 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -2,6 +2,9 @@
  * FSL SoC setup code
  *
  * Maintained by Kumar Gala (see MAINTAINERS for contact information)
+ * 
+ * 2006 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -20,11 +23,14 @@ #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/fsl_devices.h>
+#include <linux/fs_enet_pd.h>
+#include <linux/fs_uart_pd.h>
 
 #include <asm/system.h>
 #include <asm/atomic.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/time.h>
 #include <asm/prom.h>
 #include <sysdev/fsl_soc.h>
 #include <mm/mmu_decl.h>
@@ -42,7 +48,9 @@ phys_addr_t get_immrbase(void)
 	if (soc) {
 		unsigned int size;
 		const void *prop = get_property(soc, "reg", &size);
-		immrbase = of_translate_address(soc, prop);
+
+		if (prop)
+			immrbase = of_translate_address(soc, prop);
 		of_node_put(soc);
 	};
 
@@ -51,6 +59,57 @@ phys_addr_t get_immrbase(void)
 
 EXPORT_SYMBOL(get_immrbase);
 
+#ifdef CONFIG_CPM2
+
+static u32 brgfreq = -1;
+
+u32 get_brgfreq(void)
+{
+	struct device_node *node;
+
+	if (brgfreq != -1)
+		return brgfreq;
+
+	node = of_find_node_by_type(NULL, "cpm");
+	if (node) {
+		unsigned int size;
+		unsigned int *prop = (unsigned int*)get_property(node, "brg-frequency", &size);
+
+		if (prop)
+			brgfreq = *prop;
+		of_node_put(node);
+	};
+
+	return brgfreq;
+}
+
+EXPORT_SYMBOL(get_brgfreq);
+
+static u32 fs_baudrate = -1;
+
+u32 get_baudrate(void)
+{
+	struct device_node *node;
+
+	if (fs_baudrate != -1)
+		return fs_baudrate;
+
+	node = of_find_node_by_type(NULL, "serial");
+	if (node) {
+		unsigned int size;
+		unsigned int *prop = (unsigned int*)get_property(node, "current-speed", &size);
+
+		if (prop)
+			fs_baudrate = *prop;
+		of_node_put(node);
+	};
+
+	return fs_baudrate;
+}
+
+EXPORT_SYMBOL(get_baudrate);
+#endif /* CONFIG_CPM2 */
+
 static int __init gfar_mdio_of_init(void)
 {
 	struct device_node *np;
@@ -85,8 +144,11 @@ static int __init gfar_mdio_of_init(void
 			mdio_data.irq[k] = -1;
 
 		while ((child = of_get_next_child(np, child)) != NULL) {
-			const u32 *id = get_property(child, "reg", NULL);
-			mdio_data.irq[*id] = irq_of_parse_and_map(child, 0);
+			int irq = irq_of_parse_and_map(child, 0);
+			if (irq != NO_IRQ) {
+				const u32 *id = get_property(child, "reg", NULL);
+				mdio_data.irq[*id] = irq;
+			}
 		}
 
 		ret =
@@ -128,7 +190,7 @@ static int __init gfar_of_init(void)
 		const char *model;
 		const void *mac_addr;
 		const phandle *ph;
-		int n_res = 1;
+		int n_res = 2;
 
 		memset(r, 0, sizeof(r));
 		memset(&gfar_data, 0, sizeof(gfar_data));
@@ -159,7 +221,7 @@ static int __init gfar_of_init(void)
 
 		gfar_dev =
 		    platform_device_register_simple("fsl-gianfar", i, &r[0],
-						    n_res + 1);
+						    n_res);
 
 		if (IS_ERR(gfar_dev)) {
 			ret = PTR_ERR(gfar_dev);
@@ -470,3 +532,196 @@ err:
 }
 
 arch_initcall(fsl_usb_of_init);
+
+#ifdef CONFIG_CPM2
+
+static const char *fcc_regs = "fcc_regs";
+static const char *fcc_regs_c = "fcc_regs_c";
+static const char *fcc_pram = "fcc_pram";
+static char bus_id[9][BUS_ID_SIZE];
+
+static int __init fs_enet_of_init(void)
+{
+	struct device_node *np;
+	unsigned int i;
+	struct platform_device *fs_enet_dev;
+	struct resource res;
+	int ret;
+
+	for (np = NULL, i = 0;
+	     (np = of_find_compatible_node(np, "network", "fs_enet")) != NULL;
+	     i++) {
+		struct resource r[4];
+		struct device_node *phy, *mdio;
+		struct fs_platform_info fs_enet_data;
+		unsigned int *id, *phy_addr;
+		void *mac_addr;
+		phandle *ph;
+		char *model;
+
+		memset(r, 0, sizeof(r));
+		memset(&fs_enet_data, 0, sizeof(fs_enet_data));
+
+		ret = of_address_to_resource(np, 0, &r[0]);
+		if (ret)
+			goto err;
+		r[0].name = fcc_regs;
+
+		ret = of_address_to_resource(np, 1, &r[1]);
+		if (ret)
+			goto err;
+		r[1].name = fcc_pram;
+
+		ret = of_address_to_resource(np, 2, &r[2]);
+		if (ret)
+			goto err;
+		r[2].name = fcc_regs_c;
+
+		r[3].start = r[3].end = irq_of_parse_and_map(np, 0);
+		r[3].flags = IORESOURCE_IRQ;
+
+		fs_enet_dev =
+		    platform_device_register_simple("fsl-cpm-fcc", i, &r[0], 4);
+
+		if (IS_ERR(fs_enet_dev)) {
+			ret = PTR_ERR(fs_enet_dev);
+			goto err;
+		}
+
+		model = (char *)get_property(np, "model", NULL);
+		if (model == NULL) {
+			ret = -ENODEV;
+			goto unreg;
+		}
+
+		mac_addr = (void *)get_property(np, "mac-address", NULL);
+		memcpy(fs_enet_data.macaddr, mac_addr, 6);
+
+		ph = (phandle *) get_property(np, "phy-handle", NULL);
+		phy = of_find_node_by_phandle(*ph);
+
+		if (phy == NULL) {
+			ret = -ENODEV;
+			goto unreg;
+		}
+
+		phy_addr = (u32 *) get_property(phy, "reg", NULL);
+		fs_enet_data.phy_addr = *phy_addr;
+
+		id = (u32 *) get_property(np, "device-id", NULL);
+		fs_enet_data.fs_no = *id;
+
+		mdio = of_get_parent(phy);
+                ret = of_address_to_resource(mdio, 0, &res);
+                if (ret) {
+                        of_node_put(phy);
+                        of_node_put(mdio);
+                        goto unreg;
+                }
+
+		if (strstr(model, "FCC")) {
+			int fcc_index = fs_get_fcc_index(*id);
+
+			fs_enet_data.dpram_offset = (u32)cpm2_immr->im_dprambase;
+			fs_enet_data.rx_ring = 32;
+			fs_enet_data.tx_ring = 32;
+			fs_enet_data.rx_copybreak = 240;
+			fs_enet_data.use_napi = 0;
+			fs_enet_data.napi_weight = 17;
+			fs_enet_data.mem_offset = FCC_MEM_OFFSET(fcc_index);
+			fs_enet_data.cp_page = CPM_CR_FCC_PAGE(fcc_index);
+			fs_enet_data.cp_block = CPM_CR_FCC_SBLOCK(fcc_index);
+
+			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)];
+		}
+
+		of_node_put(phy);
+		of_node_put(mdio);
+
+		ret = platform_device_add_data(fs_enet_dev, &fs_enet_data,
+					     sizeof(struct
+						    fs_platform_info));
+		if (ret)
+			goto unreg;
+	}
+	return 0;
+
+unreg:
+	platform_device_unregister(fs_enet_dev);
+err:
+	return ret;
+}
+
+arch_initcall(fs_enet_of_init);
+
+static const char *scc_regs = "regs";
+static const char *scc_pram = "pram";
+
+static int __init cpm_uart_of_init(void)
+{
+	struct device_node *np;
+	unsigned int i;
+	struct platform_device *cpm_uart_dev;
+	int ret;
+
+	for (np = NULL, i = 0;
+	     (np = of_find_compatible_node(np, "serial", "cpm_uart")) != NULL;
+	     i++) {
+		struct resource r[3];
+		struct fs_uart_platform_info cpm_uart_data;
+		int *id;
+
+		memset(r, 0, sizeof(r));
+		memset(&cpm_uart_data, 0, sizeof(cpm_uart_data));
+
+		ret = of_address_to_resource(np, 0, &r[0]);
+		if (ret)
+			goto err;
+
+		r[0].name = scc_regs;
+
+		ret = of_address_to_resource(np, 1, &r[1]);
+		if (ret)
+			goto err;
+		r[1].name = scc_pram;
+
+		r[2].start = r[2].end = irq_of_parse_and_map(np, 0);
+		r[2].flags = IORESOURCE_IRQ;
+
+		cpm_uart_dev =
+		    platform_device_register_simple("fsl-cpm-scc:uart", i, &r[0], 3);
+
+		if (IS_ERR(cpm_uart_dev)) {
+			ret = PTR_ERR(cpm_uart_dev);
+			goto err;
+		}
+
+		id = (int*)get_property(np, "device-id", NULL);
+		cpm_uart_data.fs_no = *id;
+		cpm_uart_data.uart_clk = ppc_proc_freq;
+
+		cpm_uart_data.tx_num_fifo = 4;
+		cpm_uart_data.tx_buf_size = 32;
+		cpm_uart_data.rx_num_fifo = 4;
+		cpm_uart_data.rx_buf_size = 32;
+
+		ret =
+		    platform_device_add_data(cpm_uart_dev, &cpm_uart_data,
+					     sizeof(struct
+						    fs_uart_platform_info));
+		if (ret)
+			goto unreg;
+	}
+
+	return 0;
+
+unreg:
+	platform_device_unregister(cpm_uart_dev);
+err:
+	return ret;
+}
+
+arch_initcall(cpm_uart_of_init);
+#endif /* CONFIG_CPM2 */
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index c433d3f..25230ce 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -3,6 +3,8 @@ #define __PPC_FSL_SOC_H
 #ifdef __KERNEL__
 
 extern phys_addr_t get_immrbase(void);
+extern u32 get_brgfreq(void);
+extern u32 get_baudrate(void);
 
 #endif
 #endif

^ permalink raw reply related

* [PATCH 2/6] CPM_UART: update to make the utilization possible both from ppc and powerpc
From: Vitaly Bordug @ 2006-08-12  0:10 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20060812000655.6186.42738.stgit@localhost.localdomain>


Driver core has been updated to make use of the new powerpc OF-inspired
platform devices, yet keeping compatibility to the vast board list from
ppc.

Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
---

 drivers/serial/cpm_uart/cpm_uart_core.c |   11 ++++-------
 drivers/serial/cpm_uart/cpm_uart_cpm2.c |   13 +++++++------
 include/asm-powerpc/fs_pd.h             |   27 ++++++++++++++++++++++++++
 include/asm-ppc/fs_pd.h                 |   32 +++++++++++++++++++++++++++++++
 4 files changed, 70 insertions(+), 13 deletions(-)

diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 90ff96e..dfa06b6 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -46,6 +46,7 @@ #include <linux/fs_uart_pd.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/delay.h>
+#include <asm/fs_pd.h>
 
 #if defined(CONFIG_SERIAL_CPM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
@@ -1044,11 +1045,11 @@ int cpm_uart_drv_get_platform_data(struc
 
 	if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs")))
 		return -EINVAL;
-	mem = r->start;
+	mem = (u32)ioremap(r->start, r->end - r->start + 1);
 
 	if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram")))
 		return -EINVAL;
-	pram = r->start;
+	pram = (u32)ioremap(r->start, r->end - r->start + 1);
 
 	if(idx > fsid_smc2_uart) {
 		pinfo->sccp = (scc_t *)mem;
@@ -1189,11 +1190,7 @@ static int __init cpm_uart_console_setup
 	if (options) {
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
 	} else {
-		bd_t *bd = (bd_t *) __res;
-
-		if (bd->bi_baudrate)
-			baud = bd->bi_baudrate;
-		else
+		if ((baud = uart_baudrate()) == -1)
 			baud = 9600;
 	}
 
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index ef3bb47..02b9ef9 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -40,6 +40,7 @@ #include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/fs_pd.h>
 
 #include <linux/serial_core.h>
 #include <linux/kernel.h>
@@ -266,7 +267,7 @@ #ifdef CONFIG_SERIAL_CPM_SMC1
 	    (unsigned long)&cpm2_immr->im_smc[0];
 	cpm_uart_ports[UART_SMC1].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
 	cpm_uart_ports[UART_SMC1].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
-	cpm_uart_ports[UART_SMC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_ports[UART_SMC1].port.uartclk = uart_clock();
 	cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1;
 #endif
 
@@ -279,7 +280,7 @@ #ifdef CONFIG_SERIAL_CPM_SMC2
 	    (unsigned long)&cpm2_immr->im_smc[1];
 	cpm_uart_ports[UART_SMC2].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
 	cpm_uart_ports[UART_SMC2].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
-	cpm_uart_ports[UART_SMC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_ports[UART_SMC2].port.uartclk = uart_clock();
 	cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2;
 #endif
 
@@ -293,7 +294,7 @@ #ifdef CONFIG_SERIAL_CPM_SCC1
 	    ~(UART_SCCM_TX | UART_SCCM_RX);
 	cpm_uart_ports[UART_SCC1].sccp->scc_gsmrl &=
 	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-	cpm_uart_ports[UART_SCC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_ports[UART_SCC1].port.uartclk = uart_clock();
 	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1;
 #endif
 
@@ -307,7 +308,7 @@ #ifdef CONFIG_SERIAL_CPM_SCC2
 	    ~(UART_SCCM_TX | UART_SCCM_RX);
 	cpm_uart_ports[UART_SCC2].sccp->scc_gsmrl &=
 	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-	cpm_uart_ports[UART_SCC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_ports[UART_SCC2].port.uartclk = uart_clock();
 	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2;
 #endif
 
@@ -321,7 +322,7 @@ #ifdef CONFIG_SERIAL_CPM_SCC3
 	    ~(UART_SCCM_TX | UART_SCCM_RX);
 	cpm_uart_ports[UART_SCC3].sccp->scc_gsmrl &=
 	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-	cpm_uart_ports[UART_SCC3].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_ports[UART_SCC3].port.uartclk = uart_clock();
 	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3;
 #endif
 
@@ -335,7 +336,7 @@ #ifdef CONFIG_SERIAL_CPM_SCC4
 	    ~(UART_SCCM_TX | UART_SCCM_RX);
 	cpm_uart_ports[UART_SCC4].sccp->scc_gsmrl &=
 	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-	cpm_uart_ports[UART_SCC4].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_ports[UART_SCC4].port.uartclk = uart_clock();
 	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4;
 #endif
 
diff --git a/include/asm-powerpc/fs_pd.h b/include/asm-powerpc/fs_pd.h
new file mode 100644
index 0000000..d530f68
--- /dev/null
+++ b/include/asm-powerpc/fs_pd.h
@@ -0,0 +1,27 @@
+/*
+ * Platform information definitions.
+ *
+ * 2006 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef FS_PD_H
+#define FS_PD_H
+#include <sysdev/fsl_soc.h>
+#include <asm/time.h>
+
+static inline int uart_baudrate(void)
+{
+        return get_baudrate();
+}
+
+static inline int uart_clock(void)
+{
+        return ppc_proc_freq;
+}
+
+#endif
diff --git a/include/asm-ppc/fs_pd.h b/include/asm-ppc/fs_pd.h
new file mode 100644
index 0000000..eed7778
--- /dev/null
+++ b/include/asm-ppc/fs_pd.h
@@ -0,0 +1,32 @@
+/*
+ * Platform information definitions.
+ *
+ * 2006 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef FS_PD_H
+#define FS_PD_H
+
+static inline int uart_baudrate(void)
+{
+	int baud;
+	bd_t *bd = (bd_t *) __res;
+
+	if (bd->bi_baudrate)
+		baud = bd->bi_baudrate;
+	else
+		baud = -1;
+	return baud;
+}
+
+static inline int uart_clock(void)
+{
+	return (((bd_t *) __res)->bi_intfreq);
+}
+
+#endif

^ permalink raw reply related

* [PATCH 0/6] POWERPC: Add support for CPM2 peripherals and 8560 eval board
From: Vitaly Bordug @ 2006-08-11 23:42 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

The following series implements the generic cpm2 infrastructure port,
mpc8560 board-specific bits, and an attempt to overhaul and get rid
of some stuff moved along from the 2.4 times.

Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>

--
Sincerely, Vitaly

^ permalink raw reply

* Re: Realtime preemption patch on PPC
From: Roger Larsson @ 2006-08-11 22:29 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <200608110938.45385.bcook@bpointsys.com>

On Friday 11 August 2006 16:38, Brent Cook wrote:
> On Thursday 10 August 2006 18:04, Ben Weintraub wrote:
> > Howdy,
> >
> > I'm wondering if anyone has had success getting Ingo Molnar's realtime
> > preemption patch (the one here:
> > http://people.redhat.com/mingo/realtime-preempt/ ) working on the ppc
> > arch.
>
> I have gotten them to work with MPC7448 boards, but it has hardware
> floating point, so no math-emu problems.
>
> > Anyhow, when I boot on an MPC8555 with my hack, I get an endless stream
> > of:
> >
> > BUG: sleeping function called from invalid context init(1) at
> > arch/powerpc/math-emu/math.c:226
> > in_atomic():0 [00000000], irqs_disabled():1
> > Call Trace:
> > [A0BB3E90] [A000934C] show_stack+0x48/0x194 (unreliable)
> > [A0BB3EC0] [A001B7DC] __might_sleep+0xe8/0xf4
> > [A0BB3EE0] [A00136C0] do_mathemu+0x30/0x8c8
> > [A0BB3F00] [A00036AC] program_check_exception+0x1ac/0x514
> > [A0BB3F40] [A0002A08] ret_from_except_full+0x0/0x4c
> >
> > Line 226 in arch/powerpc/math-emu/math.c is part of the do_mathemu()
> > function, and contains a call to get_user(), which calls
> > __might_sleep(), causing this problem.
It is not the might sleep that is the problem. Nor the get_user.
It is that the irqs are DISABLED.
If the thread goes to sleep it might never wake up! (With interrupts disabled
what HW can not notify SW that it is live...)

1) Floating point in kernel is difficult to handle due to lazy register saving
2) When using a processor without hardware floating point, compile with 
library (to avoid taking exceptions due to unimplemented instructions with
emulation)

My guess is that you have a driver that disables interrupts, does floating 
point calculations expecting that it has floating point support, takes an 
exception, exception code does not expect to get an exception from kernel
space and absolutely not when having interrupts disabled...

Recompile with soft float, or even better use fixed point calculations!

/RogerL

^ permalink raw reply

* Re: [PATCH 4/6] ehea: header files
From: Anton Blanchard @ 2006-08-11 22:07 UTC (permalink / raw)
  To: Jan-Bernd Themann
  Cc: Thomas Klein, netdev, linux-kernel, linux-ppc, Christoph Raisch,
	Marcus Eder
In-Reply-To: <44D99F56.7010201@de.ibm.com>


> --- linux-2.6.18-rc4-orig/drivers/net/ehea/ehea.h	1969-12-31 

> +extern void exit(int);

Should be able to remove that prototype :) 

Anton

^ permalink raw reply

* Re: [PATCH 3/6] ehea: queue management
From: Anton Blanchard @ 2006-08-11 21:52 UTC (permalink / raw)
  To: Jan-Bernd Themann
  Cc: Thomas Klein, netdev, linux-kernel, linux-ppc, Christoph Raisch,
	Marcus Eder
In-Reply-To: <44D99F38.8010306@de.ibm.com>


Hi,

> --- linux-2.6.18-rc4-orig/drivers/net/ehea/ehea_ethtool.c	1969-12-31 

> +static void netdev_get_pauseparam(struct net_device *dev,
> +				  struct ethtool_pauseparam *pauseparam)
> +{
> +	printk("get pauseparam\n");
> +}

There are a number of stubbed out ethtool functions like this. Best not
to implement them and allow the upper layers to return a correct error.

Anton

^ permalink raw reply

* Re: [PATCH 4/6] ehea: header files
From: Anton Blanchard @ 2006-08-11 21:40 UTC (permalink / raw)
  To: Jan-Bernd Themann
  Cc: Thomas Klein, netdev, linux-kernel, linux-ppc, Christoph Raisch,
	Marcus Eder
In-Reply-To: <44D99F56.7010201@de.ibm.com>


Hi,

>  drivers/net/ehea/ehea.h    |  452 

> +#define EHEA_DRIVER_NAME	"IBM eHEA"

You are using this for ethtool get_drvinfo. Im not sure if it should
match the module name, and I worry about having a space in the name. Any
ideas on what we should be doing here?

> +#define NET_IP_ALIGN 0

Shouldnt override this in your driver.

> +#define EDEB_P_GENERIC(level, idstring, format, args...) \
> +#define EDEB_P_GENERIC(level,idstring,format,args...) \
> +#define EDEB(level, format, args...) \
> +#define EDEB_ERR(level, format, args...) \
> +#define EDEB_EN(level, format, args...) \
> +#define EDEB_EX(level, format, args...) \
> +#define EDEB_DMP(level, adr, len, format, args...) \

There are a lot of debug statements in the driver. When doing a review
I stripped them all out to make it easier to read. As suggested by
others, using the standard debug macros (where still required) would be
a good idea.

Anton

^ permalink raw reply

* Re: [PATCH 2/6] ehea: pHYP interface
From: Nathan Lynch @ 2006-08-11 21:26 UTC (permalink / raw)
  To: Jan-Bernd Themann
  Cc: Thomas Klein, netdev, linux-kernel, linux-ppc, Christoph Raisch,
	Marcus Eder
In-Reply-To: <20060811211915.GL3233@localdomain>

Nathan Lynch wrote:

> Hope all the callers of this function are in non-atomic context (but I
> wasn't able to find any callers?).

Never mind, I somehow missed the users of ehea_hcall_9arg_9ret in this
patch, sorry.

^ permalink raw reply

* RE: MTD Flash Howto ?
From: Lee Revell @ 2006-08-11 21:26 UTC (permalink / raw)
  To: Ned W. Rhodes; +Cc: Leonid, linuxppc-embedded
In-Reply-To: <001a01c6b7d1$17dd6130$6201eed0@ssgpoweredge>

On Fri, 2006-08-04 at 10:20 -0400, Ned W. Rhodes wrote:
> The book Building Embedded Linux Systems has a good section on the use of
> flash file systems.
> 
> When you boot, you will see something like this, depending on the type of
> flash driver you have. Make sure you have defined your mtd map in
> kernel/drivers/mtd/map.
> 
> JFFS2 version 2.2. (NAND) (C) 2001-2003 Red Hat, Inc.
> JFS: nTxBlock = 965, nTxLock = 7720
> 

Is JFFS2 required to mount MTD devices?

Everything seems to be set up correctly here:

S29GL512N MirrorBit Flash: probing 16-bit flash bus
S29GL512N MirrorBit Flash: Found 1 x16 devices at 0x0 in 16-bit bank
 Amd/Fujitsu Extended Query Table at 0x0040
S29GL512N MirrorBit Flash: CFI does not contain boot bank location.
Assuming top.
number of CFI chips: 1
cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.
Creating 2 MTD partitions on "S29GL512N MirrorBit Flash":
0x00000000-0x02a00000 : "Raw Area"
ftl_cs: FTL header not found.
0x02a00000-0x02b80000 : "User FS"
ftl_cs: FTL header not found.
blkmtd: version $Revision: 1.24 $
blkmtd: error: missing `device' name

cat /proc/mtd:

dev:    size   erasesize  name
mtd0: 02a00000 00020000 "Raw Area"
mtd1: 00180000 00020000 "User FS"

cat /proc/partitions:

major minor  #blocks  name

  31     0      43008 mtdblock0
  31     1       1536 mtdblock1

~ # ls -al /dev/mtdblock[01]
brw-r--r--    1 root     0         31,   0 Aug 11 14:27 /dev/mtdblock0
brw-r--r--    1 root     0         31,   1 Aug 11 14:27 /dev/mtdblock1

As you can see the major and minor numbers are correct, but I cannot
mount the MTD partitions:

~ # mount -t minix /dev/mtdblock1 foo
mount: Mounting /dev/mtdblock1 on /foo failed: No such device

What am I doing wrong?

Lee

^ permalink raw reply

* Re: [PATCH 2/6] ehea: pHYP interface
From: Nathan Lynch @ 2006-08-11 21:19 UTC (permalink / raw)
  To: Jan-Bernd Themann
  Cc: Thomas Klein, netdev, linux-kernel, linux-ppc, Christoph Raisch,
	Marcus Eder
In-Reply-To: <44D99F1A.4080905@de.ibm.com>

Hi-

Jan-Bernd Themann wrote:
> +static inline long ehea_hcall_9arg_9ret(unsigned long opcode,
> +					unsigned long arg1,
> +					unsigned long arg2,
> +					unsigned long arg3,
> +					unsigned long arg4,
> +					unsigned long arg5,
> +					unsigned long arg6,
> +					unsigned long arg7,
> +					unsigned long arg8,
> +					unsigned long arg9,
> +					unsigned long *out1,
> +					unsigned long *out2,
> +					unsigned long *out3,
> +					unsigned long *out4,
> +					unsigned long *out5,
> +					unsigned long *out6,
> +					unsigned long *out7,
> +					unsigned long *out8,
> +					unsigned long *out9)
> +{
> +	long hret = H_SUCCESS;
> +	int i, sleep_msecs;
> +
> +	EDEB_EN(7, "opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
> +		"arg5=%lx arg6=%lx arg7=%lx arg8=%lx arg9=%lx",
> +		opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
> +		arg8, arg9);
> +
> +
> +	for (i = 0; i < 5; i++) {
> +		hret = plpar_hcall_9arg_9ret(opcode,
> +					    arg1, arg2, arg3, arg4,
> +					    arg5, arg6, arg7, arg8,
> +					    arg9,
> +					    out1, out2, out3, out4,
> +					    out5, out6, out7, out8,
> +					    out9);
> +
> +		if (H_IS_LONG_BUSY(hret)) {
> +			sleep_msecs = get_longbusy_msecs(hret);
> +			msleep_interruptible(sleep_msecs);
> +			continue;
> +		}

Looping five times before giving up seems arbitrary and failure-prone
on busy systems.

Is msleep_interruptible (as opposed to msleep) really appropriate?

Hope all the callers of this function are in non-atomic context (but I
wasn't able to find any callers?).

And this function is too big to be inline.

^ permalink raw reply

* Re: [PATCH 2/6] ehea: pHYP interface
From: Anton Blanchard @ 2006-08-11 21:13 UTC (permalink / raw)
  To: Jan-Bernd Themann
  Cc: Thomas Klein, netdev, linux-kernel, linux-ppc, Christoph Raisch,
	Marcus Eder
In-Reply-To: <44D99F1A.4080905@de.ibm.com>


Hi,

> --- linux-2.6.18-rc4-orig/drivers/net/ehea/ehea_phyp.c	1969-12-31 16:00:00.000000000 -0800

> +u64 ehea_h_alloc_resource_eq(const u64 hcp_adapter_handle,
...
> +u64 hipz_h_reregister_pmr(const u64 adapter_handle,
...
> +static inline int hcp_galpas_ctor(struct h_galpas *galpas,

Be nice to have some consistent names, hipz_ and hcp_ is kind of
cryptic.

> +#define H_QP_CR_STATE_RESET	    0x0000010000000000	/*  Reset */

Probably want ULL on here and the other 64bit constants.

Anton

^ permalink raw reply

* Re: [RFC] Adding MTD to device tree
From: Arnd Bergmann @ 2006-08-11 21:10 UTC (permalink / raw)
  To: linuxppc-embedded; +Cc: linuxppc-dev, linux-mtd
In-Reply-To: <44DCA2BF.1030002@ru.mvista.com>

On Friday 11 August 2006 17:31, Sergei Shtylyov wrote:
> + =A0 h) MTD nodes
> +
> + =A0 Memory Technology Devices are flash, ROM, and similar chips, often =
used
> + =A0 for solid state file systems on embedded devices.
> +
> + =A0 Required properties:
> +
> + =A0 =A0- device_type : has to be "mtd"
> + =A0 =A0- compatible : Should be the name of the MTD driver. Currently, =
this is
> + =A0 =A0 =A0most likely to be "physmap".
> + =A0 =A0- reg : Offset and length of the register set for the device.

I would prefer to call them something different in the device tree.
The name 'mtd' is very specific to Linux, but the device tree
is a more generic concept.

I understand that the booting-without-of.txt file is by definition
Linux specific as well, but we should be prepared for making parts
of it a OS independent binding at the point where we put the same
device nodes into actual OF implementations that able to boot
different operating systems.

I would prefer a naming that has=20

   Required properties:
    - device_type : one of "nand-flash", "nor-flash", or "rom".
    - model : an identifier for the actual controller chip used.
    - compatible : Should be the name of the MTD driver. For
      type "rom", this is most likely "physmap".

	Arnd <><

^ permalink raw reply

* Re: [PATCH 1/6] ehea: interface to network stack
From: Anton Blanchard @ 2006-08-11 20:56 UTC (permalink / raw)
  To: Jan-Bernd Themann
  Cc: Thomas Klein, netdev, linux-kernel, linux-ppc, Christoph Raisch,
	Marcus Eder
In-Reply-To: <44D99EFC.3000105@de.ibm.com>


Hi,

> --- linux-2.6.18-rc4-orig/drivers/net/ehea/ehea_main.c	1969-12-31 

> +#define DEB_PREFIX "main"

Doesnt appear to be used.

> +static struct net_device_stats *ehea_get_stats(struct net_device *dev)
...
> +	cb2 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL);

I cant see where this gets freed.

> +
> +				skb_index = ((index - i
> +					      + port_res->skb_arr_sq_len)
> +					     % port_res->skb_arr_sq_len);

This is going to force an expensive divide. Its much better to change
this to the simpler and quicker:

i++;
if (i > max)
	i = 0;

There are a few places in the driver can be changed to do this.

> +static int ehea_setup_single_port(struct ehea_adapter *adapter,A
> +				  int portnum, struct device_node *dn)
...
> +	cb4 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL);

I cant see where this is freed.

Anton

^ permalink raw reply

* [PATCH] fix gettimeofday vs. update_gtod race
From: Nathan Lynch @ 2006-08-11 20:41 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras

Userspace can (very, very) occasionally get bogus time values due to
a tiny race between powerpc's do_gettimeofday and timer interrupt:

1. do_gettimeofday does get_tb()

2. decrementer exception on boot cpu which runs timer_recalc_offset,
   which also samples the timebase and updates the do_gtod structure
   with a greater timebase value.

3. do_gettimeofday calls __do_gettimeofday, which leads to the
   negative result from tb_val - temp_varp->tb_orig_stamp.

The fix is to ensure that do_gettimeofday samples the timebase only
after loading do_gtod.varp.


Signed-off-by: Nathan Lynch <ntl@pobox.com>

diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 774c0a3..6b690df 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -417,7 +417,7 @@ static __inline__ void timer_check_rtc(v
 /*
  * This version of gettimeofday has microsecond resolution.
  */
-static inline void __do_gettimeofday(struct timeval *tv, u64 tb_val)
+static inline void __do_gettimeofday(struct timeval *tv)
 {
 	unsigned long sec, usec;
 	u64 tb_ticks, xsec;
@@ -431,7 +431,12 @@ static inline void __do_gettimeofday(str
 	 * without a divide (and in fact, without a multiply)
 	 */
 	temp_varp = do_gtod.varp;
-	tb_ticks = tb_val - temp_varp->tb_orig_stamp;
+
+	/* Sampling the time base must be done after loading
+	 * do_gtod.varp in order to avoid racing with update_gtod.
+	 */
+	rmb();
+	tb_ticks = get_tb() - temp_varp->tb_orig_stamp;
 	temp_tb_to_xs = temp_varp->tb_to_xs;
 	temp_stamp_xsec = temp_varp->stamp_xsec;
 	xsec = temp_stamp_xsec + mulhdu(tb_ticks, temp_tb_to_xs);
@@ -464,7 +469,7 @@ void do_gettimeofday(struct timeval *tv)
 		tv->tv_usec = usec;
 		return;
 	}
-	__do_gettimeofday(tv, get_tb());
+	__do_gettimeofday(tv);
 }
 
 EXPORT_SYMBOL(do_gettimeofday);

^ permalink raw reply related

* Re: [PATCH 0/4]:  powerpc/cell spidernet ethernet driver fixes
From: Arnd Bergmann @ 2006-08-11 20:27 UTC (permalink / raw)
  To: Linas Vepstas
  Cc: netdev, James K Lewis, linux-kernel, linuxppc-dev, Sam Ravnborg,
	Jens Osterkamp
In-Reply-To: <20060811193102.GN10638@austin.ibm.com>

On Friday 11 August 2006 21:31, Linas Vepstas wrote:
> I put my name at the top when I was the primary author. 
> I put Jim's name at the top when he was the primary author. 
> 
> Both names are there because I sat in Jim's office and used
> his keyboard. I got him to compile and run the tests on
> his hardware, and we'd then debate the results.

When the patch gets added to a git repository, they end up
having your name on it, because the author is determined
from the person who sent the patch.

For the patches where Jim is the main author, you should put a 

From: James K Lewis <jklewis@us.ibm.com>

into the first line of the email body. That will make the
scripts do the right thing. The order of the Signed-off-by:
lines is used is independant from authorship and should
list the name of the submitter last.

	Arnd <><

^ permalink raw reply

* Re: [PATCH 4/4]: powerpc/cell spidernet ethtool -i version number info.
From: Linas Vepstas @ 2006-08-11 19:46 UTC (permalink / raw)
  To: Olof Johansson
  Cc: Arnd Bergmann, Jens Osterkamp, James K Lewis, linux-kernel,
	linuxppc-dev, netdev
In-Reply-To: <OF934FE4E3.EEC44FDD-ON872571C7.00668651-862571C7.00677A44@us.ibm.com>


Hi Olof,

Olof Johansson <olof@lixom.net> writes:
> On Fri, Aug 11, 2006 at 12:11:17PM -0500, Linas Vepstas wrote:
> 
> > This patch adds version information as reported by 
> > ethtool -i to the Spidernet driver.
> 
> Why does a driver that's in the mainline kernel need to have a version
> number besides the kernel version?

I'll let Jim be the primary defender. From what I can tell, "that's the
way its done".  For example:

linux-2.6.18-rc3-mm2 $ grep MODULE_VERSION */*/*.c |wc
     164     245    9081

> I can understand it for drivers like e1000 that Intel maintain outside
> of the kernel as well. But spidernet is a fully mainline maintained
> driver, right?

Yes, the spidernet is a Linux-kernel only driver.

--linas

p.s. very strange, but I did not see your original email;  
only saw Jim's reply.

^ permalink raw reply

* Re: [RFC] consolidated libdt proposal
From: Jon Loeliger @ 2006-08-11 19:33 UTC (permalink / raw)
  To: linuxppc-dev@ozlabs.org
  Cc: linuxppc-embedded, xen-ppc-devel@lists.xensource.com
In-Reply-To: <1155064370.5572.11.camel@localhost>

On Tue, 2006-08-08 at 14:12, Matthew McClintock wrote:
> This is a patch to u-boot with the changes.
> 
> * Patch to modify ft_build.c to update flat device trees in place
>   Patch by Matthew McClintock 26-June-2006
> 
> Signed-off-by: Matthew McClintock <msm@freescale.com>

Also FYI, I have assembled all Matt's 85xx related U-Boot patches,
along with the corresponding 86xx updates, into the u-boot-86xx.git
tree on:

    http://jdl.com/git_repos/

This U-Boot separates out the DTS files, but allows the DTB
to be downloaded.  It can then update it and hand it off to
either an 85xx or 86xx linux kernel.

I use these commands, roughly:

    # build U-boot and Linux as usual

    $ dtc -f -V 0x10 -I dts -O dtb \
        linux-2.6-86xx/arch/powerpc/boot/dts/mpc8641_hpcn.dts \
        mpc8641_hpcn.dtb

    In U-boot now:

    > tftp 1000000 loeliger/uImage.8641
    > tftp 900000 loeliger/mpc8641_hpcn.dtb

    > bootm 1000000 - 900000

Enjoy,
jdl

^ permalink raw reply

* Re: [PATCH 0/4]:  powerpc/cell spidernet ethernet driver fixes
From: Linas Vepstas @ 2006-08-11 19:31 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Arnd Bergmann, netdev, James K Lewis, linux-kernel, linuxppc-dev,
	Jens Osterkamp
In-Reply-To: <20060811174439.GA30191@mars.ravnborg.org>

On Fri, Aug 11, 2006 at 07:44:39PM +0200, Sam Ravnborg wrote:
> > 
> > These have been well-tested over the last few weeks. Please apply. 
> Hi Linas.
> Just noticed a nit-pick detail.
> The general rule is to add your Signed-off-by: at the bottom of the
> patch, so the top-most Signed-of-by: is also the original author whereas
> the last Signed-of-by: is the one that added this patch to the kernel.

I put my name at the top when I was the primary author. 
I put Jim's name at the top when he was the primary author. 

Both names are there because I sat in Jim's office and used
his keyboard. I got him to compile and run the tests on
his hardware, and we'd then debate the results.

> Likewise you add Cc: before your Signed-off-by: line.

The patches I ave from akpm have the CC's after the 
signed-off by line, not before.

--linas

^ permalink raw reply

* Re: [PATCH 4/4]: powerpc/cell spidernet ethtool -i version number info.
From: James K Lewis @ 2006-08-11 18:50 UTC (permalink / raw)
  To: Olof Johansson
  Cc: Arnd Bergmann, Jens Osterkamp, linux-kernel, linuxppc-dev, netdev
In-Reply-To: <20060811180013.GB6550@pb15.lixom.net>

[-- Attachment #1: Type: text/plain, Size: 1585 bytes --]

 Hi Olof,

  There are several reasons why an Ethernet driver should have an up to 
date version number:

1. Customers like to see they are really getting a new version.

2. It makes it easier for support personnel (me in this case) to see which 
driver they have. Sure, sometimes I can talk them thru doing a "sum" on 
the .ko and all that, but why not just use the version number? That's what 
it is for. And no, you can't just assume they have the version that came 
with the kernel they are running. It doesn't work that way.

3. It makes bug reporting easier. 

4. I have already run into too many problems and wasted too much time 
working with drivers when the number was NOT getting updated. 



Jim Lewis
Advisory Software Engineer
IBM Linux Technology Center
512-838-7754






Olof Johansson <olof@lixom.net> 
08/11/2006 01:00 PM

To
Linas Vepstas <linas@austin.ibm.com>
cc
netdev@vger.kernel.org, linux-kernel@vger.kernel.org, 
linuxppc-dev@ozlabs.org, Jens Osterkamp <Jens.Osterkamp@de.ibm.com>, James 
K Lewis/Austin/IBM@ibmus, Arnd Bergmann <arnd@arndb.de>
Subject
Re: [PATCH 4/4]: powerpc/cell spidernet ethtool -i version number info.






On Fri, Aug 11, 2006 at 12:11:17PM -0500, Linas Vepstas wrote:

> This patch adds version information as reported by 
> ethtool -i to the Spidernet driver.

Why does a driver that's in the mainline kernel need to have a version
number besides the kernel version?

I can understand it for drivers like e1000 that Intel maintain outside
of the kernel as well. But spidernet is a fully mainline maintained
driver, right?


-Olof


[-- Attachment #2: Type: text/html, Size: 2701 bytes --]

^ permalink raw reply

* Re: Gianfar eth driver on 8540 ppc - for 2.4 and 2.6 : differentoutputs
From: Matt Porter @ 2006-08-11 18:35 UTC (permalink / raw)
  To: Haruki Dai-r35557; +Cc: Prashant Yendigeri, linuxppc-embedded
In-Reply-To: <18AEF66AFDF06F4CAAA1D419D000FD3380B85B@az33exm24.fsl.freescale.net>

On Fri, Aug 11, 2006 at 11:08:59AM -0700, Haruki Dai-r35557 wrote:
> Why there are three TSEC on the MPC8540?? 

There aren't.  There are two TSECs and one FEC on the MPC8540.
gianfar drives them all (all the non-CPM enets, that is).

-Matt

^ permalink raw reply

* Re: [RFC] asm code for Hypervisor Call Instrumentation
From: Mike Kravetz @ 2006-08-11 18:30 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <17622.56592.41532.206800@cargo.ozlabs.ibm.com>

On Mon, Aug 07, 2006 at 04:26:24PM +1000, Paul Mackerras wrote:
> Hmmm, doing the update in assembly would avoid the need to create a
> stack frame, which would be nice...  Maybe we need to add some macros
> to include/asm-powerpc/percpu.h to make it easier to access per-cpu
> variables from assembly code.
> 
> Alternatively, we could put a pointer to the hcall_stats array for
> each cpu in its paca.  That's very easily accessed from assembly code.

I finally got around to doing the update in assembly.  I have attached
the code in question below.  Macros were added (elsewhere) for things like 
stat structure and offsets within the structure.  No macros for per-cpu
data.  Rather, I just used some existing definitions and based code on
descriptions in asm-powerpc/percpu.h.  Let me know if this introduces too
many (unchecked at compile time assumptions) into the code.

The many comments are mostly for my benefit. :)

Thanks,
-- 
Mike

#define STK_PARM(i)     (48 + ((i)-3)*8)

#ifdef CONFIG_HCALL_STATS
/*
 * precall must preserve all registers.  use unused STK_PARM()
 * areas to save snapshots and opcode.
 */
#define HCALL_INST_PRECALL					\
	std	r3,STK_PARM(r3)(r1);	/* save opcode */	\
	mftb	r3;			/* get timebase and */	\
	std     r3,STK_PARM(r5)(r1);	/* save for later */	\
BEGIN_FTR_SECTION;						\
	mfspr	r3,SPRN_PURR;		/* get PURR and */	\
END_FTR_SECTION_IFSET(CPU_FTR_PURR);				\
	std	r3,STK_PARM(r6)(r1);	/* save for later */	\
	ld	r3,STK_PARM(r3)(r1);	/* opcode back in r3 */
	
/*
 * postcall is performed immediately before function return which
 * allows liberal use of non-volital registers.
 */
#define HCALL_INST_POSTCALL					\
	/* get time and PURR snapshots after hcall */		\
	mftb	r7;			/* timebase after */	\
BEGIN_FTR_SECTION;						\
	mfspr	r8,SPRN_PURR;		/* PURR after */	\
END_FTR_SECTION_IFSET(CPU_FTR_PURR);				\
								\
	/* calculate time and PURR deltas for call */		\
	ld	r5,STK_PARM(r5)(r1);	/* timebase before */	\
	subf	r5,r5,r7;					\
	ld	r6,STK_PARM(r6)(r1);	/* PURR before */	\
	subf	r6,r6,r8;					\
								\
	/* calculate address of stat structure */		\
	ld	r4,STK_PARM(r3)(r1);	/* use opcode as */	\
	rldicl	r4,r4,62,2;		/* index into array */	\
	mulli	r4,r4,HCALL_STAT_SIZE;				\
	LOAD_REG_ADDR(r7, per_cpu__hcall_stats);		\
	add	r4,r4,r7;					\
	ld	r7,PACA_DATA_OFFSET(r13); /* per cpu offset */	\
	add	r4,r4,r7;					\
								\
	/* update stats	*/					\
	ld	r7,HCALL_STAT_CALLS(r4); /* count */		\
	addi	r7,r7,1;					\
	std	r7,HCALL_STAT_CALLS(r4);			\
	ld      r7,HCALL_STAT_TB(r4);	/* timebase */		\
	add	r7,r7,r5;					\
	std	r7,HCALL_STAT_TB(r4);				\
	ld	r7,HCALL_STAT_PURR(r4);	/* PURR */		\
	add	r7,r7,r6;					\
	std	r7,HCALL_STAT_PURR(r4);
#else

#define HCALL_INST_PRECALL
#define HCALL_INST_POSTCALL
#endif

^ permalink raw reply

* RE: Gianfar eth driver on 8540 ppc - for 2.4 and 2.6 : differentoutputs
From: Haruki Dai-r35557 @ 2006-08-11 18:08 UTC (permalink / raw)
  To: Kumar Gala, Prashant Yendigeri; +Cc: linuxppc-embedded
In-Reply-To: <CFF33627-951D-495D-8DBB-B0AC7F9D13D7@kernel.crashing.org>

Why there are three TSEC on the MPC8540??=20

Dai

> -----Original Message-----
> From:=20
> linuxppc-embedded-bounces+dai.haruki=3Dfreescale.com@ozlabs.org=20
> [mailto:linuxppc-embedded-bounces+dai.haruki=3Dfreescale.com@ozl
> abs.org] On Behalf Of Kumar Gala
> Sent: Friday, August 11, 2006 7:38 AM
> To: Prashant Yendigeri
> Cc: linuxppc-embedded@ozlabs.org
> Subject: Re: Gianfar eth driver on 8540 ppc - for 2.4 and 2.6=20
> : differentoutputs
>=20
>=20
> On Aug 11, 2006, at 6:21 AM, Prashant Yendigeri wrote:
>=20
> >
> > Hi,
> >
> > Downloaded 2.6.16.26 and booted up and got this :
> >
> > / # ifconfig eth0 172.28.8.254 up
> > [   34.034596] 0:00 not found
> > [   34.037330] eth0: Could not attach to PHY
> > [   34.041809] 0:00 not found
> > SIOCSIFFLAGS: No[   34.044526] eth0: Could not attach to PHY
> >  such device
> > SIOCSIFFLAGS: No such device
> >
> > I had enabled all the PHY devices in .config and also tried only =20
> > with Marvell phy enabled.
>=20
>=20
> Are you doing this on a custom board?  If so what is the PHY address =20
> for the Marvell phy you are using?
>=20
> - k
>=20
> >
> > Kernel boot messages :
> > [    2.296555] Gianfar MII Bus: probed
> > [    2.301789] eth0: Gianfar Ethernet Controller Version 1.2, =20
> > 00:01:af:07:9b:8a
> >
> > [    2.309039] eth0: Running with NAPI disabled
> > [    2.313307] eth0: 64/64 RX/TX BD ring size
> > [    2.318498] eth1: Gianfar Ethernet Controller Version 1.2, =20
> > 00:00:00:00:72:6f
> >
> > [    2.325738] eth1: Running with NAPI disabled
> > [    2.330006] eth1: 64/64 RX/TX BD ring size
> > [    2.335198] eth2: Gianfar Ethernet Controller Version 1.2, 6f:=20
> > 74:3d:2f:64:65
> >
> > [    2.342377] eth2: Running with NAPI disabled
> > [    2.346662] eth2: 64/64 RX/TX BD ring size
> > [    2.351586] Marvell 88E1101: Registered new driver
> > [    2.357010] Davicom DM9161E: Registered new driver
> > [    2.362443] Davicom DM9131: Registered new driver
> > [    2.367775] Cicada Cis8204: Registered new driver
> > [    2.373136] LXT970: Registered new driver
> > [    2.377794] LXT971: Registered new driver
> > [    2.382461] QS6612: Registered new driver
> >
> >
> > Regards,
> > Prashant
> >
> >
> >
> >
> >
> > Kumar Gala <galak@kernel.crashing.org>
> > 08/11/2006 09:40 AM
> >
> > To
> > Prashant Yendigeri <Prashant.Yendigeri@lntinfotech.com>
> > cc
> > linuxppc-embedded@ozlabs.org
> > Subject
> > Re: Gianfar eth driver on 8540 ppc - for 2.4 and 2.6 : different =20
> > outputs
> >
> >
> >
> >
> >
> >
> > On Aug 10, 2006, at 6:18 AM, Prashant Yendigeri wrote:
> >
> > >
> > > Hi,
> > >
> > > The gianfar driver of 2.6.12 and 2.4.20 give different outputs on
> > > the same PPC 8540 board.
> > >
> > > What could be the reason ?
> > >
> > > Output on 2.4.20 :
> > > /root # ifconfig eth0 172.28.8.254 up
> > > eth0: PHY is Marvell 88E1011S (1410c62)
> > > eth0: Auto-negotiation done
> > > eth0: Half Duplex
> > > eth0: Speed 10BT
> > > eth0: Link is up
> > >
> > > Output on 2.6.12
> > > / # ifconfig eth0 172.28.8.254 up
> > >  eth0: PHY is Generic MII (ffffffff)
> >
> > It looks like your 2.6.12 kernel isn't handling the PHY correctly.
> > I'd recommend upgrading to something newer which has the phylib
> > (can't remember which 2.6 that went into).
> >
> > - kumar
> >
> >=20
> ______________________________________________________________________
> >
> >
> >=20
> ______________________________________________________________________
>=20
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>=20

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox