/* * Generate a break. */ static void cpm_uart_break_ctl(struct uart_port *port, int break_state) { struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; pr_debug("CPM uart[%d]:break ctrl, break_state: %d\n", port->line, break_state); if (break_state) cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX); else cpm_line_cr_cmd(pinfo, CPM_CR_RESTART_TX); }
static void cpm_uart_init_scc(struct uart_cpm_port *pinfo) { int line = pinfo - cpm_uart_ports; volatile scc_t *scp; volatile scc_uart_t *sup; pr_debug("CPM uart[%d]:init_scc\n", pinfo->port.line); scp = pinfo->sccp; sup = pinfo->sccup; /* Store address */ pinfo->sccup->scc_genscc.scc_rbase = (unsigned char *)pinfo->rx_bd_base - DPRAM_BASE; pinfo->sccup->scc_genscc.scc_tbase = (unsigned char *)pinfo->tx_bd_base - DPRAM_BASE; /* Set up the uart parameters in the * parameter ram. */ cpm_set_scc_fcr(sup); sup->scc_genscc.scc_mrblr = pinfo->rx_fifosize; sup->scc_maxidl = pinfo->rx_fifosize; sup->scc_brkcr = 1; sup->scc_parec = 0; sup->scc_frmec = 0; sup->scc_nosec = 0; sup->scc_brkec = 0; sup->scc_uaddr1 = 0; sup->scc_uaddr2 = 0; sup->scc_toseq = 0; sup->scc_char1 = 0x8000; sup->scc_char2 = 0x8000; sup->scc_char3 = 0x8000; sup->scc_char4 = 0x8000; sup->scc_char5 = 0x8000; sup->scc_char6 = 0x8000; sup->scc_char7 = 0x8000; sup->scc_char8 = 0x8000; sup->scc_rccm = 0xc0ff; /* Send the CPM an initialize command. */ cpm_line_cr_cmd(line, CPM_CR_INIT_TRX); /* Set UART mode, 8 bit, no parity, one stop. * Enable receive and transmit. */ scp->scc_gsmrh = 0; scp->scc_gsmrl = (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16); /* Enable rx interrupts and clear all pending events. */ scp->scc_sccm = 0; scp->scc_scce = 0xffff; scp->scc_dsr = 0x7e7e; scp->scc_psmr = 0x3000; scp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); }
static int cpm_uart_startup(struct uart_port *port) { int retval; struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; int line = pinfo - cpm_uart_ports; pr_debug("CPM uart[%d]:startup\n", port->line); /* Install interrupt handler. */ retval = request_irq(port->irq, cpm_uart_int, 0, "cpm_uart", port); if (retval) return retval; /* Startup rx-int */ if (IS_SMC(pinfo)) { pinfo->smcp->smc_smcm |= SMCM_RX; pinfo->smcp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN); } else { pinfo->sccp->scc_sccm |= UART_SCCM_RX; pinfo->sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); } if (!(pinfo->flags & FLAG_CONSOLE)) cpm_line_cr_cmd(line,CPM_CR_INIT_TRX); return 0; }
static int cpm_uart_startup(struct uart_port *port) { int retval; struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; pr_debug("CPM uart[%d]:startup\n", port->line); /* If the port is not the console, make sure rx is disabled. */ if (!(pinfo->flags & FLAG_CONSOLE)) { /* Disable UART rx */ if (IS_SMC(pinfo)) { clrbits16(&pinfo->smcp->smc_smcmr, SMCMR_REN); clrbits8(&pinfo->smcp->smc_smcm, SMCM_RX); } else { clrbits32(&pinfo->sccp->scc_gsmrl, SCC_GSMRL_ENR); clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_RX); } cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX); } /* Install interrupt handler. */ retval = request_irq(port->irq, cpm_uart_int, 0, "cpm_uart", port); if (retval) return retval; /* Startup rx-int */ if (IS_SMC(pinfo)) { setbits8(&pinfo->smcp->smc_smcm, SMCM_RX); setbits16(&pinfo->smcp->smc_smcmr, (SMCMR_REN | SMCMR_TEN)); } else { setbits16(&pinfo->sccp->scc_sccm, UART_SCCM_RX); setbits32(&pinfo->sccp->scc_gsmrl, (SCC_GSMRL_ENR | SCC_GSMRL_ENT)); } return 0; }
/* * Shutdown the uart */ static void cpm_uart_shutdown(struct uart_port *port) { struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; int line = pinfo - cpm_uart_ports; pr_debug("CPM uart[%d]:shutdown\n", port->line); /* free interrupt handler */ free_irq(port->irq, port); /* If the port is not the console, disable Rx and Tx. */ if (!(pinfo->flags & FLAG_CONSOLE)) { /* Stop uarts */ if (IS_SMC(pinfo)) { volatile smc_t *smcp = pinfo->smcp; smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); } else { volatile scc_t *sccp = pinfo->sccp; sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX); } /* Shut them really down and reinit buffer descriptors */ cpm_line_cr_cmd(line, CPM_CR_STOP_TX); cpm_uart_initbd(pinfo); } }
/* * Shutdown the uart */ static void cpm_uart_shutdown(struct uart_port *port) { struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; pr_debug("CPM uart[%d]:shutdown\n", port->line); /* free interrupt handler */ free_irq(port->irq, port); /* If the port is not the console, disable Rx and Tx. */ if (!(pinfo->flags & FLAG_CONSOLE)) { /* Wait for all the BDs marked sent */ while(!cpm_uart_tx_empty(port)) { set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(2); } if (pinfo->wait_closing) cpm_uart_wait_until_send(pinfo); /* Stop uarts */ if (IS_SMC(pinfo)) { smc_t __iomem *smcp = pinfo->smcp; clrbits16(&smcp->smc_smcmr, SMCMR_REN | SMCMR_TEN); clrbits8(&smcp->smc_smcm, SMCM_RX | SMCM_TX); } else { scc_t __iomem *sccp = pinfo->sccp; clrbits32(&sccp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT); clrbits16(&sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX); } /* Shut them really down and reinit buffer descriptors */ if (IS_SMC(pinfo)) { out_be16(&pinfo->smcup->smc_brkcr, 0); cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX); } else { out_be16(&pinfo->sccup->scc_brkcr, 0); cpm_line_cr_cmd(pinfo, CPM_CR_GRA_STOP_TX); } cpm_uart_initbd(pinfo); } }
static void cpm_uart_init_smc(struct uart_cpm_port *pinfo) { smc_t __iomem *sp; smc_uart_t __iomem *up; pr_debug("CPM uart[%d]:init_smc\n", pinfo->port.line); sp = pinfo->smcp; up = pinfo->smcup; /* Store address */ out_be16(&pinfo->smcup->smc_rbase, (u8 __iomem *)pinfo->rx_bd_base - DPRAM_BASE); out_be16(&pinfo->smcup->smc_tbase, (u8 __iomem *)pinfo->tx_bd_base - DPRAM_BASE); /* * In case SMC1 is being relocated... */ #if defined (CONFIG_I2C_SPI_SMC1_UCODE_PATCH) out_be16(&up->smc_rbptr, in_be16(&pinfo->smcup->smc_rbase)); out_be16(&up->smc_tbptr, in_be16(&pinfo->smcup->smc_tbase)); out_be32(&up->smc_rstate, 0); out_be32(&up->smc_tstate, 0); out_be16(&up->smc_brkcr, 1); /* number of break chars */ out_be16(&up->smc_brkec, 0); #endif /* Set up the uart parameters in the * parameter ram. */ cpm_set_smc_fcr(up); /* Using idle charater time requires some additional tuning. */ out_be16(&up->smc_mrblr, pinfo->rx_fifosize); out_be16(&up->smc_maxidl, pinfo->rx_fifosize); out_be16(&up->smc_brklen, 0); out_be16(&up->smc_brkec, 0); out_be16(&up->smc_brkcr, 1); cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX); /* Set UART mode, 8 bit, no parity, one stop. * Enable receive and transmit. */ out_be16(&sp->smc_smcmr, smcr_mk_clen(9) | SMCMR_SM_UART); /* Enable only rx interrupts clear all pending events. */ out_8(&sp->smc_smcm, 0); out_8(&sp->smc_smce, 0xff); setbits16(&sp->smc_smcmr, SMCMR_REN | SMCMR_TEN); }
static void cpm_uart_init_smc(struct uart_cpm_port *pinfo) { int line = pinfo - cpm_uart_ports; volatile smc_t *sp; volatile smc_uart_t *up; pr_debug("CPM uart[%d]:init_smc\n", pinfo->port.line); sp = pinfo->smcp; up = pinfo->smcup; /* Store address */ pinfo->smcup->smc_rbase = (u_char *)pinfo->rx_bd_base - DPRAM_BASE; pinfo->smcup->smc_tbase = (u_char *)pinfo->tx_bd_base - DPRAM_BASE; /* * In case SMC1 is being relocated... */ #if defined (CONFIG_I2C_SPI_SMC1_UCODE_PATCH) up->smc_rbptr = pinfo->smcup->smc_rbase; up->smc_tbptr = pinfo->smcup->smc_tbase; up->smc_rstate = 0; up->smc_tstate = 0; up->smc_brkcr = 1; /* number of break chars */ up->smc_brkec = 0; #endif /* Set up the uart parameters in the * parameter ram. */ cpm_set_smc_fcr(up); /* Using idle charater time requires some additional tuning. */ up->smc_mrblr = pinfo->rx_fifosize; up->smc_maxidl = pinfo->rx_fifosize; up->smc_brklen = 0; up->smc_brkec = 0; up->smc_brkcr = 1; cpm_line_cr_cmd(line, CPM_CR_INIT_TRX); /* Set UART mode, 8 bit, no parity, one stop. * Enable receive and transmit. */ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; /* Enable only rx interrupts clear all pending events. */ sp->smc_smcm = 0; sp->smc_smce = 0xff; sp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN); }
int cpm_uart_early_setup(int index, int early) { int ret; struct uart_port *port; struct uart_cpm_port *pinfo = &cpm_uart_ports[index]; struct fs_uart_platform_info *pdata; struct platform_device* pdev = early_uart_get_pdev(index); int line = pinfo - cpm_uart_ports; BUG_ON(index>UART_NR); port = (struct uart_port *)&cpm_uart_ports[index]; pinfo = (struct uart_cpm_port *)port; if (!pdev) { if (pinfo->set_lineif) pinfo->set_lineif(pinfo); } else { pdata = pdev->dev.platform_data; if (pdata) if (pdata->init_ioports) pdata->init_ioports(pdata); cpm_uart_drv_get_platform_data(pdev, 1); } cpm_line_cr_cmd(line, CPM_CR_STOP_TX); if (IS_SMC(pinfo)) { pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); } else { pinfo->sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX); pinfo->sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); } ret = cpm_uart_allocbuf(pinfo, early); if (ret) return ret; cpm_uart_initbd(pinfo); if (IS_SMC(pinfo)) cpm_uart_init_smc(pinfo); else cpm_uart_init_scc(pinfo); return 0; }
/* * Setup console. Be careful is called early ! */ static int __init cpm_uart_console_setup(struct console *co, char *options) { struct uart_port *port; struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index]; int baud = 115200; int bits = 8; int parity = 'n'; int flow = 'n'; int ret; struct platform_device* pdev = early_uart_get_pdev(co->index); int line = pinfo - cpm_uart_ports; #ifdef CONFIG_KGDB_CPM_UART /* We are not interested in ports yet utilized by kgdb */ if(co->index == KGDB_PINFO_INDEX) return 0; #endif if (!pdev) { pr_info("cpm_uart: console: compat mode\n"); /* compatibility - will be cleaned up */ cpm_uart_init_portdesc(); } port = (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]]; pinfo = (struct uart_cpm_port *)port; pinfo->flags |= FLAG_CONSOLE; if (options) { uart_parse_options(options, &baud, &parity, &bits, &flow); } else { if ((baud = uart_baudrate()) == -1) baud = 9600; } ret = cpm_uart_early_setup(cpm_uart_port_map[co->index], 1); if(ret) return ret; uart_set_options(port, co, baud, parity, bits, flow); cpm_line_cr_cmd(line, CPM_CR_RESTART_TX); return 0; }
static void cpm_uart_init_scc(struct uart_cpm_port *pinfo) { scc_t __iomem *scp; scc_uart_t __iomem *sup; pr_debug("CPM uart[%d]:init_scc\n", pinfo->port.line); scp = pinfo->sccp; sup = pinfo->sccup; /* Store address */ out_be16(&pinfo->sccup->scc_genscc.scc_rbase, (u8 __iomem *)pinfo->rx_bd_base - DPRAM_BASE); out_be16(&pinfo->sccup->scc_genscc.scc_tbase, (u8 __iomem *)pinfo->tx_bd_base - DPRAM_BASE); /* Set up the uart parameters in the * parameter ram. */ cpm_set_scc_fcr(sup); out_be16(&sup->scc_genscc.scc_mrblr, pinfo->rx_fifosize); out_be16(&sup->scc_maxidl, pinfo->rx_fifosize); out_be16(&sup->scc_brkcr, 1); out_be16(&sup->scc_parec, 0); out_be16(&sup->scc_frmec, 0); out_be16(&sup->scc_nosec, 0); out_be16(&sup->scc_brkec, 0); out_be16(&sup->scc_uaddr1, 0); out_be16(&sup->scc_uaddr2, 0); out_be16(&sup->scc_toseq, 0); out_be16(&sup->scc_char1, 0x8000); out_be16(&sup->scc_char2, 0x8000); out_be16(&sup->scc_char3, 0x8000); out_be16(&sup->scc_char4, 0x8000); out_be16(&sup->scc_char5, 0x8000); out_be16(&sup->scc_char6, 0x8000); out_be16(&sup->scc_char7, 0x8000); out_be16(&sup->scc_char8, 0x8000); out_be16(&sup->scc_rccm, 0xc0ff); /* Send the CPM an initialize command. */ cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX); /* Set UART mode, 8 bit, no parity, one stop. * Enable receive and transmit. */ out_be32(&scp->scc_gsmrh, 0); out_be32(&scp->scc_gsmrl, SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16); /* Enable rx interrupts and clear all pending events. */ out_be16(&scp->scc_sccm, 0); out_be16(&scp->scc_scce, 0xffff); out_be16(&scp->scc_dsr, 0x7e7e); out_be16(&scp->scc_psmr, 0x3000); setbits32(&scp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT); }
static int __init cpm_uart_console_setup(struct console *co, char *options) { int baud = 38400; int bits = 8; int parity = 'n'; int flow = 'n'; int ret; struct uart_cpm_port *pinfo; struct uart_port *port; struct device_node *np = NULL; int i = 0; if (co->index >= UART_NR) { printk(KERN_ERR "cpm_uart: console index %d too high\n", co->index); return -ENODEV; } do { np = of_find_node_by_type(np, "serial"); if (!np) return -ENODEV; if (!of_device_is_compatible(np, "fsl,cpm1-smc-uart") && !of_device_is_compatible(np, "fsl,cpm1-scc-uart") && !of_device_is_compatible(np, "fsl,cpm2-smc-uart") && !of_device_is_compatible(np, "fsl,cpm2-scc-uart")) i--; } while (i++ != co->index); pinfo = &cpm_uart_ports[co->index]; pinfo->flags |= FLAG_CONSOLE; port = &pinfo->port; ret = cpm_uart_init_port(np, pinfo); of_node_put(np); if (ret) return ret; if (options) { uart_parse_options(options, &baud, &parity, &bits, &flow); } else { if ((baud = uart_baudrate()) == -1) baud = 9600; } #ifdef CONFIG_PPC_EARLY_DEBUG_CPM udbg_putc = NULL; #endif if (IS_SMC(pinfo)) { out_be16(&pinfo->smcup->smc_brkcr, 0); cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX); clrbits8(&pinfo->smcp->smc_smcm, SMCM_RX | SMCM_TX); clrbits16(&pinfo->smcp->smc_smcmr, SMCMR_REN | SMCMR_TEN); } else { out_be16(&pinfo->sccup->scc_brkcr, 0); cpm_line_cr_cmd(pinfo, CPM_CR_GRA_STOP_TX); clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX); clrbits32(&pinfo->sccp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT); } ret = cpm_uart_allocbuf(pinfo, 1); if (ret) return ret; cpm_uart_initbd(pinfo); if (IS_SMC(pinfo)) cpm_uart_init_smc(pinfo); else cpm_uart_init_scc(pinfo); uart_set_options(port, co, baud, parity, bits, flow); cpm_line_cr_cmd(pinfo, CPM_CR_RESTART_TX); return 0; }