aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeert Uytterhoeven <geert+renesas@glider.be>2017-07-12 06:26:01 -0400
committerMark Brown <broonie@kernel.org>2017-07-17 07:09:59 -0400
commit61a8dec502b873879fa240ec7614601523b46a43 (patch)
tree74b5d8eddd0b48ac4b101fe91224986ed2360764
parent3d108f1e2d4c21026750cd4107e03b3e7a3e98a0 (diff)
spi: sh-msiof: Limit minimum divider on R-Car Gen3
On R-Car Gen3 SoCs (excluding R-Car H3 ES1.x, which cannot be used for SPI due to a hardware erratum), BRPS x BRDV = 1/1 is an invalid divider setting. Implement this limitation using an SoC/family-specific minimum divider. Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/spi/spi-sh-msiof.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
index c304c7167866..0eb1e9583485 100644
--- a/drivers/spi/spi-sh-msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
@@ -38,6 +38,7 @@ struct sh_msiof_chipdata {
38 u16 tx_fifo_size; 38 u16 tx_fifo_size;
39 u16 rx_fifo_size; 39 u16 rx_fifo_size;
40 u16 master_flags; 40 u16 master_flags;
41 u16 min_div;
41}; 42};
42 43
43struct sh_msiof_spi_priv { 44struct sh_msiof_spi_priv {
@@ -49,6 +50,7 @@ struct sh_msiof_spi_priv {
49 struct completion done; 50 struct completion done;
50 unsigned int tx_fifo_size; 51 unsigned int tx_fifo_size;
51 unsigned int rx_fifo_size; 52 unsigned int rx_fifo_size;
53 unsigned int min_div;
52 void *tx_dma_page; 54 void *tx_dma_page;
53 void *rx_dma_page; 55 void *rx_dma_page;
54 dma_addr_t tx_dma_addr; 56 dma_addr_t tx_dma_addr;
@@ -261,6 +263,8 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
261 if (!WARN_ON(!spi_hz || !parent_rate)) 263 if (!WARN_ON(!spi_hz || !parent_rate))
262 div = DIV_ROUND_UP(parent_rate, spi_hz); 264 div = DIV_ROUND_UP(parent_rate, spi_hz);
263 265
266 div = max_t(unsigned long, div, p->min_div);
267
264 for (k = 0; k < ARRAY_SIZE(sh_msiof_spi_div_table); k++) { 268 for (k = 0; k < ARRAY_SIZE(sh_msiof_spi_div_table); k++) {
265 brps = DIV_ROUND_UP(div, sh_msiof_spi_div_table[k].div); 269 brps = DIV_ROUND_UP(div, sh_msiof_spi_div_table[k].div);
266 /* SCR_BRDV_DIV_1 is valid only if BRPS is x 1/1 or x 1/2 */ 270 /* SCR_BRDV_DIV_1 is valid only if BRPS is x 1/1 or x 1/2 */
@@ -998,24 +1002,33 @@ static const struct sh_msiof_chipdata sh_data = {
998 .tx_fifo_size = 64, 1002 .tx_fifo_size = 64,
999 .rx_fifo_size = 64, 1003 .rx_fifo_size = 64,
1000 .master_flags = 0, 1004 .master_flags = 0,
1005 .min_div = 1,
1006};
1007
1008static const struct sh_msiof_chipdata rcar_gen2_data = {
1009 .tx_fifo_size = 64,
1010 .rx_fifo_size = 64,
1011 .master_flags = SPI_MASTER_MUST_TX,
1012 .min_div = 1,
1001}; 1013};
1002 1014
1003static const struct sh_msiof_chipdata r8a779x_data = { 1015static const struct sh_msiof_chipdata rcar_gen3_data = {
1004 .tx_fifo_size = 64, 1016 .tx_fifo_size = 64,
1005 .rx_fifo_size = 64, 1017 .rx_fifo_size = 64,
1006 .master_flags = SPI_MASTER_MUST_TX, 1018 .master_flags = SPI_MASTER_MUST_TX,
1019 .min_div = 2,
1007}; 1020};
1008 1021
1009static const struct of_device_id sh_msiof_match[] = { 1022static const struct of_device_id sh_msiof_match[] = {
1010 { .compatible = "renesas,sh-mobile-msiof", .data = &sh_data }, 1023 { .compatible = "renesas,sh-mobile-msiof", .data = &sh_data },
1011 { .compatible = "renesas,msiof-r8a7790", .data = &r8a779x_data }, 1024 { .compatible = "renesas,msiof-r8a7790", .data = &rcar_gen2_data },
1012 { .compatible = "renesas,msiof-r8a7791", .data = &r8a779x_data }, 1025 { .compatible = "renesas,msiof-r8a7791", .data = &rcar_gen2_data },
1013 { .compatible = "renesas,msiof-r8a7792", .data = &r8a779x_data }, 1026 { .compatible = "renesas,msiof-r8a7792", .data = &rcar_gen2_data },
1014 { .compatible = "renesas,msiof-r8a7793", .data = &r8a779x_data }, 1027 { .compatible = "renesas,msiof-r8a7793", .data = &rcar_gen2_data },
1015 { .compatible = "renesas,msiof-r8a7794", .data = &r8a779x_data }, 1028 { .compatible = "renesas,msiof-r8a7794", .data = &rcar_gen2_data },
1016 { .compatible = "renesas,rcar-gen2-msiof", .data = &r8a779x_data }, 1029 { .compatible = "renesas,rcar-gen2-msiof", .data = &rcar_gen2_data },
1017 { .compatible = "renesas,msiof-r8a7796", .data = &r8a779x_data }, 1030 { .compatible = "renesas,msiof-r8a7796", .data = &rcar_gen3_data },
1018 { .compatible = "renesas,rcar-gen3-msiof", .data = &r8a779x_data }, 1031 { .compatible = "renesas,rcar-gen3-msiof", .data = &rcar_gen3_data },
1019 { .compatible = "renesas,sh-msiof", .data = &sh_data }, /* Deprecated */ 1032 { .compatible = "renesas,sh-msiof", .data = &sh_data }, /* Deprecated */
1020 {}, 1033 {},
1021}; 1034};
@@ -1230,6 +1243,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
1230 platform_set_drvdata(pdev, p); 1243 platform_set_drvdata(pdev, p);
1231 p->master = master; 1244 p->master = master;
1232 p->info = info; 1245 p->info = info;
1246 p->min_div = chipdata->min_div;
1233 1247
1234 init_completion(&p->done); 1248 init_completion(&p->done);
1235 1249