summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Brice <aaron.brice@datasoft.com>2015-04-03 23:39:29 +0300
committerMark Brown <broonie@kernel.org>2015-04-06 20:11:19 +0300
commite689d6df8257f92abf59e93736632b79c9b2aa66 (patch)
tree741f6c42c8409550e05085fef5bcc7cccb0e5774
parentc517d838eb7d07bbe9507871fab3931deccff539 (diff)
downloadlinux-e689d6df8257f92abf59e93736632b79c9b2aa66.tar.xz
spi: fsl-dspi: Fix clock rate scale values
Previous algorithm had an outer loop with the values {2,3,5,7} and an inner loop with {2,4,6,8,16,32,...,32768}, and would pick the first value over the required scaling value (where the total scale was the two numbers multiplied). Since the inner loop went up to 32768 it would always pick a value of 2 for PBR and a much higher than necessary value for BR. The desired scale factor was being divided by two I believe to compensate for the much higher scale factors (the divide by two not specified in the reference manual). Updated to check all values and find the smallest scale factor possible without going over the desired clock rate. Signed-off-by: Aaron Brice <aaron.brice@datasoft.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/spi/spi-fsl-dspi.c37
1 files changed, 23 insertions, 14 deletions
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index d1a39249704a..82133584c0ea 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -148,23 +148,32 @@ static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
16, 32, 64, 128,
256, 512, 1024, 2048,
4096, 8192, 16384, 32768 };
- int temp, i = 0, j = 0;
-
- temp = clkrate / 2 / speed_hz;
-
- for (i = 0; i < ARRAY_SIZE(pbr_tbl); i++)
- for (j = 0; j < ARRAY_SIZE(brs); j++) {
- if (pbr_tbl[i] * brs[j] >= temp) {
- *pbr = i;
- *br = j;
- return;
+ int scale_needed, scale, minscale = INT_MAX;
+ int i, j;
+
+ scale_needed = clkrate / speed_hz;
+ if (clkrate % speed_hz)
+ scale_needed++;
+
+ for (i = 0; i < ARRAY_SIZE(brs); i++)
+ for (j = 0; j < ARRAY_SIZE(pbr_tbl); j++) {
+ scale = brs[i] * pbr_tbl[j];
+ if (scale >= scale_needed) {
+ if (scale < minscale) {
+ minscale = scale;
+ *br = i;
+ *pbr = j;
+ }
+ break;
}
}
- pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is %ld\
- ,we use the max prescaler value.\n", speed_hz, clkrate);
- *pbr = ARRAY_SIZE(pbr_tbl) - 1;
- *br = ARRAY_SIZE(brs) - 1;
+ if (minscale == INT_MAX) {
+ pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is %ld, we use the max prescaler value.\n",
+ speed_hz, clkrate);
+ *pbr = ARRAY_SIZE(pbr_tbl) - 1;
+ *br = ARRAY_SIZE(brs) - 1;
+ }
}
static int dspi_transfer_write(struct fsl_dspi *dspi)