diff options
author | Geert Uytterhoeven <geert+renesas@glider.be> | 2017-07-12 06:26:01 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2017-07-17 07:09:59 -0400 |
commit | 61a8dec502b873879fa240ec7614601523b46a43 (patch) | |
tree | 74b5d8eddd0b48ac4b101fe91224986ed2360764 | |
parent | 3d108f1e2d4c21026750cd4107e03b3e7a3e98a0 (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.c | 32 |
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 | ||
43 | struct sh_msiof_spi_priv { | 44 | struct 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 | |||
1008 | static 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 | ||
1003 | static const struct sh_msiof_chipdata r8a779x_data = { | 1015 | static 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 | ||
1009 | static const struct of_device_id sh_msiof_match[] = { | 1022 | static 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 | ||