diff options
Diffstat (limited to 'drivers/spi/spi-imx.c')
-rw-r--r-- | drivers/spi/spi-imx.c | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index b80f2f70fef7..47f15d97e7fa 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c | |||
@@ -206,7 +206,8 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin, | |||
206 | #define MX51_ECSPI_STAT_RR (1 << 3) | 206 | #define MX51_ECSPI_STAT_RR (1 << 3) |
207 | 207 | ||
208 | /* MX51 eCSPI */ | 208 | /* MX51 eCSPI */ |
209 | static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi) | 209 | static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi, |
210 | unsigned int *fres) | ||
210 | { | 211 | { |
211 | /* | 212 | /* |
212 | * there are two 4-bit dividers, the pre-divider divides by | 213 | * there are two 4-bit dividers, the pre-divider divides by |
@@ -234,6 +235,10 @@ static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi) | |||
234 | 235 | ||
235 | pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n", | 236 | pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n", |
236 | __func__, fin, fspi, post, pre); | 237 | __func__, fin, fspi, post, pre); |
238 | |||
239 | /* Resulting frequency for the SCLK line. */ | ||
240 | *fres = (fin / (pre + 1)) >> post; | ||
241 | |||
237 | return (pre << MX51_ECSPI_CTRL_PREDIV_OFFSET) | | 242 | return (pre << MX51_ECSPI_CTRL_PREDIV_OFFSET) | |
238 | (post << MX51_ECSPI_CTRL_POSTDIV_OFFSET); | 243 | (post << MX51_ECSPI_CTRL_POSTDIV_OFFSET); |
239 | } | 244 | } |
@@ -264,6 +269,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, | |||
264 | struct spi_imx_config *config) | 269 | struct spi_imx_config *config) |
265 | { | 270 | { |
266 | u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0; | 271 | u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0; |
272 | u32 clk = config->speed_hz, delay; | ||
267 | 273 | ||
268 | /* | 274 | /* |
269 | * The hardware seems to have a race condition when changing modes. The | 275 | * The hardware seems to have a race condition when changing modes. The |
@@ -275,7 +281,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, | |||
275 | ctrl |= MX51_ECSPI_CTRL_MODE_MASK; | 281 | ctrl |= MX51_ECSPI_CTRL_MODE_MASK; |
276 | 282 | ||
277 | /* set clock speed */ | 283 | /* set clock speed */ |
278 | ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz); | 284 | ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz, &clk); |
279 | 285 | ||
280 | /* set chip select to use */ | 286 | /* set chip select to use */ |
281 | ctrl |= MX51_ECSPI_CTRL_CS(config->cs); | 287 | ctrl |= MX51_ECSPI_CTRL_CS(config->cs); |
@@ -297,6 +303,23 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, | |||
297 | writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); | 303 | writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); |
298 | writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); | 304 | writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); |
299 | 305 | ||
306 | /* | ||
307 | * Wait until the changes in the configuration register CONFIGREG | ||
308 | * propagate into the hardware. It takes exactly one tick of the | ||
309 | * SCLK clock, but we will wait two SCLK clock just to be sure. The | ||
310 | * effect of the delay it takes for the hardware to apply changes | ||
311 | * is noticable if the SCLK clock run very slow. In such a case, if | ||
312 | * the polarity of SCLK should be inverted, the GPIO ChipSelect might | ||
313 | * be asserted before the SCLK polarity changes, which would disrupt | ||
314 | * the SPI communication as the device on the other end would consider | ||
315 | * the change of SCLK polarity as a clock tick already. | ||
316 | */ | ||
317 | delay = (2 * 1000000) / clk; | ||
318 | if (likely(delay < 10)) /* SCLK is faster than 100 kHz */ | ||
319 | udelay(delay); | ||
320 | else /* SCLK is _very_ slow */ | ||
321 | usleep_range(delay, delay + 10); | ||
322 | |||
300 | return 0; | 323 | return 0; |
301 | } | 324 | } |
302 | 325 | ||
@@ -925,8 +948,8 @@ static int spi_imx_remove(struct platform_device *pdev) | |||
925 | spi_bitbang_stop(&spi_imx->bitbang); | 948 | spi_bitbang_stop(&spi_imx->bitbang); |
926 | 949 | ||
927 | writel(0, spi_imx->base + MXC_CSPICTRL); | 950 | writel(0, spi_imx->base + MXC_CSPICTRL); |
928 | clk_disable_unprepare(spi_imx->clk_ipg); | 951 | clk_unprepare(spi_imx->clk_ipg); |
929 | clk_disable_unprepare(spi_imx->clk_per); | 952 | clk_unprepare(spi_imx->clk_per); |
930 | spi_master_put(master); | 953 | spi_master_put(master); |
931 | 954 | ||
932 | return 0; | 955 | return 0; |