void scc2_lineif(struct uart_cpm_port *pinfo) { /* * STx GP3 uses the SCC2 secondary option pin assignment * which this driver doesn't account for in the static * pin assignments. This kind of board specific info * really has to get out of the driver so boards can * be supported in a sane fashion. */ volatile cpmux_t *cpmux = cpm2_map(im_cpmux); #ifndef CONFIG_STX_GP3 volatile iop_cpm2_t *io = cpm2_map(im_ioport); io->iop_pparb |= 0x008b0000; io->iop_pdirb |= 0x00880000; io->iop_psorb |= 0x00880000; io->iop_pdirb &= ~0x00030000; io->iop_psorb &= ~0x00030000; #endif 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_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; 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_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 */ cpmux->cmx_scr &= 0xffffff00; cpmux->cmx_scr |= 0x0000001b; pinfo->brg = 4; cpm2_unmap(cpmux); cpm2_unmap(io); }
void smc2_lineif(struct uart_cpm_port *pinfo) { 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; io->iop_pdira |= 0x00400000; io->iop_pdira &= ~0x00800000; io->iop_psora &= ~0x00c00000; /* Wire BRG2 to SMC2 */ cpmux->cmx_smr &= 0xf0; pinfo->brg = 2; cpm2_unmap(cpmux); cpm2_unmap(io); }
void smc1_lineif(struct uart_cpm_port *pinfo) { 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; io->iop_pdird |= 0x00400000; io->iop_pdird &= ~0x00800000; io->iop_psord &= ~0x00c00000; /* Wire BRG1 to SMC1 */ cpmux->cmx_smr &= 0x0f; pinfo->brg = 1; cpm2_unmap(cpmux); cpm2_unmap(io); }
int cpm2_smc_clk_setup(enum cpm_clk_target target, int clock) { int ret = 0; int shift; int i, bits = 0; cpmux_t __iomem *im_cpmux; u8 __iomem *reg; u8 mask = 3; u8 clk_map[][3] = { {CPM_CLK_SMC1, CPM_BRG1, 0}, {CPM_CLK_SMC1, CPM_BRG7, 1}, {CPM_CLK_SMC1, CPM_CLK7, 2}, {CPM_CLK_SMC1, CPM_CLK9, 3}, {CPM_CLK_SMC2, CPM_BRG2, 0}, {CPM_CLK_SMC2, CPM_BRG8, 1}, {CPM_CLK_SMC2, CPM_CLK4, 2}, {CPM_CLK_SMC2, CPM_CLK15, 3}, }; im_cpmux = cpm2_map(im_cpmux); switch (target) { case CPM_CLK_SMC1: reg = &im_cpmux->cmx_smr; mask = 3; shift = 4; break; case CPM_CLK_SMC2: reg = &im_cpmux->cmx_smr; mask = 3; shift = 0; break; default: printk(KERN_ERR "cpm2_smc_clock_setup: invalid clock target\n"); return -EINVAL; } 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)) ret = -EINVAL; bits <<= shift; mask <<= shift; out_8(reg, (in_8(reg) & ~mask) | bits); cpm2_unmap(im_cpmux); return ret; }
void scc1_lineif(struct uart_cpm_port *pinfo) { 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; io->iop_psord &= ~0x00000001; /* Rx */ io->iop_psord |= 0x00000002; /* Tx */ io->iop_pdird &= ~0x00000001; /* Rx */ io->iop_pdird |= 0x00000002; /* Tx */ /* Wire BRG1 to SCC1 */ cpmux->cmx_scr &= 0x00ffffff; cpmux->cmx_scr |= 0x00000000; pinfo->brg = 1; cpm2_unmap(cpmux); cpm2_unmap(io); }
/* This function is used by UARTS, or anything else that uses a 16x * oversampled clock. */ void cpm_setbrg(uint brg, uint rate) { u32 __iomem *bp; /* This is good enough to get SMCs running..... */ if (brg < 4) { bp = cpm2_map_size(im_brgc1, 16); } else { bp = cpm2_map_size(im_brgc5, 16); brg -= 4; } bp += brg; out_be32(bp, (((BRG_UART_CLK / rate) - 1) << 1) | CPM_BRG_EN); cpm2_unmap(bp); }
/* 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 = cpm2_map_size(im_brgc1, 16); } else { 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 * clocks. */ void cpm2_fastbrg(uint brg, uint rate, int div16) { volatile uint *bp; if (brg < 4) { bp = cpm2_map_size(im_brgc1, 16); } else { 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); }
/* This function is used to set high speed synchronous baud rate * clocks. */ void cpm2_fastbrg(uint brg, uint rate, int div16) { u32 __iomem *bp; u32 val; if (brg < 4) { bp = cpm2_map_size(im_brgc1, 16); } else { bp = cpm2_map_size(im_brgc5, 16); brg -= 4; } bp += brg; val = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN; if (div16) val |= CPM_BRG_DIV16; out_be32(bp, val); cpm2_unmap(bp); }
void __cpm2_setbrg(uint brg, uint rate, uint clk, int div16, int src) { u32 __iomem *bp; u32 val; if (brg < 4) { bp = cpm2_map_size(im_brgc1, 16); } else { bp = cpm2_map_size(im_brgc5, 16); brg -= 4; } bp += brg; val = (((clk * 2 / rate) - 1) & ~1) | CPM_BRG_EN | src; if (div16) val |= CPM_BRG_DIV16; out_be32(bp, val); cpm2_unmap(bp); }
void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) { ulong val; int line = port - cpm_uart_ports; volatile cpm_cpm2_t *cp = cpm2_map(im_cpm); switch (line) { case UART_SMC1: val = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0, cmd) | CPM_CR_FLG; break; case UART_SMC2: val = mk_cr_cmd(CPM_CR_SMC2_PAGE, CPM_CR_SMC2_SBLOCK, 0, cmd) | CPM_CR_FLG; break; case UART_SCC1: val = mk_cr_cmd(CPM_CR_SCC1_PAGE, CPM_CR_SCC1_SBLOCK, 0, cmd) | CPM_CR_FLG; break; case UART_SCC2: val = mk_cr_cmd(CPM_CR_SCC2_PAGE, CPM_CR_SCC2_SBLOCK, 0, cmd) | CPM_CR_FLG; break; case UART_SCC3: val = mk_cr_cmd(CPM_CR_SCC3_PAGE, CPM_CR_SCC3_SBLOCK, 0, cmd) | CPM_CR_FLG; break; case UART_SCC4: val = mk_cr_cmd(CPM_CR_SCC4_PAGE, CPM_CR_SCC4_SBLOCK, 0, cmd) | CPM_CR_FLG; break; default: return; } cp->cp_cpcr = val; while (cp->cp_cpcr & CPM_CR_FLG) ; cpm2_unmap(cp); }
/* 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. */ void __cpm2_setbrg(uint brg, uint rate, uint clk, int div16, int src) { u32 __iomem *bp; u32 val; /* This is good enough to get SMCs running..... */ if (brg < 4) { bp = cpm2_map_size(im_brgc1, 16); } else { bp = cpm2_map_size(im_brgc5, 16); brg -= 4; } bp += brg; val = (((clk / rate) - 1) << 1) | CPM_BRG_EN | src; if (div16) val |= CPM_BRG_DIV16; out_be32(bp, val); 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 __iomem *im_cpmux; u32 __iomem *reg; u32 mask = 7; u8 clk_map[][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}, {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_CLK11, 4}, {CPM_CLK_SCC1, CPM_CLK12, 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_CLK11, 4}, {CPM_CLK_SCC2, CPM_CLK12, 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}, }; im_cpmux = cpm2_map(im_cpmux); switch (target) { case CPM_CLK_SCC1: reg = &im_cpmux->cmx_scr; shift = 24; break; 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 < 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)) ret = -EINVAL; bits <<= shift; mask <<= shift; out_be32(reg, (in_be32(reg) & ~mask) | bits); cpm2_unmap(im_cpmux); return ret; }
/* 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) u16 *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_map(im_smc[0]); cpm_uart_ports[UART_SMC1].port.mapbase = (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(); cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1; #endif #ifdef CONFIG_SERIAL_CPM_SMC2 cpm_uart_ports[UART_SMC2].smcp = (smc_t *) cpm2_map(im_smc[1]); cpm_uart_ports[UART_SMC2].port.mapbase = (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(); cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2; #endif #ifdef CONFIG_SERIAL_CPM_SCC1 cpm_uart_ports[UART_SCC1].sccp = (scc_t *) cpm2_map(im_scc[0]); cpm_uart_ports[UART_SCC1].port.mapbase = (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 &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); cpm_uart_ports[UART_SCC1].port.uartclk = uart_clock(); cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1; #endif #ifdef CONFIG_SERIAL_CPM_SCC2 cpm_uart_ports[UART_SCC2].sccp = (scc_t *) cpm2_map(im_scc[1]); cpm_uart_ports[UART_SCC2].port.mapbase = (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 &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); cpm_uart_ports[UART_SCC2].port.uartclk = uart_clock(); cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2; #endif #ifdef CONFIG_SERIAL_CPM_SCC3 cpm_uart_ports[UART_SCC3].sccp = (scc_t *) cpm2_map(im_scc[2]); cpm_uart_ports[UART_SCC3].port.mapbase = (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 &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); cpm_uart_ports[UART_SCC3].port.uartclk = uart_clock(); cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3; #endif #ifdef CONFIG_SERIAL_CPM_SCC4 cpm_uart_ports[UART_SCC4].sccp = (scc_t *) cpm2_map(im_scc[3]); cpm_uart_ports[UART_SCC4].port.mapbase = (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 &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); cpm_uart_ports[UART_SCC4].port.uartclk = uart_clock(); cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4; #endif return 0; }
void init_fcc_ioports(struct fs_platform_info *fpi) { struct io_port *io = cpm2_map(im_ioport); int fcc_no = fs_get_fcc_index(fpi->fs_no); int target; u32 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 &= ~(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 &= ~(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 |= (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 FCC bits to zero, * then set the ones we want. */ cpm2_clk_setup(target, fpi->clk_rx, CPM_CLK_RX); cpm2_clk_setup(target, fpi->clk_tx, CPM_CLK_TX); }