static int lantiq_ssc_probe()

in spi-lantiq-ssc.c [903:1024]


static int lantiq_ssc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct spi_master *master;
	struct lantiq_ssc_spi *spi;
	const struct lantiq_ssc_hwcfg *hwcfg;
	const struct of_device_id *match;
	u32 id, supports_dma, revision;
	unsigned int num_cs;
	int err;

	match = of_match_device(lantiq_ssc_match, dev);
	if (!match) {
		dev_err(dev, "no device match\n");
		return -EINVAL;
	}
	hwcfg = match->data;

	master = spi_alloc_master(dev, sizeof(struct lantiq_ssc_spi));
	if (!master)
		return -ENOMEM;

	spi = spi_master_get_devdata(master);
	spi->master = master;
	spi->dev = dev;
	spi->hwcfg = hwcfg;
	platform_set_drvdata(pdev, spi);
	spi->regbase = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(spi->regbase)) {
		err = PTR_ERR(spi->regbase);
		goto err_master_put;
	}

	err = hwcfg->cfg_irq(pdev, spi);
	if (err)
		goto err_master_put;

	spi->spi_clk = devm_clk_get(dev, "gate");
	if (IS_ERR(spi->spi_clk)) {
		err = PTR_ERR(spi->spi_clk);
		goto err_master_put;
	}
	err = clk_prepare_enable(spi->spi_clk);
	if (err)
		goto err_master_put;

	/*
	 * Use the old clk_get_fpi() function on Lantiq platform, till it
	 * supports common clk.
	 */
#if defined(CONFIG_LANTIQ) && !defined(CONFIG_COMMON_CLK)
	spi->fpi_clk = clk_get_fpi();
#else
	spi->fpi_clk = clk_get(dev, "freq");
#endif
	if (IS_ERR(spi->fpi_clk)) {
		err = PTR_ERR(spi->fpi_clk);
		goto err_clk_disable;
	}

	num_cs = 8;
	of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs);

	spi->base_cs = 1;
	of_property_read_u32(pdev->dev.of_node, "base-cs", &spi->base_cs);

	spin_lock_init(&spi->lock);
	spi->bits_per_word = 8;
	spi->speed_hz = 0;

	master->dev.of_node = pdev->dev.of_node;
	master->num_chipselect = num_cs;
	master->use_gpio_descriptors = true;
	master->setup = lantiq_ssc_setup;
	master->set_cs = lantiq_ssc_set_cs;
	master->handle_err = lantiq_ssc_handle_err;
	master->prepare_message = lantiq_ssc_prepare_message;
	master->unprepare_message = lantiq_ssc_unprepare_message;
	master->transfer_one = lantiq_ssc_transfer_one;
	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH |
				SPI_LOOP;
	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 8) |
				     SPI_BPW_MASK(16) | SPI_BPW_MASK(32);

	spi->wq = alloc_ordered_workqueue(dev_name(dev), WQ_MEM_RECLAIM);
	if (!spi->wq) {
		err = -ENOMEM;
		goto err_clk_put;
	}
	INIT_WORK(&spi->work, lantiq_ssc_bussy_work);

	id = lantiq_ssc_readl(spi, LTQ_SPI_ID);
	spi->tx_fifo_size = (id >> LTQ_SPI_ID_TXFS_S) & hwcfg->fifo_size_mask;
	spi->rx_fifo_size = (id >> LTQ_SPI_ID_RXFS_S) & hwcfg->fifo_size_mask;
	supports_dma = (id & LTQ_SPI_ID_CFG_M) >> LTQ_SPI_ID_CFG_S;
	revision = id & LTQ_SPI_ID_REV_M;

	lantiq_ssc_hw_init(spi);

	dev_info(dev,
		"Lantiq SSC SPI controller (Rev %i, TXFS %u, RXFS %u, DMA %u)\n",
		revision, spi->tx_fifo_size, spi->rx_fifo_size, supports_dma);

	err = devm_spi_register_master(dev, master);
	if (err) {
		dev_err(dev, "failed to register spi_master\n");
		goto err_wq_destroy;
	}

	return 0;

err_wq_destroy:
	destroy_workqueue(spi->wq);
err_clk_put:
	clk_put(spi->fpi_clk);
err_clk_disable:
	clk_disable_unprepare(spi->spi_clk);
err_master_put:
	spi_master_put(master);

	return err;
}