diff options
Diffstat (limited to 'drivers/spi/spi-fsl-spi.c')
| -rw-r--r-- | drivers/spi/spi-fsl-spi.c | 193 | 
1 files changed, 25 insertions, 168 deletions
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 1d9b33aa1a3b..4b80ace1d137 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -18,7 +18,7 @@  #include <linux/delay.h>  #include <linux/dma-mapping.h>  #include <linux/fsl_devices.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h>  #include <linux/interrupt.h>  #include <linux/irq.h>  #include <linux/kernel.h> @@ -28,7 +28,6 @@  #include <linux/of.h>  #include <linux/of_address.h>  #include <linux/of_irq.h> -#include <linux/of_gpio.h>  #include <linux/of_platform.h>  #include <linux/platform_device.h>  #include <linux/spi/spi.h> @@ -481,32 +480,6 @@ static int fsl_spi_setup(struct spi_device *spi)  		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 */  	fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE); @@ -515,12 +488,8 @@ static int fsl_spi_setup(struct spi_device *spi)  static void fsl_spi_cleanup(struct spi_device *spi)  { -	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);  	struct spi_mpc8xxx_cs *cs = spi_get_ctldata(spi); -	if (mpc8xxx_spi->type == TYPE_GRLIB && gpio_is_valid(spi->cs_gpio)) -		gpio_free(spi->cs_gpio); -  	kfree(cs);  	spi_set_ctldata(spi, NULL);  } @@ -586,8 +555,8 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)  	u32 slvsel;  	u16 cs = spi->chip_select; -	if (gpio_is_valid(spi->cs_gpio)) { -		gpio_set_value(spi->cs_gpio, on); +	if (spi->cs_gpiod) { +		gpiod_set_value(spi->cs_gpiod, on);  	} else if (cs < mpc8xxx_spi->native_chipselects) {  		slvsel = mpc8xxx_spi_read_reg(®_base->slvsel);  		slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs)); @@ -718,139 +687,19 @@ err:  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); -	u16 cs = spi->chip_select; - -	if (cs < pinfo->ngpios) { -		int gpio = pinfo->gpios[cs]; -		bool alow = pinfo->alow_flags[cs]; - -		gpio_set_value(gpio, on ^ alow); +	if (spi->cs_gpiod) { +		gpiod_set_value(spi->cs_gpiod, on);  	} else { -		if (WARN_ON_ONCE(cs > pinfo->ngpios || !pinfo->immr_spi_cs)) +		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 ? SPI_BOOT_SEL_BIT : 0, pinfo->immr_spi_cs);  	}  } -static int of_fsl_spi_get_chipselects(struct device *dev) -{ -	struct device_node *np = dev->of_node; -	struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); -	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); -	bool spisel_boot = IS_ENABLED(CONFIG_FSL_SOC) && -		of_property_read_bool(np, "fsl,spisel_boot"); -	int ngpios; -	int i = 0; -	int ret; - -	ngpios = of_gpio_count(np); -	ngpios = max(ngpios, 0); -	if (ngpios == 0 && !spisel_boot) { -		/* -		 * SPI w/o chip-select line. One SPI device is still permitted -		 * though. -		 */ -		pdata->max_chipselect = 1; -		return 0; -	} - -	pinfo->ngpios = ngpios; -	pinfo->gpios = kmalloc_array(ngpios, sizeof(*pinfo->gpios), -				     GFP_KERNEL); -	if (!pinfo->gpios) -		return -ENOMEM; -	memset(pinfo->gpios, -1, ngpios * sizeof(*pinfo->gpios)); - -	pinfo->alow_flags = kcalloc(ngpios, sizeof(*pinfo->alow_flags), -				    GFP_KERNEL); -	if (!pinfo->alow_flags) { -		ret = -ENOMEM; -		goto err_alloc_flags; -	} - -	for (; i < ngpios; i++) { -		int gpio; -		enum of_gpio_flags flags; - -		gpio = of_get_gpio_flags(np, i, &flags); -		if (!gpio_is_valid(gpio)) { -			dev_err(dev, "invalid gpio #%d: %d\n", i, gpio); -			ret = gpio; -			goto err_loop; -		} - -		ret = gpio_request(gpio, dev_name(dev)); -		if (ret) { -			dev_err(dev, "can't request gpio #%d: %d\n", i, ret); -			goto err_loop; -		} - -		pinfo->gpios[i] = gpio; -		pinfo->alow_flags[i] = flags & OF_GPIO_ACTIVE_LOW; - -		ret = gpio_direction_output(pinfo->gpios[i], -					    pinfo->alow_flags[i]); -		if (ret) { -			dev_err(dev, -				"can't set output direction for gpio #%d: %d\n", -				i, ret); -			goto err_loop; -		} -	} - -#if IS_ENABLED(CONFIG_FSL_SOC) -	if (spisel_boot) { -		pinfo->immr_spi_cs = ioremap(get_immrbase() + IMMR_SPI_CS_OFFSET, 4); -		if (!pinfo->immr_spi_cs) { -			ret = -ENOMEM; -			i = ngpios - 1; -			goto err_loop; -		} -	} -#endif - -	pdata->max_chipselect = ngpios + spisel_boot; -	pdata->cs_control = fsl_spi_cs_control; - -	return 0; - -err_loop: -	while (i >= 0) { -		if (gpio_is_valid(pinfo->gpios[i])) -			gpio_free(pinfo->gpios[i]); -		i--; -	} - -	kfree(pinfo->alow_flags); -	pinfo->alow_flags = NULL; -err_alloc_flags: -	kfree(pinfo->gpios); -	pinfo->gpios = NULL; -	return ret; -} - -static int of_fsl_spi_free_chipselects(struct device *dev) -{ -	struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); -	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); -	int i; - -	if (!pinfo->gpios) -		return 0; - -	for (i = 0; i < pdata->max_chipselect; i++) { -		if (gpio_is_valid(pinfo->gpios[i])) -			gpio_free(pinfo->gpios[i]); -	} - -	kfree(pinfo->gpios); -	kfree(pinfo->alow_flags); -	return 0; -} -  static int of_fsl_spi_probe(struct platform_device *ofdev)  {  	struct device *dev = &ofdev->dev; @@ -866,9 +715,21 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)  	type = fsl_spi_get_type(&ofdev->dev);  	if (type == TYPE_FSL) { -		ret = of_fsl_spi_get_chipselects(dev); -		if (ret) -			goto err; +		struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); +#if IS_ENABLED(CONFIG_FSL_SOC) +		struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); +		bool spisel_boot = of_property_read_bool(np, "fsl,spisel_boot"); + +		if (spisel_boot) { +			pinfo->immr_spi_cs = ioremap(get_immrbase() + IMMR_SPI_CS_OFFSET, 4); +			if (!pinfo->immr_spi_cs) { +				ret = -ENOMEM; +				goto err; +			} +		} +#endif + +		pdata->cs_control = fsl_spi_cs_control;  	}  	ret = of_address_to_resource(np, 0, &mem); @@ -891,8 +752,6 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)  err:  	irq_dispose_mapping(irq); -	if (type == TYPE_FSL) -		of_fsl_spi_free_chipselects(dev);  	return ret;  } @@ -902,8 +761,6 @@ static int of_fsl_spi_remove(struct platform_device *ofdev)  	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);  	fsl_spi_cpm_free(mpc8xxx_spi); -	if (mpc8xxx_spi->type == TYPE_FSL) -		of_fsl_spi_free_chipselects(&ofdev->dev);  	return 0;  }  |