static int serial_pxa_probe(struct platform_device *dev) { struct uart_pxa_port *sport; struct resource *mmres, *irqres; int ret; mmres = platform_get_resource(dev, IORESOURCE_MEM, 0); irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0); if (!mmres || !irqres) return -ENODEV; sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL); if (!sport) return -ENOMEM; sport->clk = clk_get(&dev->dev, NULL); if (IS_ERR(sport->clk)) { ret = PTR_ERR(sport->clk); goto err_free; } ret = clk_prepare(sport->clk); if (ret) { clk_put(sport->clk); goto err_free; } sport->port.type = PORT_PXA; sport->port.iotype = UPIO_MEM; sport->port.mapbase = mmres->start; sport->port.irq = irqres->start; sport->port.fifosize = 64; sport->port.ops = &serial_pxa_pops; sport->port.dev = &dev->dev; sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; sport->port.uartclk = clk_get_rate(sport->clk); ret = serial_pxa_probe_dt(dev, sport); if (ret > 0) sport->port.line = dev->id; else if (ret < 0) goto err_clk; snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1); sport->port.membase = ioremap(mmres->start, resource_size(mmres)); if (!sport->port.membase) { ret = -ENOMEM; goto err_clk; } serial_pxa_ports[sport->port.line] = sport; uart_add_one_port(&serial_pxa_reg, &sport->port); platform_set_drvdata(dev, sport); return 0; err_clk: clk_unprepare(sport->clk); clk_put(sport->clk); err_free: kfree(sport); return ret; }
static int serial_pxa_probe(struct platform_device *dev) { struct uart_pxa_port *sport; struct resource *mmres, *irqres, *dmares; int ret; struct uart_pxa_dma *pxa_dma; mmres = platform_get_resource(dev, IORESOURCE_MEM, 0); irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0); if (!mmres || !irqres) return -ENODEV; sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL); if (!sport) return -ENOMEM; sport->clk = clk_get(&dev->dev, NULL); if (IS_ERR(sport->clk)) { ret = PTR_ERR(sport->clk); goto err_free; } ret = clk_prepare(sport->clk); if (ret) { clk_put(sport->clk); goto err_free; } sport->port.type = PORT_PXA; sport->port.iotype = UPIO_MEM; sport->port.mapbase = mmres->start; sport->port.irq = irqres->start; sport->port.fifosize = 64; sport->port.ops = &serial_pxa_pops; sport->port.dev = &dev->dev; sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; sport->port.uartclk = clk_get_rate(sport->clk); pxa_dma = &sport->uart_dma; pxa_dma->drcmr_rx = 0; pxa_dma->drcmr_tx = 0; pxa_dma->txdma_chan = NULL; pxa_dma->rxdma_chan = NULL; pxa_dma->txdma_addr = NULL; pxa_dma->rxdma_addr = NULL; sport->dma_enable = 0; sport->edge_wakeup_gpio = -1; ret = serial_pxa_probe_dt(dev, sport); if (ret > 0) sport->port.line = dev->id; else if (ret < 0) goto err_clk; snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1); if (ret > 0 && uart_dma) { /* Get Rx DMA mapping value */ dmares = platform_get_resource(dev, IORESOURCE_DMA, 0); if (dmares) { pxa_dma->drcmr_rx = dmares->start; /* Get Tx DMA mapping value */ dmares = platform_get_resource(dev, IORESOURCE_DMA, 1); if (dmares) { pxa_dma->drcmr_tx = dmares->start; sport->dma_enable = 1; } } } sport->qos_idle[PXA_UART_TX].name = kasprintf(GFP_KERNEL, "%s%s", "tx", sport->name); if (!sport->qos_idle[PXA_UART_TX].name) { ret = -ENOMEM; goto err_clk; } sport->qos_idle[PXA_UART_RX].name = kasprintf(GFP_KERNEL, "%s%s", "rx", sport->name); if (!sport->qos_idle[PXA_UART_RX].name) { ret = -ENOMEM; kfree(sport->qos_idle[PXA_UART_TX].name); goto err_clk; } pm_qos_add_request(&sport->qos_idle[PXA_UART_TX], PM_QOS_CPUIDLE_BLOCK, PM_QOS_CPUIDLE_BLOCK_DEFAULT_VALUE); pm_qos_add_request(&sport->qos_idle[PXA_UART_RX], PM_QOS_CPUIDLE_BLOCK, PM_QOS_CPUIDLE_BLOCK_DEFAULT_VALUE); if (sport->edge_wakeup_gpio >= 0) { ret = request_mfp_edge_wakeup(sport->edge_wakeup_gpio, uart_edge_wakeup_handler, sport, &dev->dev); if (ret) { dev_err(&dev->dev, "failed to request edge wakeup.\n"); goto err_qos; } } sport->port.membase = ioremap(mmres->start, resource_size(mmres)); if (!sport->port.membase) { ret = -ENOMEM; goto err_map; } INIT_WORK(&sport->uart_tx_lpm_work, uart_tx_lpm_handler); init_timer(&sport->pxa_timer); sport->pxa_timer.function = pxa_timer_handler; sport->pxa_timer.data = (long)sport; serial_pxa_ports[sport->port.line] = sport; uart_add_one_port(&serial_pxa_reg, &sport->port); platform_set_drvdata(dev, sport); return 0; err_map: if (sport->edge_wakeup_gpio >= 0) remove_mfp_edge_wakeup(sport->edge_wakeup_gpio); err_qos: kfree(sport->qos_idle[PXA_UART_TX].name); kfree(sport->qos_idle[PXA_UART_RX].name); pm_qos_remove_request(&sport->qos_idle[PXA_UART_RX]); pm_qos_remove_request(&sport->qos_idle[PXA_UART_TX]); err_clk: clk_unprepare(sport->clk); clk_put(sport->clk); err_free: kfree(sport); return ret; }