aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-sh-msiof.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi-sh-msiof.c')
-rw-r--r--drivers/spi/spi-sh-msiof.c96
1 files changed, 71 insertions, 25 deletions
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
index 239be7cbe5a8..e57eec0b2f46 100644
--- a/drivers/spi/spi-sh-msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
@@ -82,7 +82,9 @@ struct sh_msiof_spi_priv {
82#define MDR1_SYNCMD_LR 0x30000000 /* L/R mode */ 82#define MDR1_SYNCMD_LR 0x30000000 /* L/R mode */
83#define MDR1_SYNCAC_SHIFT 25 /* Sync Polarity (1 = Active-low) */ 83#define MDR1_SYNCAC_SHIFT 25 /* Sync Polarity (1 = Active-low) */
84#define MDR1_BITLSB_SHIFT 24 /* MSB/LSB First (1 = LSB first) */ 84#define MDR1_BITLSB_SHIFT 24 /* MSB/LSB First (1 = LSB first) */
85#define MDR1_FLD_MASK 0x000000c0 /* Frame Sync Signal Interval (0-3) */ 85#define MDR1_DTDL_SHIFT 20 /* Data Pin Bit Delay for MSIOF_SYNC */
86#define MDR1_SYNCDL_SHIFT 16 /* Frame Sync Signal Timing Delay */
87#define MDR1_FLD_MASK 0x0000000c /* Frame Sync Signal Interval (0-3) */
86#define MDR1_FLD_SHIFT 2 88#define MDR1_FLD_SHIFT 2
87#define MDR1_XXSTP 0x00000001 /* Transmission/Reception Stop on FIFO */ 89#define MDR1_XXSTP 0x00000001 /* Transmission/Reception Stop on FIFO */
88/* TMDR1 */ 90/* TMDR1 */
@@ -241,42 +243,80 @@ static irqreturn_t sh_msiof_spi_irq(int irq, void *data)
241 243
242static struct { 244static struct {
243 unsigned short div; 245 unsigned short div;
244 unsigned short scr; 246 unsigned short brdv;
245} const sh_msiof_spi_clk_table[] = { 247} const sh_msiof_spi_div_table[] = {
246 { 1, SCR_BRPS( 1) | SCR_BRDV_DIV_1 }, 248 { 1, SCR_BRDV_DIV_1 },
247 { 2, SCR_BRPS( 1) | SCR_BRDV_DIV_2 }, 249 { 2, SCR_BRDV_DIV_2 },
248 { 4, SCR_BRPS( 1) | SCR_BRDV_DIV_4 }, 250 { 4, SCR_BRDV_DIV_4 },
249 { 8, SCR_BRPS( 1) | SCR_BRDV_DIV_8 }, 251 { 8, SCR_BRDV_DIV_8 },
250 { 16, SCR_BRPS( 1) | SCR_BRDV_DIV_16 }, 252 { 16, SCR_BRDV_DIV_16 },
251 { 32, SCR_BRPS( 1) | SCR_BRDV_DIV_32 }, 253 { 32, SCR_BRDV_DIV_32 },
252 { 64, SCR_BRPS(32) | SCR_BRDV_DIV_2 },
253 { 128, SCR_BRPS(32) | SCR_BRDV_DIV_4 },
254 { 256, SCR_BRPS(32) | SCR_BRDV_DIV_8 },
255 { 512, SCR_BRPS(32) | SCR_BRDV_DIV_16 },
256 { 1024, SCR_BRPS(32) | SCR_BRDV_DIV_32 },
257}; 254};
258 255
259static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p, 256static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
260 unsigned long parent_rate, u32 spi_hz) 257 unsigned long parent_rate, u32 spi_hz)
261{ 258{
262 unsigned long div = 1024; 259 unsigned long div = 1024;
260 u32 brps, scr;
263 size_t k; 261 size_t k;
264 262
265 if (!WARN_ON(!spi_hz || !parent_rate)) 263 if (!WARN_ON(!spi_hz || !parent_rate))
266 div = DIV_ROUND_UP(parent_rate, spi_hz); 264 div = DIV_ROUND_UP(parent_rate, spi_hz);
267 265
268 /* TODO: make more fine grained */ 266 for (k = 0; k < ARRAY_SIZE(sh_msiof_spi_div_table); k++) {
269 267 brps = DIV_ROUND_UP(div, sh_msiof_spi_div_table[k].div);
270 for (k = 0; k < ARRAY_SIZE(sh_msiof_spi_clk_table); k++) { 268 if (brps <= 32) /* max of brdv is 32 */
271 if (sh_msiof_spi_clk_table[k].div >= div)
272 break; 269 break;
273 } 270 }
274 271
275 k = min_t(int, k, ARRAY_SIZE(sh_msiof_spi_clk_table) - 1); 272 k = min_t(int, k, ARRAY_SIZE(sh_msiof_spi_div_table) - 1);
276 273
277 sh_msiof_write(p, TSCR, sh_msiof_spi_clk_table[k].scr); 274 scr = sh_msiof_spi_div_table[k].brdv | SCR_BRPS(brps);
275 sh_msiof_write(p, TSCR, scr);
278 if (!(p->chipdata->master_flags & SPI_MASTER_MUST_TX)) 276 if (!(p->chipdata->master_flags & SPI_MASTER_MUST_TX))
279 sh_msiof_write(p, RSCR, sh_msiof_spi_clk_table[k].scr); 277 sh_msiof_write(p, RSCR, scr);
278}
279
280static u32 sh_msiof_get_delay_bit(u32 dtdl_or_syncdl)
281{
282 /*
283 * DTDL/SYNCDL bit : p->info->dtdl or p->info->syncdl
284 * b'000 : 0
285 * b'001 : 100
286 * b'010 : 200
287 * b'011 (SYNCDL only) : 300
288 * b'101 : 50
289 * b'110 : 150
290 */
291 if (dtdl_or_syncdl % 100)
292 return dtdl_or_syncdl / 100 + 5;
293 else
294 return dtdl_or_syncdl / 100;
295}
296
297static u32 sh_msiof_spi_get_dtdl_and_syncdl(struct sh_msiof_spi_priv *p)
298{
299 u32 val;
300
301 if (!p->info)
302 return 0;
303
304 /* check if DTDL and SYNCDL is allowed value */
305 if (p->info->dtdl > 200 || p->info->syncdl > 300) {
306 dev_warn(&p->pdev->dev, "DTDL or SYNCDL is too large\n");
307 return 0;
308 }
309
310 /* check if the sum of DTDL and SYNCDL becomes an integer value */
311 if ((p->info->dtdl + p->info->syncdl) % 100) {
312 dev_warn(&p->pdev->dev, "the sum of DTDL/SYNCDL is not good\n");
313 return 0;
314 }
315
316 val = sh_msiof_get_delay_bit(p->info->dtdl) << MDR1_DTDL_SHIFT;
317 val |= sh_msiof_get_delay_bit(p->info->syncdl) << MDR1_SYNCDL_SHIFT;
318
319 return val;
280} 320}
281 321
282static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, 322static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
@@ -296,6 +336,7 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
296 tmp = MDR1_SYNCMD_SPI | 1 << MDR1_FLD_SHIFT | MDR1_XXSTP; 336 tmp = MDR1_SYNCMD_SPI | 1 << MDR1_FLD_SHIFT | MDR1_XXSTP;
297 tmp |= !cs_high << MDR1_SYNCAC_SHIFT; 337 tmp |= !cs_high << MDR1_SYNCAC_SHIFT;
298 tmp |= lsb_first << MDR1_BITLSB_SHIFT; 338 tmp |= lsb_first << MDR1_BITLSB_SHIFT;
339 tmp |= sh_msiof_spi_get_dtdl_and_syncdl(p);
299 sh_msiof_write(p, TMDR1, tmp | MDR1_TRMD | TMDR1_PCON); 340 sh_msiof_write(p, TMDR1, tmp | MDR1_TRMD | TMDR1_PCON);
300 if (p->chipdata->master_flags & SPI_MASTER_MUST_TX) { 341 if (p->chipdata->master_flags & SPI_MASTER_MUST_TX) {
301 /* These bits are reserved if RX needs TX */ 342 /* These bits are reserved if RX needs TX */
@@ -480,6 +521,8 @@ static int sh_msiof_spi_setup(struct spi_device *spi)
480 struct device_node *np = spi->master->dev.of_node; 521 struct device_node *np = spi->master->dev.of_node;
481 struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master); 522 struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master);
482 523
524 pm_runtime_get_sync(&p->pdev->dev);
525
483 if (!np) { 526 if (!np) {
484 /* 527 /*
485 * Use spi->controller_data for CS (same strategy as spi_gpio), 528 * Use spi->controller_data for CS (same strategy as spi_gpio),
@@ -498,6 +541,9 @@ static int sh_msiof_spi_setup(struct spi_device *spi)
498 if (spi->cs_gpio >= 0) 541 if (spi->cs_gpio >= 0)
499 gpio_set_value(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); 542 gpio_set_value(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
500 543
544
545 pm_runtime_put(&p->pdev->dev);
546
501 return 0; 547 return 0;
502} 548}
503 549
@@ -590,8 +636,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
590 } 636 }
591 637
592 /* wait for tx fifo to be emptied / rx fifo to be filled */ 638 /* wait for tx fifo to be emptied / rx fifo to be filled */
593 ret = wait_for_completion_timeout(&p->done, HZ); 639 if (!wait_for_completion_timeout(&p->done, HZ)) {
594 if (!ret) {
595 dev_err(&p->pdev->dev, "PIO timeout\n"); 640 dev_err(&p->pdev->dev, "PIO timeout\n");
596 ret = -ETIMEDOUT; 641 ret = -ETIMEDOUT;
597 goto stop_reset; 642 goto stop_reset;
@@ -701,8 +746,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
701 } 746 }
702 747
703 /* wait for tx fifo to be emptied / rx fifo to be filled */ 748 /* wait for tx fifo to be emptied / rx fifo to be filled */
704 ret = wait_for_completion_timeout(&p->done, HZ); 749 if (!wait_for_completion_timeout(&p->done, HZ)) {
705 if (!ret) {
706 dev_err(&p->pdev->dev, "DMA timeout\n"); 750 dev_err(&p->pdev->dev, "DMA timeout\n");
707 ret = -ETIMEDOUT; 751 ret = -ETIMEDOUT;
708 goto stop_reset; 752 goto stop_reset;
@@ -952,6 +996,8 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev)
952 &info->tx_fifo_override); 996 &info->tx_fifo_override);
953 of_property_read_u32(np, "renesas,rx-fifo-size", 997 of_property_read_u32(np, "renesas,rx-fifo-size",
954 &info->rx_fifo_override); 998 &info->rx_fifo_override);
999 of_property_read_u32(np, "renesas,dtdl", &info->dtdl);
1000 of_property_read_u32(np, "renesas,syncdl", &info->syncdl);
955 1001
956 info->num_chipselect = num_cs; 1002 info->num_chipselect = num_cs;
957 1003