aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2015-02-07 22:16:43 -0500
committerMark Brown <broonie@kernel.org>2015-02-07 22:16:43 -0500
commit81306d53da7efde6fa17c04700b8782e08006e80 (patch)
treea64e4a2e6499f45da3bbd72af035f0000fba8b5c
parentf69c22ed22a0529143aea74ead7696d6a8b8269d (diff)
parent19f0ad0942d560d33afedc66a27fe7d6e67373dc (diff)
Merge remote-tracking branch 'spi/topic/sh-msiof' into spi-next
-rw-r--r--Documentation/devicetree/bindings/spi/sh-msiof.txt16
-rw-r--r--drivers/spi/spi-sh-msiof.c91
-rw-r--r--include/linux/spi/sh_msiof.h2
3 files changed, 84 insertions, 25 deletions
diff --git a/Documentation/devicetree/bindings/spi/sh-msiof.txt b/Documentation/devicetree/bindings/spi/sh-msiof.txt
index d11c3721e7cd..4c388bb2f0a2 100644
--- a/Documentation/devicetree/bindings/spi/sh-msiof.txt
+++ b/Documentation/devicetree/bindings/spi/sh-msiof.txt
@@ -30,6 +30,22 @@ Optional properties:
30 specifiers, one for transmission, and one for 30 specifiers, one for transmission, and one for
31 reception. 31 reception.
32- dma-names : Must contain a list of two DMA names, "tx" and "rx". 32- dma-names : Must contain a list of two DMA names, "tx" and "rx".
33- renesas,dtdl : delay sync signal (setup) in transmit mode.
34 Must contain one of the following values:
35 0 (no bit delay)
36 50 (0.5-clock-cycle delay)
37 100 (1-clock-cycle delay)
38 150 (1.5-clock-cycle delay)
39 200 (2-clock-cycle delay)
40
41- renesas,syncdl : delay sync signal (hold) in transmit mode.
42 Must contain one of the following values:
43 0 (no bit delay)
44 50 (0.5-clock-cycle delay)
45 100 (1-clock-cycle delay)
46 150 (1.5-clock-cycle delay)
47 200 (2-clock-cycle delay)
48 300 (3-clock-cycle delay)
33 49
34Optional properties, deprecated for soctype-specific bindings: 50Optional properties, deprecated for soctype-specific bindings:
35- renesas,tx-fifo-size : Overrides the default tx fifo size given in words 51- renesas,tx-fifo-size : Overrides the default tx fifo size given in words
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
index 3ab7a21445fc..e57eec0b2f46 100644
--- a/drivers/spi/spi-sh-msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
@@ -82,6 +82,8 @@ 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_DTDL_SHIFT 20 /* Data Pin Bit Delay for MSIOF_SYNC */
86#define MDR1_SYNCDL_SHIFT 16 /* Frame Sync Signal Timing Delay */
85#define MDR1_FLD_MASK 0x0000000c /* Frame Sync Signal Interval (0-3) */ 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 */
@@ -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 */
@@ -501,7 +542,7 @@ static int sh_msiof_spi_setup(struct spi_device *spi)
501 gpio_set_value(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); 542 gpio_set_value(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
502 543
503 544
504 pm_runtime_put_sync(&p->pdev->dev); 545 pm_runtime_put(&p->pdev->dev);
505 546
506 return 0; 547 return 0;
507} 548}
@@ -595,8 +636,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
595 } 636 }
596 637
597 /* 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 */
598 ret = wait_for_completion_timeout(&p->done, HZ); 639 if (!wait_for_completion_timeout(&p->done, HZ)) {
599 if (!ret) {
600 dev_err(&p->pdev->dev, "PIO timeout\n"); 640 dev_err(&p->pdev->dev, "PIO timeout\n");
601 ret = -ETIMEDOUT; 641 ret = -ETIMEDOUT;
602 goto stop_reset; 642 goto stop_reset;
@@ -706,8 +746,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
706 } 746 }
707 747
708 /* 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 */
709 ret = wait_for_completion_timeout(&p->done, HZ); 749 if (!wait_for_completion_timeout(&p->done, HZ)) {
710 if (!ret) {
711 dev_err(&p->pdev->dev, "DMA timeout\n"); 750 dev_err(&p->pdev->dev, "DMA timeout\n");
712 ret = -ETIMEDOUT; 751 ret = -ETIMEDOUT;
713 goto stop_reset; 752 goto stop_reset;
@@ -957,6 +996,8 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev)
957 &info->tx_fifo_override); 996 &info->tx_fifo_override);
958 of_property_read_u32(np, "renesas,rx-fifo-size", 997 of_property_read_u32(np, "renesas,rx-fifo-size",
959 &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);
960 1001
961 info->num_chipselect = num_cs; 1002 info->num_chipselect = num_cs;
962 1003
diff --git a/include/linux/spi/sh_msiof.h b/include/linux/spi/sh_msiof.h
index 88a14d81c49e..b087a85f5f72 100644
--- a/include/linux/spi/sh_msiof.h
+++ b/include/linux/spi/sh_msiof.h
@@ -7,6 +7,8 @@ struct sh_msiof_spi_info {
7 u16 num_chipselect; 7 u16 num_chipselect;
8 unsigned int dma_tx_id; 8 unsigned int dma_tx_id;
9 unsigned int dma_rx_id; 9 unsigned int dma_rx_id;
10 u32 dtdl;
11 u32 syncdl;
10}; 12};
11 13
12#endif /* __SPI_SH_MSIOF_H__ */ 14#endif /* __SPI_SH_MSIOF_H__ */