aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/sysdev/commproc.c201
-rw-r--r--include/asm-powerpc/commproc.h49
2 files changed, 250 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/commproc.c b/arch/powerpc/sysdev/commproc.c
index f8f3741acd8..428eb8c151b 100644
--- a/arch/powerpc/sysdev/commproc.c
+++ b/arch/powerpc/sysdev/commproc.c
@@ -397,3 +397,204 @@ uint cpm_dpram_phys(u8 *addr)
return (dpram_pbase + (uint)(addr - dpram_vbase));
}
EXPORT_SYMBOL(cpm_dpram_phys);
+
+struct cpm_ioport16 {
+ __be16 dir, par, sor, dat, intr;
+ __be16 res[3];
+};
+
+struct cpm_ioport32 {
+ __be32 dir, par, sor;
+};
+
+static void cpm1_set_pin32(int port, int pin, int flags)
+{
+ struct cpm_ioport32 __iomem *iop;
+ pin = 1 << (31 - pin);
+
+ if (port == CPM_PORTB)
+ iop = (struct cpm_ioport32 __iomem *)
+ &mpc8xx_immr->im_cpm.cp_pbdir;
+ else
+ iop = (struct cpm_ioport32 __iomem *)
+ &mpc8xx_immr->im_cpm.cp_pedir;
+
+ if (flags & CPM_PIN_OUTPUT)
+ setbits32(&iop->dir, pin);
+ else
+ clrbits32(&iop->dir, pin);
+
+ if (!(flags & CPM_PIN_GPIO))
+ setbits32(&iop->par, pin);
+ else
+ clrbits32(&iop->par, pin);
+
+ if (port == CPM_PORTE) {
+ if (flags & CPM_PIN_SECONDARY)
+ setbits32(&iop->sor, pin);
+ else
+ clrbits32(&iop->sor, pin);
+
+ if (flags & CPM_PIN_OPENDRAIN)
+ setbits32(&mpc8xx_immr->im_cpm.cp_peodr, pin);
+ else
+ clrbits32(&mpc8xx_immr->im_cpm.cp_peodr, pin);
+ }
+}
+
+static void cpm1_set_pin16(int port, int pin, int flags)
+{
+ struct cpm_ioport16 __iomem *iop =
+ (struct cpm_ioport16 __iomem *)&mpc8xx_immr->im_ioport;
+
+ pin = 1 << (15 - pin);
+
+ if (port != 0)
+ iop += port - 1;
+
+ if (flags & CPM_PIN_OUTPUT)
+ setbits16(&iop->dir, pin);
+ else
+ clrbits16(&iop->dir, pin);
+
+ if (!(flags & CPM_PIN_GPIO))
+ setbits16(&iop->par, pin);
+ else
+ clrbits16(&iop->par, pin);
+
+ if (port == CPM_PORTC) {
+ if (flags & CPM_PIN_SECONDARY)
+ setbits16(&iop->sor, pin);
+ else
+ clrbits16(&iop->sor, pin);
+ }
+}
+
+void cpm1_set_pin(enum cpm_port port, int pin, int flags)
+{
+ if (port == CPM_PORTB || port == CPM_PORTE)
+ cpm1_set_pin32(port, pin, flags);
+ else
+ cpm1_set_pin16(port, pin, flags);
+}
+
+int cpm1_clk_setup(enum cpm_clk_target target, int clock, int mode)
+{
+ int shift;
+ int i, bits = 0;
+ u32 __iomem *reg;
+ u32 mask = 7;
+
+ u8 clk_map[][3] = {
+ {CPM_CLK_SCC1, CPM_BRG1, 0},
+ {CPM_CLK_SCC1, CPM_BRG2, 1},
+ {CPM_CLK_SCC1, CPM_BRG3, 2},
+ {CPM_CLK_SCC1, CPM_BRG4, 3},
+ {CPM_CLK_SCC1, CPM_CLK1, 4},
+ {CPM_CLK_SCC1, CPM_CLK2, 5},
+ {CPM_CLK_SCC1, CPM_CLK3, 6},
+ {CPM_CLK_SCC1, CPM_CLK4, 7},
+
+ {CPM_CLK_SCC2, CPM_BRG1, 0},
+ {CPM_CLK_SCC2, CPM_BRG2, 1},
+ {CPM_CLK_SCC2, CPM_BRG3, 2},
+ {CPM_CLK_SCC2, CPM_BRG4, 3},
+ {CPM_CLK_SCC2, CPM_CLK1, 4},
+ {CPM_CLK_SCC2, CPM_CLK2, 5},
+ {CPM_CLK_SCC2, CPM_CLK3, 6},
+ {CPM_CLK_SCC2, CPM_CLK4, 7},
+
+ {CPM_CLK_SCC3, CPM_BRG1, 0},
+ {CPM_CLK_SCC3, CPM_BRG2, 1},
+ {CPM_CLK_SCC3, CPM_BRG3, 2},
+ {CPM_CLK_SCC3, CPM_BRG4, 3},
+ {CPM_CLK_SCC3, CPM_CLK5, 4},
+ {CPM_CLK_SCC3, CPM_CLK6, 5},
+ {CPM_CLK_SCC3, CPM_CLK7, 6},
+ {CPM_CLK_SCC3, CPM_CLK8, 7},
+
+ {CPM_CLK_SCC4, CPM_BRG1, 0},
+ {CPM_CLK_SCC4, CPM_BRG2, 1},
+ {CPM_CLK_SCC4, CPM_BRG3, 2},
+ {CPM_CLK_SCC4, CPM_BRG4, 3},
+ {CPM_CLK_SCC4, CPM_CLK5, 4},
+ {CPM_CLK_SCC4, CPM_CLK6, 5},
+ {CPM_CLK_SCC4, CPM_CLK7, 6},
+ {CPM_CLK_SCC4, CPM_CLK8, 7},
+
+ {CPM_CLK_SMC1, CPM_BRG1, 0},
+ {CPM_CLK_SMC1, CPM_BRG2, 1},
+ {CPM_CLK_SMC1, CPM_BRG3, 2},
+ {CPM_CLK_SMC1, CPM_BRG4, 3},
+ {CPM_CLK_SMC1, CPM_CLK1, 4},
+ {CPM_CLK_SMC1, CPM_CLK2, 5},
+ {CPM_CLK_SMC1, CPM_CLK3, 6},
+ {CPM_CLK_SMC1, CPM_CLK4, 7},
+
+ {CPM_CLK_SMC2, CPM_BRG1, 0},
+ {CPM_CLK_SMC2, CPM_BRG2, 1},
+ {CPM_CLK_SMC2, CPM_BRG3, 2},
+ {CPM_CLK_SMC2, CPM_BRG4, 3},
+ {CPM_CLK_SMC2, CPM_CLK5, 4},
+ {CPM_CLK_SMC2, CPM_CLK6, 5},
+ {CPM_CLK_SMC2, CPM_CLK7, 6},
+ {CPM_CLK_SMC2, CPM_CLK8, 7},
+ };
+
+ switch (target) {
+ case CPM_CLK_SCC1:
+ reg = &mpc8xx_immr->im_cpm.cp_sicr;
+ shift = 0;
+ break;
+
+ case CPM_CLK_SCC2:
+ reg = &mpc8xx_immr->im_cpm.cp_sicr;
+ shift = 8;
+ break;
+
+ case CPM_CLK_SCC3:
+ reg = &mpc8xx_immr->im_cpm.cp_sicr;
+ shift = 16;
+ break;
+
+ case CPM_CLK_SCC4:
+ reg = &mpc8xx_immr->im_cpm.cp_sicr;
+ shift = 24;
+ break;
+
+ case CPM_CLK_SMC1:
+ reg = &mpc8xx_immr->im_cpm.cp_simode;
+ shift = 12;
+ break;
+
+ case CPM_CLK_SMC2:
+ reg = &mpc8xx_immr->im_cpm.cp_simode;
+ shift = 28;
+ break;
+
+ default:
+ printk(KERN_ERR "cpm1_clock_setup: invalid clock target\n");
+ return -EINVAL;
+ }
+
+ if (reg == &mpc8xx_immr->im_cpm.cp_sicr && mode == CPM_CLK_RX)
+ shift += 3;
+
+ for (i = 0; i < ARRAY_SIZE(clk_map); i++) {
+ if (clk_map[i][0] == target && clk_map[i][1] == clock) {
+ bits = clk_map[i][2];
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(clk_map)) {
+ printk(KERN_ERR "cpm1_clock_setup: invalid clock combination\n");
+ return -EINVAL;
+ }
+
+ bits <<= shift;
+ mask <<= shift;
+ out_be32(reg, (in_be32(reg) & ~mask) | bits);
+
+ return 0;
+}
diff --git a/include/asm-powerpc/commproc.h b/include/asm-powerpc/commproc.h
index 86fcf265c54..5dec32404fa 100644
--- a/include/asm-powerpc/commproc.h
+++ b/include/asm-powerpc/commproc.h
@@ -691,4 +691,53 @@ extern void cpm_free_handler(int vec);
#define IMAP_ADDR (get_immrbase())
+#define CPM_PIN_INPUT 0
+#define CPM_PIN_OUTPUT 1
+#define CPM_PIN_PRIMARY 0
+#define CPM_PIN_SECONDARY 2
+#define CPM_PIN_GPIO 4
+#define CPM_PIN_OPENDRAIN 8
+
+enum cpm_port {
+ CPM_PORTA,
+ CPM_PORTB,
+ CPM_PORTC,
+ CPM_PORTD,
+ CPM_PORTE,
+};
+
+void cpm1_set_pin(enum cpm_port port, int pin, int flags);
+
+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_SMC1,
+ CPM_CLK_SMC2,
+};
+
+enum cpm_clk {
+ 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_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 */
+};
+
+int cpm1_clk_setup(enum cpm_clk_target target, int clock, int mode);
+
#endif /* __CPM_8XX__ */