diff options
Diffstat (limited to 'drivers/spi/spi-fsl-dspi.c')
| -rw-r--r-- | drivers/spi/spi-fsl-dspi.c | 117 | 
1 files changed, 67 insertions, 50 deletions
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 6cd07d13eca..5021ddf03f6 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -18,6 +18,7 @@  #include <linux/interrupt.h>  #include <linux/errno.h>  #include <linux/platform_device.h> +#include <linux/regmap.h>  #include <linux/sched.h>  #include <linux/delay.h>  #include <linux/io.h> @@ -108,11 +109,11 @@ struct fsl_dspi {  	struct spi_bitbang	bitbang;  	struct platform_device	*pdev; -	void			*base; +	struct regmap		*regmap;  	int			irq; -	struct clk 		*clk; +	struct clk		*clk; -	struct spi_transfer 	*cur_transfer; +	struct spi_transfer	*cur_transfer;  	struct chip_data	*cur_chip;  	size_t			len;  	void			*tx; @@ -123,24 +124,17 @@ struct fsl_dspi {  	u8			cs;  	u16			void_write_data; -	wait_queue_head_t 	waitq; -	u32 			waitflags; +	wait_queue_head_t	waitq; +	u32			waitflags;  };  static inline int is_double_byte_mode(struct fsl_dspi *dspi)  { -	return ((readl(dspi->base + SPI_CTAR(dspi->cs)) & SPI_FRAME_BITS_MASK) -			== SPI_FRAME_BITS(8)) ? 0 : 1; -} +	unsigned int val; -static void set_bit_mode(struct fsl_dspi *dspi, unsigned char bits) -{ -	u32 temp; +	regmap_read(dspi->regmap, SPI_CTAR(dspi->cs), &val); -	temp = readl(dspi->base + SPI_CTAR(dspi->cs)); -	temp &= ~SPI_FRAME_BITS_MASK; -	temp |= SPI_FRAME_BITS(bits); -	writel(temp, dspi->base + SPI_CTAR(dspi->cs)); +	return ((val & SPI_FRAME_BITS_MASK) == SPI_FRAME_BITS(8)) ? 0 : 1;  }  static void hz_to_spi_baud(char *pbr, char *br, int speed_hz, @@ -165,7 +159,7 @@ static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,  			}  		} -	pr_warn("Can not find valid buad rate,speed_hz is %d,clkrate is %ld\ +	pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is %ld\  		,we use the max prescaler value.\n", speed_hz, clkrate);  	*pbr = ARRAY_SIZE(pbr_tbl) - 1;  	*br =  ARRAY_SIZE(brs) - 1; @@ -188,7 +182,8 @@ static int dspi_transfer_write(struct fsl_dspi *dspi)  	 */  	if (tx_word && (dspi->len == 1)) {  		dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM; -		set_bit_mode(dspi, 8); +		regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs), +				SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8));  		tx_word = 0;  	} @@ -238,7 +233,8 @@ static int dspi_transfer_write(struct fsl_dspi *dspi)  			dspi_pushr |= SPI_PUSHR_CTCNT; /* clear counter */  		} -		writel(dspi_pushr, dspi->base + SPI_PUSHR); +		regmap_write(dspi->regmap, SPI_PUSHR, dspi_pushr); +  		tx_count++;  	} @@ -253,17 +249,23 @@ static int dspi_transfer_read(struct fsl_dspi *dspi)  	while ((dspi->rx < dspi->rx_end)  			&& (rx_count < DSPI_FIFO_SIZE)) {  		if (rx_word) { +			unsigned int val; +  			if ((dspi->rx_end - dspi->rx) == 1)  				break; -			d = SPI_POPR_RXDATA(readl(dspi->base + SPI_POPR)); +			regmap_read(dspi->regmap, SPI_POPR, &val); +			d = SPI_POPR_RXDATA(val);  			if (!(dspi->dataflags & TRAN_STATE_RX_VOID))  				*(u16 *)dspi->rx = d;  			dspi->rx += 2;  		} else { -			d = SPI_POPR_RXDATA(readl(dspi->base + SPI_POPR)); +			unsigned int val; + +			regmap_read(dspi->regmap, SPI_POPR, &val); +			d = SPI_POPR_RXDATA(val);  			if (!(dspi->dataflags & TRAN_STATE_RX_VOID))  				*(u8 *)dspi->rx = d;  			dspi->rx++; @@ -295,13 +297,13 @@ static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t)  	if (!dspi->tx)  		dspi->dataflags |= TRAN_STATE_TX_VOID; -	writel(dspi->cur_chip->mcr_val, dspi->base + SPI_MCR); -	writel(dspi->cur_chip->ctar_val, dspi->base + SPI_CTAR(dspi->cs)); -	writel(SPI_RSER_EOQFE, dspi->base + SPI_RSER); +	regmap_write(dspi->regmap, SPI_MCR, dspi->cur_chip->mcr_val); +	regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), dspi->cur_chip->ctar_val); +	regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE);  	if (t->speed_hz) -		writel(dspi->cur_chip->ctar_val, -				dspi->base + SPI_CTAR(dspi->cs)); +		regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), +				dspi->cur_chip->ctar_val);  	dspi_transfer_write(dspi); @@ -315,16 +317,20 @@ static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t)  static void dspi_chipselect(struct spi_device *spi, int value)  {  	struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); -	u32 pushr = readl(dspi->base + SPI_PUSHR); +	unsigned int pushr; + +	regmap_read(dspi->regmap, SPI_PUSHR, &pushr);  	switch (value) {  	case BITBANG_CS_ACTIVE:  		pushr |= SPI_PUSHR_CONT; +		break;  	case BITBANG_CS_INACTIVE:  		pushr &= ~SPI_PUSHR_CONT; +		break;  	} -	writel(pushr, dspi->base + SPI_PUSHR); +	regmap_write(dspi->regmap, SPI_PUSHR, pushr);  }  static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) @@ -336,7 +342,8 @@ static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)  	/* Only alloc on first setup */  	chip = spi_get_ctldata(spi);  	if (chip == NULL) { -		chip = kcalloc(1, sizeof(struct chip_data), GFP_KERNEL); +		chip = devm_kzalloc(&spi->dev, sizeof(struct chip_data), +				    GFP_KERNEL);  		if (!chip)  			return -ENOMEM;  	} @@ -347,7 +354,6 @@ static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)  		fmsz = spi->bits_per_word - 1;  	} else {  		pr_err("Invalid wordsize\n"); -		kfree(chip);  		return -ENODEV;  	} @@ -373,9 +379,6 @@ static int dspi_setup(struct spi_device *spi)  	if (!spi->max_speed_hz)  		return -EINVAL; -	if (!spi->bits_per_word) -		spi->bits_per_word = 8; -  	return dspi_setup_transfer(spi, NULL);  } @@ -383,13 +386,15 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)  {  	struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; -	writel(SPI_SR_EOQF, dspi->base + SPI_SR); +	regmap_write(dspi->regmap, SPI_SR, SPI_SR_EOQF);  	dspi_transfer_read(dspi);  	if (!dspi->len) {  		if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) -			set_bit_mode(dspi, 16); +			regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs), +				SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(16)); +  		dspi->waitflags = 1;  		wake_up_interruptible(&dspi->waitq);  	} else { @@ -401,7 +406,7 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)  	return IRQ_HANDLED;  } -static struct of_device_id fsl_dspi_dt_ids[] = { +static const struct of_device_id fsl_dspi_dt_ids[] = {  	{ .compatible = "fsl,vf610-dspi", .data = NULL, },  	{ /* sentinel */ }  }; @@ -421,7 +426,6 @@ static int dspi_suspend(struct device *dev)  static int dspi_resume(struct device *dev)  { -  	struct spi_master *master = dev_get_drvdata(dev);  	struct fsl_dspi *dspi = spi_master_get_devdata(master); @@ -432,8 +436,13 @@ static int dspi_resume(struct device *dev)  }  #endif /* CONFIG_PM_SLEEP */ -static const struct dev_pm_ops dspi_pm = { -	SET_SYSTEM_SLEEP_PM_OPS(dspi_suspend, dspi_resume) +static SIMPLE_DEV_PM_OPS(dspi_pm, dspi_suspend, dspi_resume); + +static struct regmap_config dspi_regmap_config = { +	.reg_bits = 32, +	.val_bits = 32, +	.reg_stride = 4, +	.max_register = 0x88,  };  static int dspi_probe(struct platform_device *pdev) @@ -442,6 +451,7 @@ static int dspi_probe(struct platform_device *pdev)  	struct spi_master *master;  	struct fsl_dspi *dspi;  	struct resource *res; +	void __iomem *base;  	int ret = 0, cs_num, bus_num;  	master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi)); @@ -450,7 +460,7 @@ static int dspi_probe(struct platform_device *pdev)  	dspi = spi_master_get_devdata(master);  	dspi->pdev = pdev; -	dspi->bitbang.master = spi_master_get(master); +	dspi->bitbang.master = master;  	dspi->bitbang.chipselect = dspi_chipselect;  	dspi->bitbang.setup_transfer = dspi_setup_transfer;  	dspi->bitbang.txrx_bufs = dspi_txrx_transfer; @@ -476,16 +486,22 @@ static int dspi_probe(struct platform_device *pdev)  	master->bus_num = bus_num;  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		dev_err(&pdev->dev, "can't get platform resource\n"); -		ret = -EINVAL; +	base = devm_ioremap_resource(&pdev->dev, res); +	if (IS_ERR(base)) { +		ret = PTR_ERR(base);  		goto out_master_put;  	} -	dspi->base = devm_ioremap_resource(&pdev->dev, res); -	if (!dspi->base) { -		ret = -EINVAL; -		goto out_master_put; +	dspi_regmap_config.lock_arg = dspi; +	dspi_regmap_config.val_format_endian = +		of_property_read_bool(np, "big-endian") +			? REGMAP_ENDIAN_BIG : REGMAP_ENDIAN_DEFAULT; +	dspi->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "dspi", base, +						&dspi_regmap_config); +	if (IS_ERR(dspi->regmap)) { +		dev_err(&pdev->dev, "failed to init regmap: %ld\n", +				PTR_ERR(dspi->regmap)); +		return PTR_ERR(dspi->regmap);  	}  	dspi->irq = platform_get_irq(pdev, 0); @@ -511,7 +527,7 @@ static int dspi_probe(struct platform_device *pdev)  	clk_prepare_enable(dspi->clk);  	init_waitqueue_head(&dspi->waitq); -	platform_set_drvdata(pdev, dspi); +	platform_set_drvdata(pdev, master);  	ret = spi_bitbang_start(&dspi->bitbang);  	if (ret != 0) { @@ -526,17 +542,18 @@ out_clk_put:  	clk_disable_unprepare(dspi->clk);  out_master_put:  	spi_master_put(master); -	platform_set_drvdata(pdev, NULL);  	return ret;  }  static int dspi_remove(struct platform_device *pdev)  { -	struct fsl_dspi *dspi = platform_get_drvdata(pdev); +	struct spi_master *master = platform_get_drvdata(pdev); +	struct fsl_dspi *dspi = spi_master_get_devdata(master);  	/* Disconnect from the SPI framework */  	spi_bitbang_stop(&dspi->bitbang); +	clk_disable_unprepare(dspi->clk);  	spi_master_put(dspi->bitbang.master);  	return 0; @@ -553,5 +570,5 @@ static struct platform_driver fsl_dspi_driver = {  module_platform_driver(fsl_dspi_driver);  MODULE_DESCRIPTION("Freescale DSPI Controller Driver"); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL");  MODULE_ALIAS("platform:" DRIVER_NAME);  | 
