diff options
Diffstat (limited to 'drivers/spi/spi-sh-msiof.c')
-rw-r--r-- | drivers/spi/spi-sh-msiof.c | 96 |
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 | ||
242 | static struct { | 244 | static 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 | ||
259 | static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p, | 256 | static 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 | |||
280 | static 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 | |||
297 | static 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 | ||
282 | static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, | 322 | static 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 | ||