static int synquacer_spi_probe()

in spi-synquacer.c [602:737]


static int synquacer_spi_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct spi_master *master;
	struct synquacer_spi *sspi;
	int ret;
	int rx_irq, tx_irq;

	master = spi_alloc_master(&pdev->dev, sizeof(*sspi));
	if (!master)
		return -ENOMEM;

	platform_set_drvdata(pdev, master);

	sspi = spi_master_get_devdata(master);
	sspi->dev = &pdev->dev;

	init_completion(&sspi->transfer_done);

	sspi->regs = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(sspi->regs)) {
		ret = PTR_ERR(sspi->regs);
		goto put_spi;
	}

	sspi->clk_src_type = SYNQUACER_HSSPI_CLOCK_SRC_IHCLK; /* Default */
	device_property_read_u32(&pdev->dev, "socionext,ihclk-rate",
				 &master->max_speed_hz); /* for ACPI */

	if (dev_of_node(&pdev->dev)) {
		if (device_property_match_string(&pdev->dev,
					 "clock-names", "iHCLK") >= 0) {
			sspi->clk_src_type = SYNQUACER_HSSPI_CLOCK_SRC_IHCLK;
			sspi->clk = devm_clk_get(sspi->dev, "iHCLK");
		} else if (device_property_match_string(&pdev->dev,
						"clock-names", "iPCLK") >= 0) {
			sspi->clk_src_type = SYNQUACER_HSSPI_CLOCK_SRC_IPCLK;
			sspi->clk = devm_clk_get(sspi->dev, "iPCLK");
		} else {
			dev_err(&pdev->dev, "specified wrong clock source\n");
			ret = -EINVAL;
			goto put_spi;
		}

		if (IS_ERR(sspi->clk)) {
			ret = dev_err_probe(&pdev->dev, PTR_ERR(sspi->clk),
					    "clock not found\n");
			goto put_spi;
		}

		ret = clk_prepare_enable(sspi->clk);
		if (ret) {
			dev_err(&pdev->dev, "failed to enable clock (%d)\n",
				ret);
			goto put_spi;
		}

		master->max_speed_hz = clk_get_rate(sspi->clk);
	}

	if (!master->max_speed_hz) {
		dev_err(&pdev->dev, "missing clock source\n");
		ret = -EINVAL;
		goto disable_clk;
	}
	master->min_speed_hz = master->max_speed_hz / 254;

	sspi->aces = device_property_read_bool(&pdev->dev,
					       "socionext,set-aces");
	sspi->rtm = device_property_read_bool(&pdev->dev, "socionext,use-rtm");

	master->num_chipselect = SYNQUACER_HSSPI_NUM_CHIP_SELECT;

	rx_irq = platform_get_irq(pdev, 0);
	if (rx_irq <= 0) {
		ret = rx_irq;
		goto disable_clk;
	}
	snprintf(sspi->rx_irq_name, SYNQUACER_HSSPI_IRQ_NAME_MAX, "%s-rx",
		 dev_name(&pdev->dev));
	ret = devm_request_irq(&pdev->dev, rx_irq, sq_spi_rx_handler,
				0, sspi->rx_irq_name, sspi);
	if (ret) {
		dev_err(&pdev->dev, "request rx_irq failed (%d)\n", ret);
		goto disable_clk;
	}

	tx_irq = platform_get_irq(pdev, 1);
	if (tx_irq <= 0) {
		ret = tx_irq;
		goto disable_clk;
	}
	snprintf(sspi->tx_irq_name, SYNQUACER_HSSPI_IRQ_NAME_MAX, "%s-tx",
		 dev_name(&pdev->dev));
	ret = devm_request_irq(&pdev->dev, tx_irq, sq_spi_tx_handler,
				0, sspi->tx_irq_name, sspi);
	if (ret) {
		dev_err(&pdev->dev, "request tx_irq failed (%d)\n", ret);
		goto disable_clk;
	}

	master->dev.of_node = np;
	master->dev.fwnode = pdev->dev.fwnode;
	master->auto_runtime_pm = true;
	master->bus_num = pdev->id;

	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_TX_DUAL | SPI_RX_DUAL |
			    SPI_TX_QUAD | SPI_RX_QUAD;
	master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(24) |
				     SPI_BPW_MASK(16) | SPI_BPW_MASK(8);

	master->set_cs = synquacer_spi_set_cs;
	master->transfer_one = synquacer_spi_transfer_one;

	ret = synquacer_spi_enable(master);
	if (ret)
		goto disable_clk;

	pm_runtime_set_active(sspi->dev);
	pm_runtime_enable(sspi->dev);

	ret = devm_spi_register_master(sspi->dev, master);
	if (ret)
		goto disable_pm;

	return 0;

disable_pm:
	pm_runtime_disable(sspi->dev);
disable_clk:
	clk_disable_unprepare(sspi->clk);
put_spi:
	spi_master_put(master);

	return ret;
}