static int pxa2xx_spi_probe()

in spi-pxa2xx.c [1623:1848]


static int pxa2xx_spi_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct pxa2xx_spi_controller *platform_info;
	struct spi_controller *controller;
	struct driver_data *drv_data;
	struct ssp_device *ssp;
	const struct lpss_config *config;
	int status;
	u32 tmp;

	platform_info = dev_get_platdata(dev);
	if (!platform_info) {
		platform_info = pxa2xx_spi_init_pdata(pdev);
		if (IS_ERR(platform_info)) {
			dev_err(&pdev->dev, "missing platform data\n");
			return PTR_ERR(platform_info);
		}
	}

	ssp = pxa_ssp_request(pdev->id, pdev->name);
	if (!ssp)
		ssp = &platform_info->ssp;

	if (!ssp->mmio_base) {
		dev_err(&pdev->dev, "failed to get SSP\n");
		return -ENODEV;
	}

	if (platform_info->is_slave)
		controller = devm_spi_alloc_slave(dev, sizeof(*drv_data));
	else
		controller = devm_spi_alloc_master(dev, sizeof(*drv_data));

	if (!controller) {
		dev_err(&pdev->dev, "cannot alloc spi_controller\n");
		status = -ENOMEM;
		goto out_error_controller_alloc;
	}
	drv_data = spi_controller_get_devdata(controller);
	drv_data->controller = controller;
	drv_data->controller_info = platform_info;
	drv_data->ssp = ssp;

	device_set_node(&controller->dev, dev_fwnode(dev));

	/* The spi->mode bits understood by this driver: */
	controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;

	controller->bus_num = ssp->port_id;
	controller->dma_alignment = DMA_ALIGNMENT;
	controller->cleanup = cleanup;
	controller->setup = setup;
	controller->set_cs = pxa2xx_spi_set_cs;
	controller->transfer_one = pxa2xx_spi_transfer_one;
	controller->slave_abort = pxa2xx_spi_slave_abort;
	controller->handle_err = pxa2xx_spi_handle_err;
	controller->unprepare_transfer_hardware = pxa2xx_spi_unprepare_transfer;
	controller->fw_translate_cs = pxa2xx_spi_fw_translate_cs;
	controller->auto_runtime_pm = true;
	controller->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX;

	drv_data->ssp_type = ssp->type;

	if (pxa25x_ssp_comp(drv_data)) {
		switch (drv_data->ssp_type) {
		case QUARK_X1000_SSP:
			controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
			break;
		default:
			controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
			break;
		}

		drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE;
		drv_data->dma_cr1 = 0;
		drv_data->clear_sr = SSSR_ROR;
		drv_data->mask_sr = SSSR_RFS | SSSR_TFS | SSSR_ROR;
	} else {
		controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
		drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE;
		drv_data->dma_cr1 = DEFAULT_DMA_CR1;
		drv_data->clear_sr = SSSR_ROR | SSSR_TINT;
		drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS
						| SSSR_ROR | SSSR_TUR;
	}

	status = request_irq(ssp->irq, ssp_int, IRQF_SHARED, dev_name(dev),
			drv_data);
	if (status < 0) {
		dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq);
		goto out_error_controller_alloc;
	}

	/* Setup DMA if requested */
	if (platform_info->enable_dma) {
		status = pxa2xx_spi_dma_setup(drv_data);
		if (status) {
			dev_warn(dev, "no DMA channels available, using PIO\n");
			platform_info->enable_dma = false;
		} else {
			controller->can_dma = pxa2xx_spi_can_dma;
			controller->max_dma_len = MAX_DMA_LEN;
			controller->max_transfer_size =
				pxa2xx_spi_max_dma_transfer_size;
		}
	}

	/* Enable SOC clock */
	status = clk_prepare_enable(ssp->clk);
	if (status)
		goto out_error_dma_irq_alloc;

	controller->max_speed_hz = clk_get_rate(ssp->clk);
	/*
	 * Set minimum speed for all other platforms than Intel Quark which is
	 * able do under 1 Hz transfers.
	 */
	if (!pxa25x_ssp_comp(drv_data))
		controller->min_speed_hz =
			DIV_ROUND_UP(controller->max_speed_hz, 4096);
	else if (!is_quark_x1000_ssp(drv_data))
		controller->min_speed_hz =
			DIV_ROUND_UP(controller->max_speed_hz, 512);

	pxa_ssp_disable(ssp);

	/* Load default SSP configuration */
	switch (drv_data->ssp_type) {
	case QUARK_X1000_SSP:
		tmp = QUARK_X1000_SSCR1_RxTresh(RX_THRESH_QUARK_X1000_DFLT) |
		      QUARK_X1000_SSCR1_TxTresh(TX_THRESH_QUARK_X1000_DFLT);
		pxa2xx_spi_write(drv_data, SSCR1, tmp);

		/* Using the Motorola SPI protocol and use 8 bit frame */
		tmp = QUARK_X1000_SSCR0_Motorola | QUARK_X1000_SSCR0_DataSize(8);
		pxa2xx_spi_write(drv_data, SSCR0, tmp);
		break;
	case CE4100_SSP:
		tmp = CE4100_SSCR1_RxTresh(RX_THRESH_CE4100_DFLT) |
		      CE4100_SSCR1_TxTresh(TX_THRESH_CE4100_DFLT);
		pxa2xx_spi_write(drv_data, SSCR1, tmp);
		tmp = SSCR0_SCR(2) | SSCR0_Motorola | SSCR0_DataSize(8);
		pxa2xx_spi_write(drv_data, SSCR0, tmp);
		break;
	default:

		if (spi_controller_is_slave(controller)) {
			tmp = SSCR1_SCFR |
			      SSCR1_SCLKDIR |
			      SSCR1_SFRMDIR |
			      SSCR1_RxTresh(2) |
			      SSCR1_TxTresh(1) |
			      SSCR1_SPH;
		} else {
			tmp = SSCR1_RxTresh(RX_THRESH_DFLT) |
			      SSCR1_TxTresh(TX_THRESH_DFLT);
		}
		pxa2xx_spi_write(drv_data, SSCR1, tmp);
		tmp = SSCR0_Motorola | SSCR0_DataSize(8);
		if (!spi_controller_is_slave(controller))
			tmp |= SSCR0_SCR(2);
		pxa2xx_spi_write(drv_data, SSCR0, tmp);
		break;
	}

	if (!pxa25x_ssp_comp(drv_data))
		pxa2xx_spi_write(drv_data, SSTO, 0);

	if (!is_quark_x1000_ssp(drv_data))
		pxa2xx_spi_write(drv_data, SSPSP, 0);

	if (is_lpss_ssp(drv_data)) {
		lpss_ssp_setup(drv_data);
		config = lpss_get_config(drv_data);
		if (config->reg_capabilities >= 0) {
			tmp = __lpss_ssp_read_priv(drv_data,
						   config->reg_capabilities);
			tmp &= LPSS_CAPS_CS_EN_MASK;
			tmp >>= LPSS_CAPS_CS_EN_SHIFT;
			platform_info->num_chipselect = ffz(tmp);
		} else if (config->cs_num) {
			platform_info->num_chipselect = config->cs_num;
		}
	}
	controller->num_chipselect = platform_info->num_chipselect;
	controller->use_gpio_descriptors = true;

	if (platform_info->is_slave) {
		drv_data->gpiod_ready = devm_gpiod_get_optional(dev,
						"ready", GPIOD_OUT_LOW);
		if (IS_ERR(drv_data->gpiod_ready)) {
			status = PTR_ERR(drv_data->gpiod_ready);
			goto out_error_clock_enabled;
		}
	}

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

	/* Register with the SPI framework */
	platform_set_drvdata(pdev, drv_data);
	status = spi_register_controller(controller);
	if (status) {
		dev_err(&pdev->dev, "problem registering SPI controller\n");
		goto out_error_pm_runtime_enabled;
	}

	return status;

out_error_pm_runtime_enabled:
	pm_runtime_disable(&pdev->dev);

out_error_clock_enabled:
	clk_disable_unprepare(ssp->clk);

out_error_dma_irq_alloc:
	pxa2xx_spi_dma_release(drv_data);
	free_irq(ssp->irq, drv_data);

out_error_controller_alloc:
	pxa_ssp_free(ssp);
	return status;
}