Patchwork powerpc/qe: Setup clock source for TDM

login
register
mail settings
Submitter Xiaobo Xie
Date March 18, 2014, 9:09 a.m.
Message ID <1395133745-5557-1-git-send-email-X.Xie@freescale.com>
Download mbox | patch
Permalink /patch/331372/
State Changes Requested
Headers show

Comments

Xiaobo Xie - March 18, 2014, 9:09 a.m.
Add tdm clock configuration in both qe clock system and
ucc fast controler.

Signed-off-by: Xie Xiaobo <X.Xie@freescale.com>
Signed-off-by: Haiying Wang <Haiying.Wang@freescale.com>
---
 arch/powerpc/include/asm/immap_qe.h   |   5 +-
 arch/powerpc/include/asm/qe.h         |  13 +-
 arch/powerpc/include/asm/ucc.h        |   6 +-
 arch/powerpc/include/asm/ucc_fast.h   |  10 +-
 arch/powerpc/sysdev/qe_lib/qe.c       |   9 +-
 arch/powerpc/sysdev/qe_lib/ucc.c      | 773 +++++++++++++++++++++++++++++++++-
 arch/powerpc/sysdev/qe_lib/ucc_fast.c |  40 +-
 7 files changed, 845 insertions(+), 11 deletions(-)
Scott Wood - April 9, 2014, 1:05 a.m.
On Tue, 2014-03-18 at 17:09 +0800, Xie Xiaobo wrote:
> diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
> index 238a07b..9a9f733 100644
> --- a/arch/powerpc/sysdev/qe_lib/qe.c
> +++ b/arch/powerpc/sysdev/qe_lib/qe.c
> @@ -1,5 +1,6 @@
>  /*
> - * Copyright (C) 2006-2010 Freescale Semiconductor, Inc. All rights reserved.
> + * Copyright (C) 2006-2010, 2014 Freescale Semiconductor, Inc.
> + * All rights reserved.
>   *
>   * Authors: 	Shlomi Gridish <gridish@freescale.com>
>   * 		Li Yang <leoli@freescale.com>
> @@ -240,6 +241,12 @@ enum qe_clock qe_clock_source(const char *source)
>  	if (strcasecmp(source, "none") == 0)
>  		return QE_CLK_NONE;
>  
> +	if (strcasecmp(source, "tsync_pin") == 0)
> +		return QE_TSYNC_PIN;
> +
> +	if (strcasecmp(source, "rsync_pin") == 0)
> +		return QE_RSYNC_PIN;
> +

Binding update?

> @@ -210,3 +210,774 @@ int ucc_set_qe_mux_rxtx(unsigned int ucc_num, enum qe_clock clock,
>  
>  	return 0;
>  }
> +
> +/* tdm_num: TDM A-H port num is 0-7 */
> +int ucc_set_tdm_rxtx_clk(u32 tdm_num, enum qe_clock clock,
> +		enum comm_dir mode)
> +{
> +	u32 clock_bits, shift;
> +	struct qe_mux *qe_mux_reg;
> +	 __be32 __iomem *cmxs1cr;
> +
> +	clock_bits = 0;
> +	qe_mux_reg = &qe_immr->qmx;
> +
> +	if ((tdm_num > 7 || tdm_num < 0))
> +		return -EINVAL;
> +
> +	/* The communications direction must be RX or TX */
> +	if (!((mode == COMM_DIR_RX) || (mode == COMM_DIR_TX)))
> +		return -EINVAL;

Unnecessary parentheses.

tdm_num cannot be < 0 as it is unsigned.

Use a symbolic name rather than "7".

> +	switch (mode) {
> +	case COMM_DIR_RX:
> +		switch (tdm_num) {
> +		case 0:
> +			switch (clock) {
> +			case QE_BRG3:
> +					clock_bits = 1;
> +					break;
> +			case QE_BRG4:
> +					clock_bits = 2;
> +					break;
> +			case QE_CLK1:
> +					clock_bits = 4;
> +					break;
> +			case QE_CLK2:
> +					clock_bits = 5;
> +					break;
> +			case QE_CLK3:
> +					clock_bits = 6;
> +					break;
> +			case QE_CLK8:
> +					clock_bits = 7;
> +					break;
> +			default:
> +					break;
> +			}
> +			shift = 28;
> +			break;
> +		case 1:
> +			switch (clock) {
> +			case QE_BRG3:
> +					clock_bits = 1;
> +					break;
> +			case QE_BRG4:
> +					clock_bits = 2;
> +					break;
> +			case QE_CLK1:
> +					clock_bits = 4;
> +					break;
> +			case QE_CLK2:
> +					clock_bits = 5;
> +					break;
> +			case QE_CLK5:
> +					clock_bits = 6;
> +					break;
> +			case QE_CLK10:
> +					clock_bits = 7;
> +					break;
> +			default:
> +					break;
> +			}
> +			shift = 24;
> +			break;
> +		case 2:
> +			switch (clock) {
> +			case QE_BRG3:
> +					clock_bits = 1;
> +					break;
> +			case QE_BRG4:
> +					clock_bits = 2;
> +					break;
> +			case QE_CLK1:
> +					clock_bits = 4;
> +					break;
> +			case QE_CLK2:
> +					clock_bits = 5;
> +					break;
> +			case QE_CLK7:
> +					clock_bits = 6;
> +					break;
> +			case QE_CLK12:
> +					clock_bits = 7;
> +					break;
> +			default:
> +					break;
> +			}
> +			shift = 20;
> +			break;
> +		case 3:
> +			switch (clock) {
> +			case QE_BRG3:
> +					clock_bits = 1;
> +					break;
> +			case QE_BRG4:
> +					clock_bits = 2;
> +					break;
> +			case QE_CLK1:
> +					clock_bits = 4;
> +					break;
> +			case QE_CLK2:
> +					clock_bits = 5;
> +					break;
> +			case QE_CLK9:
> +					clock_bits = 6;
> +					break;
> +			case QE_CLK14:
> +					clock_bits = 7;
> +					break;
> +			default:
> +					break;
> +			}
> +			shift = 16;
> +			break;
> +		case 4:
> +			switch (clock) {
> +			case QE_BRG12:
> +					clock_bits = 1;
> +					break;
> +			case QE_BRG13:
> +					clock_bits = 2;
> +					break;
> +			case QE_CLK23:
> +					clock_bits = 4;
> +					break;
> +			case QE_CLK24:
> +					clock_bits = 5;
> +					break;
> +			case QE_CLK11:
> +					clock_bits = 6;
> +					break;
> +			case QE_CLK16:
> +					clock_bits = 7;
> +					break;
> +			default:
> +					break;
> +			}
> +			shift = 28;
> +			break;
> +		case 5:
> +			switch (clock) {
> +			case QE_BRG12:
> +					clock_bits = 1;
> +					break;
> +			case QE_BRG13:
> +					clock_bits = 2;
> +					break;
> +			case QE_CLK23:
> +					clock_bits = 4;
> +					break;
> +			case QE_CLK24:
> +					clock_bits = 5;
> +					break;
> +			case QE_CLK13:
> +					clock_bits = 6;
> +					break;
> +			case QE_CLK18:
> +					clock_bits = 7;
> +					break;
> +			default:
> +					break;
> +			}
> +			shift = 24;
> +			break;
> +		case 6:
> +			switch (clock) {
> +			case QE_BRG12:
> +					clock_bits = 1;
> +					break;
> +			case QE_BRG13:
> +					clock_bits = 2;
> +					break;
> +			case QE_CLK23:
> +					clock_bits = 4;
> +					break;
> +			case QE_CLK24:
> +					clock_bits = 5;
> +					break;
> +			case QE_CLK15:
> +					clock_bits = 6;
> +					break;
> +			case QE_CLK20:
> +					clock_bits = 7;
> +					break;
> +			default:
> +					break;
> +			}
> +			shift = 20;
> +			break;
> +		case 7:
> +			switch (clock) {
> +			case QE_BRG12:
> +					clock_bits = 1;
> +					break;
> +			case QE_BRG13:
> +					clock_bits = 2;
> +					break;
> +			case QE_CLK23:
> +					clock_bits = 4;
> +					break;
> +			case QE_CLK24:
> +					clock_bits = 5;
> +					break;
> +			case QE_CLK17:
> +					clock_bits = 6;
> +					break;
> +			case QE_CLK22:
> +					clock_bits = 7;
> +					break;
> +			default:
> +					break;
> +			}
> +			shift = 16;
> +			break;
> +		default:
> +				break;
> +		}
> +		break;
> +	case COMM_DIR_TX:
> +		switch (tdm_num) {
> +		case 0:
> +			switch (clock) {
> +			case QE_BRG3:
> +					clock_bits = 1;
> +					break;
> +			case QE_BRG4:
> +					clock_bits = 2;
> +					break;
> +			case QE_CLK1:
> +					clock_bits = 4;
> +					break;
> +			case QE_CLK2:
> +					clock_bits = 5;
> +					break;
> +			case QE_CLK4:
> +					clock_bits = 6;
> +					break;
> +			case QE_CLK9:
> +					clock_bits = 7;
> +					break;
> +			default:
> +					break;
> +			}
> +			shift = 12;
> +			break;
> +		case 1:
> +			switch (clock) {
> +			case QE_BRG3:
> +					clock_bits = 1;
> +					break;
> +			case QE_BRG4:
> +					clock_bits = 2;
> +					break;
> +			case QE_CLK1:
> +					clock_bits = 4;
> +					break;
> +			case QE_CLK2:
> +					clock_bits = 5;
> +					break;
> +			case QE_CLK6:
> +					clock_bits = 6;
> +					break;
> +			case QE_CLK11:
> +					clock_bits = 7;
> +					break;
> +			default:
> +					break;
> +			}
> +			shift = 8;
> +			break;
> +		case 2:
> +			switch (clock) {
> +			case QE_BRG3:
> +					clock_bits = 1;
> +					break;
> +			case QE_BRG4:
> +					clock_bits = 2;
> +					break;
> +			case QE_CLK1:
> +					clock_bits = 4;
> +					break;
> +			case QE_CLK2:
> +					clock_bits = 5;
> +					break;
> +			case QE_CLK8:
> +					clock_bits = 6;
> +					break;
> +			case QE_CLK13:
> +					clock_bits = 7;
> +					break;
> +			default:
> +					break;
> +			}
> +			shift = 4;
> +			break;
> +		case 3:
> +			switch (clock) {
> +			case QE_BRG3:
> +					clock_bits = 1;
> +					break;
> +			case QE_BRG4:
> +					clock_bits = 2;
> +					break;
> +			case QE_CLK1:
> +					clock_bits = 4;
> +					break;
> +			case QE_CLK2:
> +					clock_bits = 5;
> +					break;
> +			case QE_CLK10:
> +					clock_bits = 6;
> +					break;
> +			case QE_CLK15:
> +					clock_bits = 7;
> +					break;
> +			default:
> +					break;
> +			}
> +			shift = 0;
> +			break;
> +		case 4:
> +			switch (clock) {
> +			case QE_BRG12:
> +					clock_bits = 1;
> +					break;
> +			case QE_BRG13:
> +					clock_bits = 2;
> +					break;
> +			case QE_CLK23:
> +					clock_bits = 4;
> +					break;
> +			case QE_CLK24:
> +					clock_bits = 5;
> +					break;
> +			case QE_CLK12:
> +					clock_bits = 6;
> +					break;
> +			case QE_CLK17:
> +					clock_bits = 7;
> +					break;
> +			default:
> +					break;
> +			}
> +			shift = 12;
> +			break;
> +		case 5:
> +			switch (clock) {
> +			case QE_BRG12:
> +					clock_bits = 1;
> +					break;
> +			case QE_BRG13:
> +					clock_bits = 2;
> +					break;
> +			case QE_CLK23:
> +					clock_bits = 4;
> +					break;
> +			case QE_CLK24:
> +					clock_bits = 5;
> +					break;
> +			case QE_CLK14:
> +					clock_bits = 6;
> +					break;
> +			case QE_CLK19:
> +					clock_bits = 7;
> +					break;
> +			default:
> +					break;
> +			}
> +			shift = 8;
> +			break;
> +		case 6:
> +			switch (clock) {
> +			case QE_BRG12:
> +					clock_bits = 1;
> +					break;
> +			case QE_BRG13:
> +					clock_bits = 2;
> +					break;
> +			case QE_CLK23:
> +					clock_bits = 4;
> +					break;
> +			case QE_CLK24:
> +					clock_bits = 5;
> +					break;
> +			case QE_CLK16:
> +					clock_bits = 6;
> +					break;
> +			case QE_CLK21:
> +					clock_bits = 7;
> +					break;
> +			default:
> +					break;
> +			}
> +			shift = 4;
> +			break;
> +		case 7:
> +			switch (clock) {
> +			case QE_BRG12:
> +					clock_bits = 1;
> +					break;
> +			case QE_BRG13:
> +					clock_bits = 2;
> +					break;
> +			case QE_CLK23:
> +					clock_bits = 4;
> +					break;
> +			case QE_CLK24:
> +					clock_bits = 5;
> +					break;
> +			case QE_CLK18:
> +					clock_bits = 6;
> +					break;
> +			case QE_CLK3:
> +					clock_bits = 7;
> +					break;
> +			default:
> +					break;
> +			}
> +			shift = 0;
> +			break;
> +		default:
> +			break;
> +		}
> +		break;
> +	default:
> +		break;
> +	}

Unnecessary "default"s.

Please consider reformatting this data into an array.

> +	if (!clock_bits)
> +		return -ENOENT;
> +
> +	cmxs1cr = (tdm_num < 4) ? (&qe_mux_reg->cmxsi1cr_l) :
> +				  (&qe_mux_reg->cmxsi1cr_h);

Unnecessary parentheses.

> +int ucc_set_tdm_rxtx_sync(u32 tdm_num, enum qe_clock clock,
> +		enum comm_dir mode)

Similar comments as the clock function above.

> +	clock_bits = (u32) source;

Unnecessary cast.

> +#ifdef CONFIG_FSL_UCC_TDM
> +	} else {
> +		/* tdm Rx clock routing */
> +		if ((uf_info->rx_clock != QE_CLK_NONE) &&
> +			ucc_set_tdm_rxtx_clk(uf_info->tdm_num,
> +				uf_info->rx_clock, COMM_DIR_RX)) {
> +			pr_err("%s: illegal value for RX clock", __func__);
> +			ucc_fast_free(uccf);
> +			return -EINVAL;
> +		}
> +
> +		/* tdm Tx clock routing */
> +		if ((uf_info->tx_clock != QE_CLK_NONE) &&
> +			ucc_set_tdm_rxtx_clk(uf_info->tdm_num,
> +				uf_info->tx_clock, COMM_DIR_TX)) {
> +			pr_err("%s:illegal value for TX clock", __func__);
> +			ucc_fast_free(uccf);
> +			return -EINVAL;
> +		}
> +
> +		/* tdm Rx sync clock routing */
> +		if ((uf_info->rx_sync != QE_CLK_NONE) &&
> +			ucc_set_tdm_rxtx_sync(uf_info->tdm_num,
> +				uf_info->rx_sync, COMM_DIR_RX)) {
> +			pr_err("%s:illegal value for TX clock", __func__);
> +			ucc_fast_free(uccf);
> +			return -EINVAL;
> +		}
> +
> +		/* tdm Tx sync clock routing */
> +		if ((uf_info->tx_sync != QE_CLK_NONE) &&
> +			ucc_set_tdm_rxtx_sync(uf_info->tdm_num,
> +				uf_info->tx_sync, COMM_DIR_TX)) {
> +			pr_err("%s:illegal value for TX clock", __func__);
> +			ucc_fast_free(uccf);
> +			return -EINVAL;
> +		}

Please be consistent with error formatting (space after colon), and
either make the error messages distinctive, or if it isn't worthwhile,
factor out the error code to the end and use goto.  You should probably
do that anyway, even if you print a distinctive error message first.

Also you should probably provide more info in the print regarding the
particular values and subdevices involved.

-Scott

Patch

diff --git a/arch/powerpc/include/asm/immap_qe.h b/arch/powerpc/include/asm/immap_qe.h
index bedbff8..c76ef30 100644
--- a/arch/powerpc/include/asm/immap_qe.h
+++ b/arch/powerpc/include/asm/immap_qe.h
@@ -159,10 +159,7 @@  struct spi {
 
 /* SI */
 struct si1 {
-	__be16	siamr1;		/* SI1 TDMA mode register */
-	__be16	sibmr1;		/* SI1 TDMB mode register */
-	__be16	sicmr1;		/* SI1 TDMC mode register */
-	__be16	sidmr1;		/* SI1 TDMD mode register */
+	__be16	sixmr1[4];	/* SI1 TDMx (x = A B C D) mode register */
 	u8	siglmr1_h;	/* SI1 global mode register high */
 	u8	res0[0x1];
 	u8	sicmdr1_h;	/* SI1 command register high */
diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h
index 32b9bfa..1c80fdc 100644
--- a/arch/powerpc/include/asm/qe.h
+++ b/arch/powerpc/include/asm/qe.h
@@ -1,5 +1,5 @@ 
 /*
- * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2006, 2014 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Authors: 	Shlomi Gridish <gridish@freescale.com>
  * 		Li Yang <leoli@freescale.com>
@@ -75,6 +75,8 @@  enum qe_clock {
 	QE_CLK22,		/* Clock 22 */
 	QE_CLK23,		/* Clock 23 */
 	QE_CLK24,		/* Clock 24 */
+	QE_RSYNC_PIN,		/* RSYNC from pin */
+	QE_TSYNC_PIN,		/* TSYNC from pin */
 	QE_CLK_DUMMY
 };
 
@@ -636,6 +638,15 @@  struct ucc_slow_pram {
 #define UCC_BISYNC_UCCE_TXB	0x0002
 #define UCC_BISYNC_UCCE_RXB	0x0001
 
+/* Transparent UCC Event Register (UCCE) */
+#define UCC_TRANS_UCCE_GRA	0x0080
+#define UCC_TRANS_UCCE_TXE	0x0010
+#define UCC_TRANS_UCCE_RXF	0x0008
+#define UCC_TRANS_UCCE_BSY	0x0004
+#define UCC_TRANS_UCCE_TXB	0x0002
+#define UCC_TRANS_UCCE_RXB	0x0001
+
+
 /* Gigabit Ethernet Fast UCC Event Register (UCCE) */
 #define UCC_GETH_UCCE_MPD       0x80000000
 #define UCC_GETH_UCCE_SCAR      0x40000000
diff --git a/arch/powerpc/include/asm/ucc.h b/arch/powerpc/include/asm/ucc.h
index 6927ac2..0a942c9 100644
--- a/arch/powerpc/include/asm/ucc.h
+++ b/arch/powerpc/include/asm/ucc.h
@@ -1,5 +1,5 @@ 
 /*
- * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2006, 2014 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Authors: 	Shlomi Gridish <gridish@freescale.com>
  * 		Li Yang <leoli@freescale.com>
@@ -41,6 +41,10 @@  int ucc_set_qe_mux_mii_mng(unsigned int ucc_num);
 
 int ucc_set_qe_mux_rxtx(unsigned int ucc_num, enum qe_clock clock,
 	enum comm_dir mode);
+int ucc_set_tdm_rxtx_clk(unsigned int tdm_num, enum qe_clock clock,
+	enum comm_dir mode);
+int ucc_set_tdm_rxtx_sync(unsigned int tdm_num, enum qe_clock clock,
+	enum comm_dir mode);
 
 int ucc_mux_set_grant_tsa_bkpt(unsigned int ucc_num, int set, u32 mask);
 
diff --git a/arch/powerpc/include/asm/ucc_fast.h b/arch/powerpc/include/asm/ucc_fast.h
index 72ea9ba..98e19d8 100644
--- a/arch/powerpc/include/asm/ucc_fast.h
+++ b/arch/powerpc/include/asm/ucc_fast.h
@@ -1,7 +1,7 @@ 
 /*
  * Internal header file for UCC FAST unit routines.
  *
- * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2006, 2014 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Authors: 	Shlomi Gridish <gridish@freescale.com>
  * 		Li Yang <leoli@freescale.com>
@@ -27,12 +27,15 @@ 
 #define R_I	0x10000000	/* interrupt on reception */
 #define R_L	0x08000000	/* last */
 #define R_F	0x04000000	/* first */
+#define R_CM	0x02000000	/* CM */
 
 /* transmit BD's status */
 #define T_R	0x80000000	/* ready bit */
 #define T_W	0x20000000	/* wrap bit */
 #define T_I	0x10000000	/* interrupt on completion */
 #define T_L	0x08000000	/* last */
+#define T_TC	0x04000000	/* crc */
+#define T_CM	0x02000000	/* CM */
 
 /* Rx Data buffer must be 4 bytes aligned in most cases */
 #define UCC_FAST_RX_ALIGN			4
@@ -118,9 +121,12 @@  enum ucc_fast_transparent_tcrc {
 /* Fast UCC initialization structure */
 struct ucc_fast_info {
 	int ucc_num;
+	int tdm_num;
 	enum qe_clock rx_clock;
 	enum qe_clock tx_clock;
-	u32 regs;
+	enum qe_clock rx_sync;
+	enum qe_clock tx_sync;
+	resource_size_t regs;
 	int irq;
 	u32 uccm_mask;
 	int bd_mem_part;
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 238a07b..9a9f733 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -1,5 +1,6 @@ 
 /*
- * Copyright (C) 2006-2010 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2006-2010, 2014 Freescale Semiconductor, Inc.
+ * All rights reserved.
  *
  * Authors: 	Shlomi Gridish <gridish@freescale.com>
  * 		Li Yang <leoli@freescale.com>
@@ -240,6 +241,12 @@  enum qe_clock qe_clock_source(const char *source)
 	if (strcasecmp(source, "none") == 0)
 		return QE_CLK_NONE;
 
+	if (strcasecmp(source, "tsync_pin") == 0)
+		return QE_TSYNC_PIN;
+
+	if (strcasecmp(source, "rsync_pin") == 0)
+		return QE_RSYNC_PIN;
+
 	if (strncasecmp(source, "brg", 3) == 0) {
 		i = simple_strtoul(source + 3, NULL, 10);
 		if ((i >= 1) && (i <= 16))
diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c
index 621575b..5c27e04 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc.c
@@ -3,7 +3,7 @@ 
  *
  * QE UCC API Set - UCC specific routines implementations.
  *
- * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2006, 2014 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Authors: 	Shlomi Gridish <gridish@freescale.com>
  * 		Li Yang <leoli@freescale.com>
@@ -210,3 +210,774 @@  int ucc_set_qe_mux_rxtx(unsigned int ucc_num, enum qe_clock clock,
 
 	return 0;
 }
+
+/* tdm_num: TDM A-H port num is 0-7 */
+int ucc_set_tdm_rxtx_clk(u32 tdm_num, enum qe_clock clock,
+		enum comm_dir mode)
+{
+	u32 clock_bits, shift;
+	struct qe_mux *qe_mux_reg;
+	 __be32 __iomem *cmxs1cr;
+
+	clock_bits = 0;
+	qe_mux_reg = &qe_immr->qmx;
+
+	if ((tdm_num > 7 || tdm_num < 0))
+		return -EINVAL;
+
+	/* The communications direction must be RX or TX */
+	if (!((mode == COMM_DIR_RX) || (mode == COMM_DIR_TX)))
+		return -EINVAL;
+
+	switch (mode) {
+	case COMM_DIR_RX:
+		switch (tdm_num) {
+		case 0:
+			switch (clock) {
+			case QE_BRG3:
+					clock_bits = 1;
+					break;
+			case QE_BRG4:
+					clock_bits = 2;
+					break;
+			case QE_CLK1:
+					clock_bits = 4;
+					break;
+			case QE_CLK2:
+					clock_bits = 5;
+					break;
+			case QE_CLK3:
+					clock_bits = 6;
+					break;
+			case QE_CLK8:
+					clock_bits = 7;
+					break;
+			default:
+					break;
+			}
+			shift = 28;
+			break;
+		case 1:
+			switch (clock) {
+			case QE_BRG3:
+					clock_bits = 1;
+					break;
+			case QE_BRG4:
+					clock_bits = 2;
+					break;
+			case QE_CLK1:
+					clock_bits = 4;
+					break;
+			case QE_CLK2:
+					clock_bits = 5;
+					break;
+			case QE_CLK5:
+					clock_bits = 6;
+					break;
+			case QE_CLK10:
+					clock_bits = 7;
+					break;
+			default:
+					break;
+			}
+			shift = 24;
+			break;
+		case 2:
+			switch (clock) {
+			case QE_BRG3:
+					clock_bits = 1;
+					break;
+			case QE_BRG4:
+					clock_bits = 2;
+					break;
+			case QE_CLK1:
+					clock_bits = 4;
+					break;
+			case QE_CLK2:
+					clock_bits = 5;
+					break;
+			case QE_CLK7:
+					clock_bits = 6;
+					break;
+			case QE_CLK12:
+					clock_bits = 7;
+					break;
+			default:
+					break;
+			}
+			shift = 20;
+			break;
+		case 3:
+			switch (clock) {
+			case QE_BRG3:
+					clock_bits = 1;
+					break;
+			case QE_BRG4:
+					clock_bits = 2;
+					break;
+			case QE_CLK1:
+					clock_bits = 4;
+					break;
+			case QE_CLK2:
+					clock_bits = 5;
+					break;
+			case QE_CLK9:
+					clock_bits = 6;
+					break;
+			case QE_CLK14:
+					clock_bits = 7;
+					break;
+			default:
+					break;
+			}
+			shift = 16;
+			break;
+		case 4:
+			switch (clock) {
+			case QE_BRG12:
+					clock_bits = 1;
+					break;
+			case QE_BRG13:
+					clock_bits = 2;
+					break;
+			case QE_CLK23:
+					clock_bits = 4;
+					break;
+			case QE_CLK24:
+					clock_bits = 5;
+					break;
+			case QE_CLK11:
+					clock_bits = 6;
+					break;
+			case QE_CLK16:
+					clock_bits = 7;
+					break;
+			default:
+					break;
+			}
+			shift = 28;
+			break;
+		case 5:
+			switch (clock) {
+			case QE_BRG12:
+					clock_bits = 1;
+					break;
+			case QE_BRG13:
+					clock_bits = 2;
+					break;
+			case QE_CLK23:
+					clock_bits = 4;
+					break;
+			case QE_CLK24:
+					clock_bits = 5;
+					break;
+			case QE_CLK13:
+					clock_bits = 6;
+					break;
+			case QE_CLK18:
+					clock_bits = 7;
+					break;
+			default:
+					break;
+			}
+			shift = 24;
+			break;
+		case 6:
+			switch (clock) {
+			case QE_BRG12:
+					clock_bits = 1;
+					break;
+			case QE_BRG13:
+					clock_bits = 2;
+					break;
+			case QE_CLK23:
+					clock_bits = 4;
+					break;
+			case QE_CLK24:
+					clock_bits = 5;
+					break;
+			case QE_CLK15:
+					clock_bits = 6;
+					break;
+			case QE_CLK20:
+					clock_bits = 7;
+					break;
+			default:
+					break;
+			}
+			shift = 20;
+			break;
+		case 7:
+			switch (clock) {
+			case QE_BRG12:
+					clock_bits = 1;
+					break;
+			case QE_BRG13:
+					clock_bits = 2;
+					break;
+			case QE_CLK23:
+					clock_bits = 4;
+					break;
+			case QE_CLK24:
+					clock_bits = 5;
+					break;
+			case QE_CLK17:
+					clock_bits = 6;
+					break;
+			case QE_CLK22:
+					clock_bits = 7;
+					break;
+			default:
+					break;
+			}
+			shift = 16;
+			break;
+		default:
+				break;
+		}
+		break;
+	case COMM_DIR_TX:
+		switch (tdm_num) {
+		case 0:
+			switch (clock) {
+			case QE_BRG3:
+					clock_bits = 1;
+					break;
+			case QE_BRG4:
+					clock_bits = 2;
+					break;
+			case QE_CLK1:
+					clock_bits = 4;
+					break;
+			case QE_CLK2:
+					clock_bits = 5;
+					break;
+			case QE_CLK4:
+					clock_bits = 6;
+					break;
+			case QE_CLK9:
+					clock_bits = 7;
+					break;
+			default:
+					break;
+			}
+			shift = 12;
+			break;
+		case 1:
+			switch (clock) {
+			case QE_BRG3:
+					clock_bits = 1;
+					break;
+			case QE_BRG4:
+					clock_bits = 2;
+					break;
+			case QE_CLK1:
+					clock_bits = 4;
+					break;
+			case QE_CLK2:
+					clock_bits = 5;
+					break;
+			case QE_CLK6:
+					clock_bits = 6;
+					break;
+			case QE_CLK11:
+					clock_bits = 7;
+					break;
+			default:
+					break;
+			}
+			shift = 8;
+			break;
+		case 2:
+			switch (clock) {
+			case QE_BRG3:
+					clock_bits = 1;
+					break;
+			case QE_BRG4:
+					clock_bits = 2;
+					break;
+			case QE_CLK1:
+					clock_bits = 4;
+					break;
+			case QE_CLK2:
+					clock_bits = 5;
+					break;
+			case QE_CLK8:
+					clock_bits = 6;
+					break;
+			case QE_CLK13:
+					clock_bits = 7;
+					break;
+			default:
+					break;
+			}
+			shift = 4;
+			break;
+		case 3:
+			switch (clock) {
+			case QE_BRG3:
+					clock_bits = 1;
+					break;
+			case QE_BRG4:
+					clock_bits = 2;
+					break;
+			case QE_CLK1:
+					clock_bits = 4;
+					break;
+			case QE_CLK2:
+					clock_bits = 5;
+					break;
+			case QE_CLK10:
+					clock_bits = 6;
+					break;
+			case QE_CLK15:
+					clock_bits = 7;
+					break;
+			default:
+					break;
+			}
+			shift = 0;
+			break;
+		case 4:
+			switch (clock) {
+			case QE_BRG12:
+					clock_bits = 1;
+					break;
+			case QE_BRG13:
+					clock_bits = 2;
+					break;
+			case QE_CLK23:
+					clock_bits = 4;
+					break;
+			case QE_CLK24:
+					clock_bits = 5;
+					break;
+			case QE_CLK12:
+					clock_bits = 6;
+					break;
+			case QE_CLK17:
+					clock_bits = 7;
+					break;
+			default:
+					break;
+			}
+			shift = 12;
+			break;
+		case 5:
+			switch (clock) {
+			case QE_BRG12:
+					clock_bits = 1;
+					break;
+			case QE_BRG13:
+					clock_bits = 2;
+					break;
+			case QE_CLK23:
+					clock_bits = 4;
+					break;
+			case QE_CLK24:
+					clock_bits = 5;
+					break;
+			case QE_CLK14:
+					clock_bits = 6;
+					break;
+			case QE_CLK19:
+					clock_bits = 7;
+					break;
+			default:
+					break;
+			}
+			shift = 8;
+			break;
+		case 6:
+			switch (clock) {
+			case QE_BRG12:
+					clock_bits = 1;
+					break;
+			case QE_BRG13:
+					clock_bits = 2;
+					break;
+			case QE_CLK23:
+					clock_bits = 4;
+					break;
+			case QE_CLK24:
+					clock_bits = 5;
+					break;
+			case QE_CLK16:
+					clock_bits = 6;
+					break;
+			case QE_CLK21:
+					clock_bits = 7;
+					break;
+			default:
+					break;
+			}
+			shift = 4;
+			break;
+		case 7:
+			switch (clock) {
+			case QE_BRG12:
+					clock_bits = 1;
+					break;
+			case QE_BRG13:
+					clock_bits = 2;
+					break;
+			case QE_CLK23:
+					clock_bits = 4;
+					break;
+			case QE_CLK24:
+					clock_bits = 5;
+					break;
+			case QE_CLK18:
+					clock_bits = 6;
+					break;
+			case QE_CLK3:
+					clock_bits = 7;
+					break;
+			default:
+					break;
+			}
+			shift = 0;
+			break;
+		default:
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+
+	if (!clock_bits)
+		return -ENOENT;
+
+	cmxs1cr = (tdm_num < 4) ? (&qe_mux_reg->cmxsi1cr_l) :
+				  (&qe_mux_reg->cmxsi1cr_h);
+
+	clrsetbits_be32(cmxs1cr, QE_CMXUCR_TX_CLK_SRC_MASK << shift,
+		   clock_bits << shift);
+
+	return 0;
+}
+
+
+int ucc_set_tdm_rxtx_sync(u32 tdm_num, enum qe_clock clock,
+		enum comm_dir mode)
+{
+	u32 shift, clock_bits;
+	struct qe_mux *qe_mux_reg;
+	int source;
+
+	source = 0;
+	shift = 0;
+	qe_mux_reg = &qe_immr->qmx;
+
+	if ((tdm_num > 7 || tdm_num < 0))
+		return -EINVAL;
+
+	/* The communications direction must be RX or TX */
+	if (!((mode == COMM_DIR_RX) || (mode == COMM_DIR_TX)))
+		return -EINVAL;
+
+	switch (mode) {
+	case COMM_DIR_RX:
+		switch (tdm_num) {
+		case 0:
+			switch (clock) {
+			case QE_RSYNC_PIN:
+					source = 0;
+					break;
+			case QE_BRG9:
+					source = 1;
+					break;
+			case QE_BRG10:
+					source = 2;
+					break;
+			default:
+					source = -1;
+					break;
+			}
+			shift = 30;
+			break;
+		case 1:
+			switch (clock) {
+			case QE_RSYNC_PIN:
+					source = 0;
+					break;
+			case QE_BRG9:
+					source = 1;
+					break;
+			case QE_BRG10:
+					source = 2;
+					break;
+			default:
+					source = -1;
+					break;
+			}
+			shift = 28;
+			break;
+		case 2:
+			switch (clock) {
+			case QE_RSYNC_PIN:
+					source = 0;
+					break;
+			case QE_BRG9:
+					source = 1;
+					break;
+			case QE_BRG11:
+					source = 2;
+					break;
+			default:
+					source = -1;
+					break;
+			}
+			shift = 26;
+			break;
+		case 3:
+			switch (clock) {
+			case QE_RSYNC_PIN:
+					source = 0;
+					break;
+			case QE_BRG9:
+					source = 1;
+					break;
+			case QE_BRG11:
+					source = 2;
+					break;
+			default:
+					source = -1;
+					break;
+			}
+			shift = 24;
+			break;
+		case 4:
+			switch (clock) {
+			case QE_RSYNC_PIN:
+					source = 0;
+					break;
+			case QE_BRG13:
+					source = 1;
+					break;
+			case QE_BRG14:
+					source = 2;
+					break;
+			default:
+					source = -1;
+					break;
+			}
+			shift = 22;
+			break;
+		case 5:
+			switch (clock) {
+			case QE_RSYNC_PIN:
+					source = 0;
+					break;
+			case QE_BRG13:
+					source = 1;
+					break;
+			case QE_BRG14:
+					source = 2;
+					break;
+			default:
+					source = -1;
+					break;
+			}
+			shift = 20;
+			break;
+		case 6:
+			switch (clock) {
+			case QE_RSYNC_PIN:
+					source = 0;
+					break;
+			case QE_BRG13:
+					source = 1;
+					break;
+			case QE_BRG15:
+					source = 2;
+					break;
+			default:
+					source = -1;
+					break;
+			}
+			shift = 18;
+			break;
+		case 7:
+			switch (clock) {
+			case QE_RSYNC_PIN:
+					source = 0;
+					break;
+			case QE_BRG13:
+					source = 1;
+					break;
+			case QE_BRG15:
+					source = 2;
+					break;
+			default:
+					source = -1;
+					break;
+			}
+			shift = 16;
+			break;
+		default:
+			source = -1;
+			break;
+		}
+		break;
+	case COMM_DIR_TX:
+		switch (tdm_num) {
+		case 0:
+			switch (clock) {
+			case QE_TSYNC_PIN:
+					source = 0;
+					break;
+			case QE_BRG9:
+					source = 1;
+					break;
+			case QE_BRG10:
+					source = 2;
+					break;
+			default:
+					source = -1;
+					break;
+			}
+			shift = 14;
+			break;
+		case 1:
+			switch (clock) {
+			case QE_TSYNC_PIN:
+					source = 0;
+					break;
+			case QE_BRG9:
+					source = 1;
+					break;
+			case QE_BRG10:
+					source = 2;
+					break;
+			default:
+					source = -1;
+					break;
+			}
+			shift = 12;
+			break;
+		case 2:
+			switch (clock) {
+			case QE_TSYNC_PIN:
+					source = 0;
+					break;
+			case QE_BRG9:
+					source = 1;
+					break;
+			case QE_BRG11:
+					source = 2;
+					break;
+			default:
+					source = -1;
+					break;
+			}
+			shift = 10;
+			break;
+		case 3:
+			switch (clock) {
+			case QE_TSYNC_PIN:
+					source = 0;
+					break;
+			case QE_BRG9:
+					source = 1;
+					break;
+			case QE_BRG11:
+					source = 2;
+					break;
+			default:
+					source = -1;
+					break;
+			}
+			shift = 8;
+			break;
+		case 4:
+			switch (clock) {
+			case QE_TSYNC_PIN:
+					source = 0;
+					break;
+			case QE_BRG13:
+					source = 1;
+					break;
+			case QE_BRG14:
+					source = 2;
+					break;
+			default:
+					source = -1;
+					break;
+			}
+			shift = 6;
+			break;
+		case 5:
+			switch (clock) {
+			case QE_TSYNC_PIN:
+					source = 0;
+					break;
+			case QE_BRG13:
+					source = 1;
+					break;
+			case QE_BRG14:
+					source = 2;
+					break;
+			default:
+					source = -1;
+					break;
+			}
+			shift = 4;
+			break;
+		case 6:
+			switch (clock) {
+			case QE_TSYNC_PIN:
+					source = 0;
+					break;
+			case QE_BRG13:
+					source = 1;
+					break;
+			case QE_BRG15:
+					source = 2;
+					break;
+			default:
+					source = -1;
+					break;
+			}
+			shift = 2;
+			break;
+		case 7:
+			switch (clock) {
+			case QE_TSYNC_PIN:
+					source = 0;
+					break;
+			case QE_BRG13:
+					source = 1;
+					break;
+			case QE_BRG15:
+					source = 2;
+					break;
+			default:
+					source = -1;
+					break;
+			}
+			shift = 0;
+			break;
+
+		default:
+			source = -1;
+			break;
+		}
+		break;
+	default:
+		source = -1;
+		break;
+	}
+
+	if (source == -1)
+		return -ENOENT;
+
+	clock_bits = (u32) source;
+
+	clrsetbits_be32(&qe_mux_reg->cmxsi1syr,
+			QE_CMXUCR_TX_CLK_SRC_MASK << shift,
+			clock_bits << shift);
+
+	return 0;
+}
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
index 65aaf15..16b88d6 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
@@ -1,5 +1,5 @@ 
 /*
- * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2006, 2014 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Authors: 	Shlomi Gridish <gridish@freescale.com>
  * 		Li Yang <leoli@freescale.com>
@@ -327,6 +327,44 @@  int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
 			ucc_fast_free(uccf);
 			return -EINVAL;
 		}
+#ifdef CONFIG_FSL_UCC_TDM
+	} else {
+		/* tdm Rx clock routing */
+		if ((uf_info->rx_clock != QE_CLK_NONE) &&
+			ucc_set_tdm_rxtx_clk(uf_info->tdm_num,
+				uf_info->rx_clock, COMM_DIR_RX)) {
+			pr_err("%s: illegal value for RX clock", __func__);
+			ucc_fast_free(uccf);
+			return -EINVAL;
+		}
+
+		/* tdm Tx clock routing */
+		if ((uf_info->tx_clock != QE_CLK_NONE) &&
+			ucc_set_tdm_rxtx_clk(uf_info->tdm_num,
+				uf_info->tx_clock, COMM_DIR_TX)) {
+			pr_err("%s:illegal value for TX clock", __func__);
+			ucc_fast_free(uccf);
+			return -EINVAL;
+		}
+
+		/* tdm Rx sync clock routing */
+		if ((uf_info->rx_sync != QE_CLK_NONE) &&
+			ucc_set_tdm_rxtx_sync(uf_info->tdm_num,
+				uf_info->rx_sync, COMM_DIR_RX)) {
+			pr_err("%s:illegal value for TX clock", __func__);
+			ucc_fast_free(uccf);
+			return -EINVAL;
+		}
+
+		/* tdm Tx sync clock routing */
+		if ((uf_info->tx_sync != QE_CLK_NONE) &&
+			ucc_set_tdm_rxtx_sync(uf_info->tdm_num,
+				uf_info->tx_sync, COMM_DIR_TX)) {
+			pr_err("%s:illegal value for TX clock", __func__);
+			ucc_fast_free(uccf);
+			return -EINVAL;
+		}
+#endif
 	}
 
 	/* Set interrupt mask register at UCC level. */