in serial/cpm_uart/cpm_uart_core.c [1146:1265]
static int cpm_uart_init_port(struct device_node *np,
struct uart_cpm_port *pinfo)
{
const u32 *data;
void __iomem *mem, *pram;
struct device *dev = pinfo->port.dev;
int len;
int ret;
int i;
data = of_get_property(np, "clock", NULL);
if (data) {
struct clk *clk = clk_get(NULL, (const char*)data);
if (!IS_ERR(clk))
pinfo->clk = clk;
}
if (!pinfo->clk) {
data = of_get_property(np, "fsl,cpm-brg", &len);
if (!data || len != 4) {
printk(KERN_ERR "CPM UART %pOFn has no/invalid "
"fsl,cpm-brg property.\n", np);
return -EINVAL;
}
pinfo->brg = *data;
}
data = of_get_property(np, "fsl,cpm-command", &len);
if (!data || len != 4) {
printk(KERN_ERR "CPM UART %pOFn has no/invalid "
"fsl,cpm-command property.\n", np);
return -EINVAL;
}
pinfo->command = *data;
mem = of_iomap(np, 0);
if (!mem)
return -ENOMEM;
if (of_device_is_compatible(np, "fsl,cpm1-scc-uart") ||
of_device_is_compatible(np, "fsl,cpm2-scc-uart")) {
pinfo->sccp = mem;
pinfo->sccup = pram = cpm_uart_map_pram(pinfo, np);
} else if (of_device_is_compatible(np, "fsl,cpm1-smc-uart") ||
of_device_is_compatible(np, "fsl,cpm2-smc-uart")) {
pinfo->flags |= FLAG_SMC;
pinfo->smcp = mem;
pinfo->smcup = pram = cpm_uart_map_pram(pinfo, np);
} else {
ret = -ENODEV;
goto out_mem;
}
if (!pram) {
ret = -ENOMEM;
goto out_mem;
}
pinfo->tx_nrfifos = TX_NUM_FIFO;
pinfo->tx_fifosize = TX_BUF_SIZE;
pinfo->rx_nrfifos = RX_NUM_FIFO;
pinfo->rx_fifosize = RX_BUF_SIZE;
pinfo->port.uartclk = ppc_proc_freq;
pinfo->port.mapbase = (unsigned long)mem;
pinfo->port.type = PORT_CPM;
pinfo->port.ops = &cpm_uart_pops;
pinfo->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_CPM_CONSOLE);
pinfo->port.iotype = UPIO_MEM;
pinfo->port.fifosize = pinfo->tx_nrfifos * pinfo->tx_fifosize;
spin_lock_init(&pinfo->port.lock);
pinfo->port.irq = irq_of_parse_and_map(np, 0);
if (pinfo->port.irq == NO_IRQ) {
ret = -EINVAL;
goto out_pram;
}
for (i = 0; i < NUM_GPIOS; i++) {
struct gpio_desc *gpiod;
pinfo->gpios[i] = NULL;
gpiod = devm_gpiod_get_index_optional(dev, NULL, i, GPIOD_ASIS);
if (IS_ERR(gpiod)) {
ret = PTR_ERR(gpiod);
goto out_irq;
}
if (gpiod) {
if (i == GPIO_RTS || i == GPIO_DTR)
ret = gpiod_direction_output(gpiod, 0);
else
ret = gpiod_direction_input(gpiod);
if (ret) {
pr_err("can't set direction for gpio #%d: %d\n",
i, ret);
continue;
}
pinfo->gpios[i] = gpiod;
}
}
#ifdef CONFIG_PPC_EARLY_DEBUG_CPM
#ifdef CONFIG_CONSOLE_POLL
if (!udbg_port)
#endif
udbg_putc = NULL;
#endif
return cpm_uart_request_port(&pinfo->port);
out_irq:
irq_dispose_mapping(pinfo->port.irq);
out_pram:
cpm_uart_unmap_pram(pinfo, pram);
out_mem:
iounmap(mem);
return ret;
}