Unverified Commit 64ca1a03 authored by Christophe Leroy's avatar Christophe Leroy Committed by Mark Brown
Browse files

spi: fsl_spi: Convert to transfer_one



Let the core handle all the chipselect bakery and replace
transfer_one_message() by transfer_one() and prepare_message().

At the time being, there is fsl_spi_cs_control() to handle
chipselects. That function handles both GPIO and non-GPIO
chipselects. The GPIO chipselects will now be handled by
the core directly, so only handle non-GPIO chipselects and
hook it to ->set_cs

Signed-off-by: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
Link: https://lore.kernel.org/r/753266abafe81722d86c3ddb8bac8ef1cb00fe8c.1660829841.git.christophe.leroy@csgroup.eu


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 83e5335b
Loading
Loading
Loading
Loading
+43 −114
Original line number Original line Diff line number Diff line
@@ -111,32 +111,6 @@ static void fsl_spi_change_mode(struct spi_device *spi)
	local_irq_restore(flags);
	local_irq_restore(flags);
}
}


static void fsl_spi_chipselect(struct spi_device *spi, int value)
{
	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
	struct fsl_spi_platform_data *pdata;
	struct spi_mpc8xxx_cs	*cs = spi->controller_state;

	pdata = spi->dev.parent->parent->platform_data;

	if (value == BITBANG_CS_INACTIVE) {
		if (pdata->cs_control)
			pdata->cs_control(spi, false);
	}

	if (value == BITBANG_CS_ACTIVE) {
		mpc8xxx_spi->rx_shift = cs->rx_shift;
		mpc8xxx_spi->tx_shift = cs->tx_shift;
		mpc8xxx_spi->get_rx = cs->get_rx;
		mpc8xxx_spi->get_tx = cs->get_tx;

		fsl_spi_change_mode(spi);

		if (pdata->cs_control)
			pdata->cs_control(spi, true);
	}
}

static void fsl_spi_qe_cpu_set_shifts(u32 *rx_shift, u32 *tx_shift,
static void fsl_spi_qe_cpu_set_shifts(u32 *rx_shift, u32 *tx_shift,
				      int bits_per_word, int msb_first)
				      int bits_per_word, int msb_first)
{
{
@@ -354,15 +328,11 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
	return mpc8xxx_spi->count;
	return mpc8xxx_spi->count;
}
}


static int fsl_spi_do_one_msg(struct spi_master *master,
static int fsl_spi_prepare_message(struct spi_controller *ctlr,
				   struct spi_message *m)
				   struct spi_message *m)
{
{
	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
	struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(ctlr);
	struct spi_device *spi = m->spi;
	struct spi_transfer *t;
	struct spi_transfer *t, *first;
	unsigned int cs_change;
	const int nsecs = 50;
	int status, last_bpw;


	/*
	/*
	 * In CPU mode, optimize large byte transfers to use larger
	 * In CPU mode, optimize large byte transfers to use larger
@@ -378,62 +348,30 @@ static int fsl_spi_do_one_msg(struct spi_master *master,
				t->bits_per_word = 16;
				t->bits_per_word = 16;
		}
		}
	}
	}

	return 0;
	/* Don't allow changes if CS is active */
	cs_change = 1;
	list_for_each_entry(t, &m->transfers, transfer_list) {
		if (cs_change)
			first = t;
		cs_change = t->cs_change;
		if (first->speed_hz != t->speed_hz) {
			dev_err(&spi->dev,
				"speed_hz cannot change while CS is active\n");
			return -EINVAL;
		}
}
}


	last_bpw = -1;
static int fsl_spi_transfer_one(struct spi_controller *controller,
	cs_change = 1;
				struct spi_device *spi,
	status = -EINVAL;
				struct spi_transfer *t)
	list_for_each_entry(t, &m->transfers, transfer_list) {
{
		if (cs_change || last_bpw != t->bits_per_word)
	int status;

	status = fsl_spi_setup_transfer(spi, t);
	status = fsl_spi_setup_transfer(spi, t);
	if (status < 0)
	if (status < 0)
			break;
		return status;
		last_bpw = t->bits_per_word;

		if (cs_change) {
			fsl_spi_chipselect(spi, BITBANG_CS_ACTIVE);
			ndelay(nsecs);
		}
		cs_change = t->cs_change;
	if (t->len)
	if (t->len)
			status = fsl_spi_bufs(spi, t, m->is_dma_mapped);
		status = fsl_spi_bufs(spi, t, !!t->tx_dma || !!t->rx_dma);
		if (status) {
	if (status > 0)
			status = -EMSGSIZE;
		return -EMSGSIZE;
			break;
		}
		m->actual_length += t->len;

		spi_transfer_delay_exec(t);


		if (cs_change) {
	return status;
			ndelay(nsecs);
			fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
			ndelay(nsecs);
}
}
	}

	m->status = status;


	if (status || !cs_change) {
static int fsl_spi_unprepare_message(struct spi_controller *controller,
		ndelay(nsecs);
				     struct spi_message *msg)
		fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
{
	}
	return fsl_spi_setup_transfer(msg->spi, NULL);

	fsl_spi_setup_transfer(spi, NULL);
	spi_finalize_current_message(master);
	return 0;
}
}


static int fsl_spi_setup(struct spi_device *spi)
static int fsl_spi_setup(struct spi_device *spi)
@@ -482,9 +420,6 @@ static int fsl_spi_setup(struct spi_device *spi)
		return retval;
		return retval;
	}
	}


	/* Initialize chipselect - might be active for SPI_CS_HIGH mode */
	fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);

	return 0;
	return 0;
}
}


@@ -557,9 +492,7 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
	u32 slvsel;
	u32 slvsel;
	u16 cs = spi->chip_select;
	u16 cs = spi->chip_select;


	if (spi->cs_gpiod) {
	if (cs < mpc8xxx_spi->native_chipselects) {
		gpiod_set_value(spi->cs_gpiod, on);
	} else if (cs < mpc8xxx_spi->native_chipselects) {
		slvsel = mpc8xxx_spi_read_reg(&reg_base->slvsel);
		slvsel = mpc8xxx_spi_read_reg(&reg_base->slvsel);
		slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs));
		slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs));
		mpc8xxx_spi_write_reg(&reg_base->slvsel, slvsel);
		mpc8xxx_spi_write_reg(&reg_base->slvsel, slvsel);
@@ -568,7 +501,6 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)


static void fsl_spi_grlib_probe(struct device *dev)
static void fsl_spi_grlib_probe(struct device *dev)
{
{
	struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
	struct spi_master *master = dev_get_drvdata(dev);
	struct spi_master *master = dev_get_drvdata(dev);
	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
	struct fsl_spi_reg __iomem *reg_base = mpc8xxx_spi->reg_base;
	struct fsl_spi_reg __iomem *reg_base = mpc8xxx_spi->reg_base;
@@ -588,7 +520,18 @@ static void fsl_spi_grlib_probe(struct device *dev)
		mpc8xxx_spi_write_reg(&reg_base->slvsel, 0xffffffff);
		mpc8xxx_spi_write_reg(&reg_base->slvsel, 0xffffffff);
	}
	}
	master->num_chipselect = mpc8xxx_spi->native_chipselects;
	master->num_chipselect = mpc8xxx_spi->native_chipselects;
	pdata->cs_control = fsl_spi_grlib_cs_control;
	master->set_cs = fsl_spi_grlib_cs_control;
}

static void fsl_spi_cs_control(struct spi_device *spi, bool on)
{
	struct device *dev = spi->dev.parent->parent;
	struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);

	if (WARN_ON_ONCE(!pinfo->immr_spi_cs))
		return;
	iowrite32be(on ? 0 : SPI_BOOT_SEL_BIT, pinfo->immr_spi_cs);
}
}


static struct spi_master *fsl_spi_probe(struct device *dev,
static struct spi_master *fsl_spi_probe(struct device *dev,
@@ -613,8 +556,11 @@ static struct spi_master *fsl_spi_probe(struct device *dev,


	master->setup = fsl_spi_setup;
	master->setup = fsl_spi_setup;
	master->cleanup = fsl_spi_cleanup;
	master->cleanup = fsl_spi_cleanup;
	master->transfer_one_message = fsl_spi_do_one_msg;
	master->prepare_message = fsl_spi_prepare_message;
	master->transfer_one = fsl_spi_transfer_one;
	master->unprepare_message = fsl_spi_unprepare_message;
	master->use_gpio_descriptors = true;
	master->use_gpio_descriptors = true;
	master->set_cs = fsl_spi_cs_control;


	mpc8xxx_spi = spi_master_get_devdata(master);
	mpc8xxx_spi = spi_master_get_devdata(master);
	mpc8xxx_spi->max_bits_per_word = 32;
	mpc8xxx_spi->max_bits_per_word = 32;
@@ -688,21 +634,6 @@ static struct spi_master *fsl_spi_probe(struct device *dev,
	return ERR_PTR(ret);
	return ERR_PTR(ret);
}
}


static void fsl_spi_cs_control(struct spi_device *spi, bool on)
{
	if (spi->cs_gpiod) {
		gpiod_set_value(spi->cs_gpiod, on);
	} else {
		struct device *dev = spi->dev.parent->parent;
		struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
		struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);

		if (WARN_ON_ONCE(!pinfo->immr_spi_cs))
			return;
		iowrite32be(on ? 0 : SPI_BOOT_SEL_BIT, pinfo->immr_spi_cs);
	}
}

static int of_fsl_spi_probe(struct platform_device *ofdev)
static int of_fsl_spi_probe(struct platform_device *ofdev)
{
{
	struct device *dev = &ofdev->dev;
	struct device *dev = &ofdev->dev;
@@ -744,12 +675,10 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
		ret = gpiod_count(dev, "cs");
		ret = gpiod_count(dev, "cs");
		if (ret < 0)
		if (ret < 0)
			ret = 0;
			ret = 0;
		if (ret == 0 && !spisel_boot) {
		if (ret == 0 && !spisel_boot)
			pdata->max_chipselect = 1;
			pdata->max_chipselect = 1;
		} else {
		else
			pdata->max_chipselect = ret + spisel_boot;
			pdata->max_chipselect = ret + spisel_boot;
			pdata->cs_control = fsl_spi_cs_control;
		}
	}
	}


	ret = of_address_to_resource(np, 0, &mem);
	ret = of_address_to_resource(np, 0, &mem);