Esempio n. 1
0
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;
}