static int omap2_mcspi_probe()

in spi-omap2-mcspi.c [1420:1548]


static int omap2_mcspi_probe(struct platform_device *pdev)
{
	struct spi_master	*master;
	const struct omap2_mcspi_platform_config *pdata;
	struct omap2_mcspi	*mcspi;
	struct resource		*r;
	int			status = 0, i;
	u32			regs_offset = 0;
	struct device_node	*node = pdev->dev.of_node;
	const struct of_device_id *match;

	if (of_property_read_bool(node, "spi-slave"))
		master = spi_alloc_slave(&pdev->dev, sizeof(*mcspi));
	else
		master = spi_alloc_master(&pdev->dev, sizeof(*mcspi));
	if (!master)
		return -ENOMEM;

	/* the spi->mode bits understood by this driver: */
	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
	master->setup = omap2_mcspi_setup;
	master->auto_runtime_pm = true;
	master->prepare_message = omap2_mcspi_prepare_message;
	master->can_dma = omap2_mcspi_can_dma;
	master->transfer_one = omap2_mcspi_transfer_one;
	master->set_cs = omap2_mcspi_set_cs;
	master->cleanup = omap2_mcspi_cleanup;
	master->slave_abort = omap2_mcspi_slave_abort;
	master->dev.of_node = node;
	master->max_speed_hz = OMAP2_MCSPI_MAX_FREQ;
	master->min_speed_hz = OMAP2_MCSPI_MAX_FREQ >> 15;
	master->use_gpio_descriptors = true;

	platform_set_drvdata(pdev, master);

	mcspi = spi_master_get_devdata(master);
	mcspi->master = master;

	match = of_match_device(omap_mcspi_of_match, &pdev->dev);
	if (match) {
		u32 num_cs = 1; /* default number of chipselect */
		pdata = match->data;

		of_property_read_u32(node, "ti,spi-num-cs", &num_cs);
		master->num_chipselect = num_cs;
		if (of_get_property(node, "ti,pindir-d0-out-d1-in", NULL))
			mcspi->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN;
	} else {
		pdata = dev_get_platdata(&pdev->dev);
		master->num_chipselect = pdata->num_cs;
		mcspi->pin_dir = pdata->pin_dir;
	}
	regs_offset = pdata->regs_offset;
	if (pdata->max_xfer_len) {
		mcspi->max_xfer_len = pdata->max_xfer_len;
		master->max_transfer_size = omap2_mcspi_max_xfer_size;
	}

	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	mcspi->base = devm_ioremap_resource(&pdev->dev, r);
	if (IS_ERR(mcspi->base)) {
		status = PTR_ERR(mcspi->base);
		goto free_master;
	}
	mcspi->phys = r->start + regs_offset;
	mcspi->base += regs_offset;

	mcspi->dev = &pdev->dev;

	INIT_LIST_HEAD(&mcspi->ctx.cs);

	mcspi->dma_channels = devm_kcalloc(&pdev->dev, master->num_chipselect,
					   sizeof(struct omap2_mcspi_dma),
					   GFP_KERNEL);
	if (mcspi->dma_channels == NULL) {
		status = -ENOMEM;
		goto free_master;
	}

	for (i = 0; i < master->num_chipselect; i++) {
		sprintf(mcspi->dma_channels[i].dma_rx_ch_name, "rx%d", i);
		sprintf(mcspi->dma_channels[i].dma_tx_ch_name, "tx%d", i);

		status = omap2_mcspi_request_dma(mcspi,
						 &mcspi->dma_channels[i]);
		if (status == -EPROBE_DEFER)
			goto free_master;
	}

	status = platform_get_irq(pdev, 0);
	if (status == -EPROBE_DEFER)
		goto free_master;
	if (status < 0) {
		dev_err(&pdev->dev, "no irq resource found\n");
		goto free_master;
	}
	init_completion(&mcspi->txdone);
	status = devm_request_irq(&pdev->dev, status,
				  omap2_mcspi_irq_handler, 0, pdev->name,
				  mcspi);
	if (status) {
		dev_err(&pdev->dev, "Cannot request IRQ");
		goto free_master;
	}

	pm_runtime_use_autosuspend(&pdev->dev);
	pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
	pm_runtime_enable(&pdev->dev);

	status = omap2_mcspi_controller_setup(mcspi);
	if (status < 0)
		goto disable_pm;

	status = devm_spi_register_controller(&pdev->dev, master);
	if (status < 0)
		goto disable_pm;

	return status;

disable_pm:
	pm_runtime_dont_use_autosuspend(&pdev->dev);
	pm_runtime_put_sync(&pdev->dev);
	pm_runtime_disable(&pdev->dev);
free_master:
	omap2_mcspi_release_dma(master);
	spi_master_put(master);
	return status;
}