Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 76a7498f authored by Andreas Larsson's avatar Andreas Larsson Committed by Grant Likely
Browse files

spi/spi-fsl-spi: Add support for gpio chipselects for GRLIB type cores



This relies upon of_spi_register_master to find out which gpios to use.

Acked-by: default avatarAnton Vorontsov <anton@enomsg.org>
Signed-off-by: default avatarAndreas Larsson <andreas@gaisler.com>
Signed-off-by: default avatarGrant Likely <grant.likely@secretlab.ca>
parent 447b0c7b
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -71,6 +71,7 @@ struct mpc8xxx_spi {


#ifdef CONFIG_SPI_FSL_SPI
#ifdef CONFIG_SPI_FSL_SPI
	int type;
	int type;
	int native_chipselects;
	u8 max_bits_per_word;
	u8 max_bits_per_word;


	void (*set_shifts)(u32 *rx_shift, u32 *tx_shift,
	void (*set_shifts)(u32 *rx_shift, u32 *tx_shift,
+45 −5
Original line number Original line Diff line number Diff line
@@ -456,12 +456,46 @@ static int fsl_spi_setup(struct spi_device *spi)
		return retval;
		return retval;
	}
	}


	if (mpc8xxx_spi->type == TYPE_GRLIB) {
		if (gpio_is_valid(spi->cs_gpio)) {
			int desel;

			retval = gpio_request(spi->cs_gpio,
					      dev_name(&spi->dev));
			if (retval)
				return retval;

			desel = !(spi->mode & SPI_CS_HIGH);
			retval = gpio_direction_output(spi->cs_gpio, desel);
			if (retval) {
				gpio_free(spi->cs_gpio);
				return retval;
			}
		} else if (spi->cs_gpio != -ENOENT) {
			if (spi->cs_gpio < 0)
				return spi->cs_gpio;
			return -EINVAL;
		}
		/* When spi->cs_gpio == -ENOENT, a hole in the phandle list
		 * indicates to use native chipselect if present, or allow for
		 * an always selected chip
		 */
	}

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


	return 0;
	return 0;
}
}


static void fsl_spi_cleanup(struct spi_device *spi)
{
	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);

	if (mpc8xxx_spi->type == TYPE_GRLIB && gpio_is_valid(spi->cs_gpio))
		gpio_free(spi->cs_gpio);
}

static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
{
{
	struct fsl_spi_reg *reg_base = mspi->reg_base;
	struct fsl_spi_reg *reg_base = mspi->reg_base;
@@ -529,10 +563,14 @@ 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 (gpio_is_valid(spi->cs_gpio)) {
		gpio_set_value(spi->cs_gpio, 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);
	}
	}
}


static void fsl_spi_grlib_probe(struct device *dev)
static void fsl_spi_grlib_probe(struct device *dev)
{
{
@@ -550,11 +588,12 @@ static void fsl_spi_grlib_probe(struct device *dev)
	if (mbits)
	if (mbits)
		mpc8xxx_spi->max_bits_per_word = mbits + 1;
		mpc8xxx_spi->max_bits_per_word = mbits + 1;


	master->num_chipselect = 1; /* Allow for an always selected chip */
	mpc8xxx_spi->native_chipselects = 0;
	if (SPCAP_SSEN(capabilities)) {
	if (SPCAP_SSEN(capabilities)) {
		master->num_chipselect = SPCAP_SSSZ(capabilities);
		mpc8xxx_spi->native_chipselects = SPCAP_SSSZ(capabilities);
		mpc8xxx_spi_write_reg(&reg_base->slvsel, 0xffffffff);
		mpc8xxx_spi_write_reg(&reg_base->slvsel, 0xffffffff);
	}
	}
	master->num_chipselect = mpc8xxx_spi->native_chipselects;
	pdata->cs_control = fsl_spi_grlib_cs_control;
	pdata->cs_control = fsl_spi_grlib_cs_control;
}
}


@@ -581,6 +620,7 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
		goto err_probe;
		goto err_probe;


	master->setup = fsl_spi_setup;
	master->setup = fsl_spi_setup;
	master->cleanup = fsl_spi_cleanup;


	mpc8xxx_spi = spi_master_get_devdata(master);
	mpc8xxx_spi = spi_master_get_devdata(master);
	mpc8xxx_spi->spi_do_one_msg = fsl_spi_do_one_msg;
	mpc8xxx_spi->spi_do_one_msg = fsl_spi_do_one_msg;