diff options
Diffstat (limited to 'drivers/spi/spi-sh-msiof.c')
| -rw-r--r-- | drivers/spi/spi-sh-msiof.c | 73 | 
1 files changed, 39 insertions, 34 deletions
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 8171eedbfc90..0e74cbf9929d 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -39,7 +39,7 @@ struct sh_msiof_chipdata {  	u16 tx_fifo_size;  	u16 rx_fifo_size;  	u16 master_flags; -	u16 min_div; +	u16 min_div_pow;  };  struct sh_msiof_spi_priv { @@ -51,7 +51,7 @@ struct sh_msiof_spi_priv {  	struct completion done;  	unsigned int tx_fifo_size;  	unsigned int rx_fifo_size; -	unsigned int min_div; +	unsigned int min_div_pow;  	void *tx_dma_page;  	void *rx_dma_page;  	dma_addr_t tx_dma_addr; @@ -249,43 +249,46 @@ static irqreturn_t sh_msiof_spi_irq(int irq, void *data)  	return IRQ_HANDLED;  } -static struct { -	unsigned short div; -	unsigned short brdv; -} const sh_msiof_spi_div_table[] = { -	{ 1,	SCR_BRDV_DIV_1 }, -	{ 2,	SCR_BRDV_DIV_2 }, -	{ 4,	SCR_BRDV_DIV_4 }, -	{ 8,	SCR_BRDV_DIV_8 }, -	{ 16,	SCR_BRDV_DIV_16 }, -	{ 32,	SCR_BRDV_DIV_32 }, +static const u32 sh_msiof_spi_div_array[] = { +	SCR_BRDV_DIV_1, SCR_BRDV_DIV_2,	 SCR_BRDV_DIV_4, +	SCR_BRDV_DIV_8,	SCR_BRDV_DIV_16, SCR_BRDV_DIV_32,  };  static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,  				      unsigned long parent_rate, u32 spi_hz)  { -	unsigned long div = 1024; +	unsigned long div;  	u32 brps, scr; -	size_t k; +	unsigned int div_pow = p->min_div_pow; -	if (!WARN_ON(!spi_hz || !parent_rate)) -		div = DIV_ROUND_UP(parent_rate, spi_hz); - -	div = max_t(unsigned long, div, p->min_div); +	if (!spi_hz || !parent_rate) { +		WARN(1, "Invalid clock rate parameters %lu and %u\n", +		     parent_rate, spi_hz); +		return; +	} -	for (k = 0; k < ARRAY_SIZE(sh_msiof_spi_div_table); k++) { -		brps = DIV_ROUND_UP(div, sh_msiof_spi_div_table[k].div); +	div = DIV_ROUND_UP(parent_rate, spi_hz); +	if (div <= 1024) {  		/* SCR_BRDV_DIV_1 is valid only if BRPS is x 1/1 or x 1/2 */ -		if (sh_msiof_spi_div_table[k].div == 1 && brps > 2) -			continue; -		if (brps <= 32) /* max of brdv is 32 */ -			break; -	} +		if (!div_pow && div <= 32 && div > 2) +			div_pow = 1; + +		if (div_pow) +			brps = (div + 1) >> div_pow; +		else +			brps = div; -	k = min_t(int, k, ARRAY_SIZE(sh_msiof_spi_div_table) - 1); -	brps = min_t(int, brps, 32); +		for (; brps > 32; div_pow++) +			brps = (brps + 1) >> 1; +	} else { +		/* Set transfer rate composite divisor to 2^5 * 32 = 1024 */ +		dev_err(&p->pdev->dev, +			"Requested SPI transfer rate %d is too low\n", spi_hz); +		div_pow = 5; +		brps = 32; +	} -	scr = sh_msiof_spi_div_table[k].brdv | SCR_BRPS(brps); +	scr = sh_msiof_spi_div_array[div_pow] | SCR_BRPS(brps);  	sh_msiof_write(p, TSCR, scr);  	if (!(p->master->flags & SPI_MASTER_MUST_TX))  		sh_msiof_write(p, RSCR, scr); @@ -564,14 +567,16 @@ static int sh_msiof_spi_setup(struct spi_device *spi)  	/* Configure native chip select mode/polarity early */  	clr = MDR1_SYNCMD_MASK; -	set = MDR1_TRMD | TMDR1_PCON | MDR1_SYNCMD_SPI; +	set = MDR1_SYNCMD_SPI;  	if (spi->mode & SPI_CS_HIGH)  		clr |= BIT(MDR1_SYNCAC_SHIFT);  	else  		set |= BIT(MDR1_SYNCAC_SHIFT);  	pm_runtime_get_sync(&p->pdev->dev);  	tmp = sh_msiof_read(p, TMDR1) & ~clr; -	sh_msiof_write(p, TMDR1, tmp | set); +	sh_msiof_write(p, TMDR1, tmp | set | MDR1_TRMD | TMDR1_PCON); +	tmp = sh_msiof_read(p, RMDR1) & ~clr; +	sh_msiof_write(p, RMDR1, tmp | set);  	pm_runtime_put(&p->pdev->dev);  	p->native_cs_high = spi->mode & SPI_CS_HIGH;  	p->native_cs_inited = true; @@ -1041,21 +1046,21 @@ static const struct sh_msiof_chipdata sh_data = {  	.tx_fifo_size = 64,  	.rx_fifo_size = 64,  	.master_flags = 0, -	.min_div = 1, +	.min_div_pow = 0,  };  static const struct sh_msiof_chipdata rcar_gen2_data = {  	.tx_fifo_size = 64,  	.rx_fifo_size = 64,  	.master_flags = SPI_MASTER_MUST_TX, -	.min_div = 1, +	.min_div_pow = 0,  };  static const struct sh_msiof_chipdata rcar_gen3_data = {  	.tx_fifo_size = 64,  	.rx_fifo_size = 64,  	.master_flags = SPI_MASTER_MUST_TX, -	.min_div = 2, +	.min_div_pow = 1,  };  static const struct of_device_id sh_msiof_match[] = { @@ -1319,7 +1324,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, p);  	p->master = master;  	p->info = info; -	p->min_div = chipdata->min_div; +	p->min_div_pow = chipdata->min_div_pow;  	init_completion(&p->done);  |