diff options
Diffstat (limited to 'drivers/spi/spi-ep93xx.c')
-rw-r--r-- | drivers/spi/spi-ep93xx.c | 57 |
1 files changed, 25 insertions, 32 deletions
diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 6cdfc4036b75..2e64806b40af 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c | |||
@@ -136,18 +136,10 @@ struct ep93xx_spi { | |||
136 | /** | 136 | /** |
137 | * struct ep93xx_spi_chip - SPI device hardware settings | 137 | * struct ep93xx_spi_chip - SPI device hardware settings |
138 | * @spi: back pointer to the SPI device | 138 | * @spi: back pointer to the SPI device |
139 | * @div_cpsr: cpsr (pre-scaler) divider | ||
140 | * @div_scr: scr divider | ||
141 | * @ops: private chip operations | 139 | * @ops: private chip operations |
142 | * | ||
143 | * This structure is used to store hardware register specific settings for each | ||
144 | * SPI device. Settings are written to hardware by function | ||
145 | * ep93xx_spi_chip_setup(). | ||
146 | */ | 140 | */ |
147 | struct ep93xx_spi_chip { | 141 | struct ep93xx_spi_chip { |
148 | const struct spi_device *spi; | 142 | const struct spi_device *spi; |
149 | u8 div_cpsr; | ||
150 | u8 div_scr; | ||
151 | struct ep93xx_spi_chip_ops *ops; | 143 | struct ep93xx_spi_chip_ops *ops; |
152 | }; | 144 | }; |
153 | 145 | ||
@@ -224,17 +216,13 @@ static void ep93xx_spi_disable_interrupts(const struct ep93xx_spi *espi) | |||
224 | /** | 216 | /** |
225 | * ep93xx_spi_calc_divisors() - calculates SPI clock divisors | 217 | * ep93xx_spi_calc_divisors() - calculates SPI clock divisors |
226 | * @espi: ep93xx SPI controller struct | 218 | * @espi: ep93xx SPI controller struct |
227 | * @chip: divisors are calculated for this chip | ||
228 | * @rate: desired SPI output clock rate | 219 | * @rate: desired SPI output clock rate |
229 | * | 220 | * @div_cpsr: pointer to return the cpsr (pre-scaler) divider |
230 | * Function calculates cpsr (clock pre-scaler) and scr divisors based on | 221 | * @div_scr: pointer to return the scr divider |
231 | * given @rate and places them to @chip->div_cpsr and @chip->div_scr. If, | ||
232 | * for some reason, divisors cannot be calculated nothing is stored and | ||
233 | * %-EINVAL is returned. | ||
234 | */ | 222 | */ |
235 | static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, | 223 | static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, |
236 | struct ep93xx_spi_chip *chip, | 224 | unsigned long rate, |
237 | unsigned long rate) | 225 | u8 *div_cpsr, u8 *div_scr) |
238 | { | 226 | { |
239 | unsigned long spi_clk_rate = clk_get_rate(espi->clk); | 227 | unsigned long spi_clk_rate = clk_get_rate(espi->clk); |
240 | int cpsr, scr; | 228 | int cpsr, scr; |
@@ -257,8 +245,8 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, | |||
257 | for (cpsr = 2; cpsr <= 254; cpsr += 2) { | 245 | for (cpsr = 2; cpsr <= 254; cpsr += 2) { |
258 | for (scr = 0; scr <= 255; scr++) { | 246 | for (scr = 0; scr <= 255; scr++) { |
259 | if ((spi_clk_rate / (cpsr * (scr + 1))) <= rate) { | 247 | if ((spi_clk_rate / (cpsr * (scr + 1))) <= rate) { |
260 | chip->div_scr = (u8)scr; | 248 | *div_scr = (u8)scr; |
261 | chip->div_cpsr = (u8)cpsr; | 249 | *div_cpsr = (u8)cpsr; |
262 | return 0; | 250 | return 0; |
263 | } | 251 | } |
264 | } | 252 | } |
@@ -389,29 +377,35 @@ static void ep93xx_spi_cleanup(struct spi_device *spi) | |||
389 | * ep93xx_spi_chip_setup() - configures hardware according to given @chip | 377 | * ep93xx_spi_chip_setup() - configures hardware according to given @chip |
390 | * @espi: ep93xx SPI controller struct | 378 | * @espi: ep93xx SPI controller struct |
391 | * @chip: chip specific settings | 379 | * @chip: chip specific settings |
380 | * @speed_hz: transfer speed | ||
392 | * @bits_per_word: transfer bits_per_word | 381 | * @bits_per_word: transfer bits_per_word |
393 | * | ||
394 | * This function sets up the actual hardware registers with settings given in | ||
395 | * @chip. Note that no validation is done so make sure that callers validate | ||
396 | * settings before calling this. | ||
397 | */ | 382 | */ |
398 | static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, | 383 | static int ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, |
399 | const struct ep93xx_spi_chip *chip, | 384 | const struct ep93xx_spi_chip *chip, |
400 | u8 bits_per_word) | 385 | u32 speed_hz, u8 bits_per_word) |
401 | { | 386 | { |
402 | u8 dss = bits_per_word_to_dss(bits_per_word); | 387 | u8 dss = bits_per_word_to_dss(bits_per_word); |
388 | u8 div_cpsr = 0; | ||
389 | u8 div_scr = 0; | ||
403 | u16 cr0; | 390 | u16 cr0; |
391 | int err; | ||
392 | |||
393 | err = ep93xx_spi_calc_divisors(espi, speed_hz, &div_cpsr, &div_scr); | ||
394 | if (err) | ||
395 | return err; | ||
404 | 396 | ||
405 | cr0 = chip->div_scr << SSPCR0_SCR_SHIFT; | 397 | cr0 = div_scr << SSPCR0_SCR_SHIFT; |
406 | cr0 |= (chip->spi->mode & (SPI_CPHA|SPI_CPOL)) << SSPCR0_MODE_SHIFT; | 398 | cr0 |= (chip->spi->mode & (SPI_CPHA|SPI_CPOL)) << SSPCR0_MODE_SHIFT; |
407 | cr0 |= dss; | 399 | cr0 |= dss; |
408 | 400 | ||
409 | dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n", | 401 | dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n", |
410 | chip->spi->mode, chip->div_cpsr, chip->div_scr, dss); | 402 | chip->spi->mode, div_cpsr, div_scr, dss); |
411 | dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0); | 403 | dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0); |
412 | 404 | ||
413 | ep93xx_spi_write_u8(espi, SSPCPSR, chip->div_cpsr); | 405 | ep93xx_spi_write_u8(espi, SSPCPSR, div_cpsr); |
414 | ep93xx_spi_write_u16(espi, SSPCR0, cr0); | 406 | ep93xx_spi_write_u16(espi, SSPCR0, cr0); |
407 | |||
408 | return 0; | ||
415 | } | 409 | } |
416 | 410 | ||
417 | static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t) | 411 | static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t) |
@@ -687,15 +681,14 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi, | |||
687 | 681 | ||
688 | msg->state = t; | 682 | msg->state = t; |
689 | 683 | ||
690 | err = ep93xx_spi_calc_divisors(espi, chip, t->speed_hz); | 684 | err = ep93xx_spi_chip_setup(espi, chip, t->speed_hz, t->bits_per_word); |
691 | if (err) { | 685 | if (err) { |
692 | dev_err(&espi->pdev->dev, "failed to adjust speed\n"); | 686 | dev_err(&espi->pdev->dev, |
687 | "failed to setup chip for transfer\n"); | ||
693 | msg->status = err; | 688 | msg->status = err; |
694 | return; | 689 | return; |
695 | } | 690 | } |
696 | 691 | ||
697 | ep93xx_spi_chip_setup(espi, chip, t->bits_per_word); | ||
698 | |||
699 | espi->rx = 0; | 692 | espi->rx = 0; |
700 | espi->tx = 0; | 693 | espi->tx = 0; |
701 | 694 | ||