Commit 6064893a authored by Imre Deak's avatar Imre Deak Committed by Juha Yrjola

ARM: OMAP: uWire clock calculation

In the uWire driver only one of the clock dividers was used to set
the clock to the required frequency. This will add a loop to try all
possible combinations using the other divider as well.
Signed-off-by: default avatarImre Deak <imre.deak@nokia.com>
Signed-off-by: default avatarJuha Yrjölä <juha.yrjola@nokia.com>
parent 202b883f
...@@ -290,9 +290,12 @@ eio: ...@@ -290,9 +290,12 @@ eio:
static int uwire_setup(struct spi_device *spi) static int uwire_setup(struct spi_device *spi)
{ {
struct uwire_spi *uwire; struct uwire_spi *uwire;
unsigned flags = 0; unsigned flags = 0;
unsigned long rate; unsigned long rate;
u16 div1; int div1_idx;
int div1;
int div2;
u16 w;
int status; int status;
uwire = spi_master_get_devdata(spi->master); uwire = spi_master_get_devdata(spi->master);
...@@ -335,36 +338,60 @@ static int uwire_setup(struct spi_device *spi) ...@@ -335,36 +338,60 @@ static int uwire_setup(struct spi_device *spi)
rate = clk_get_rate(uwire->ck); rate = clk_get_rate(uwire->ck);
/* F_INT = mpu_per_clk / DIV1 */ /* F_INT = mpu_per_clk / DIV1 */
div1 = (uwire_read_reg(UWIRE_SR3) >> 1) & 0x3; for (div1_idx = 0; div1_idx < 4; div1_idx++) {
switch (div1) { switch (div1_idx) {
case 0: rate /= 2; break; case 0:
case 1: rate /= 4; break; div1 = 2;
case 2: rate /= 7; break; break;
case 3: rate /= 10; break; case 1:
div1 = 4;
break;
case 2:
div1 = 7;
break;
default:
case 3:
div1 = 10;
break;
}
div2 = (rate / div1 + spi->max_speed_hz - 1) /
spi->max_speed_hz;
if (div2 <= 8)
break;
}
if (div1_idx == 4) {
pr_debug("%s: lowest clock %ld, need %d\n",
spi->dev.bus_id, rate / 10 / 8, spi->max_speed_hz);
status = -EDOM;
goto done;
} }
/* SCLK = F_INT / DIV2 */ w = uwire_read_reg(UWIRE_SR3);
rate >>= 1; w &= ~(0x03 << 1);
if (rate <= spi->max_speed_hz) w |= div1_idx << 1;
uwire_write_reg(UWIRE_SR3, w);
rate /= div1;
switch (div2) {
case 0:
case 1:
case 2:
flags |= UWIRE_FREQ_DIV_2; flags |= UWIRE_FREQ_DIV_2;
else { rate /= 2;
rate >>= 1; break;
if (rate <= spi->max_speed_hz) case 3:
flags |= UWIRE_FREQ_DIV_4; case 4:
else { flags |= UWIRE_FREQ_DIV_4;
rate >>= 1; rate /= 4;
if (rate <= spi->max_speed_hz) break;
flags |= UWIRE_FREQ_DIV_8; case 5:
else { case 6:
/* REVISIT: we could change DIV2 */ case 7:
pr_debug("%s: lowest clock %ld, need %d, " case 8:
"div1 %d\n", flags |= UWIRE_FREQ_DIV_8;
spi->dev.bus_id, rate, rate /= 8;
spi->max_speed_hz, div1); break;
status = -EDOM;
goto done;
}
}
} }
omap_uwire_configure_mode(spi->chip_select, flags); omap_uwire_configure_mode(spi->chip_select, flags);
pr_debug("%s: uwire flags %02x, armper %lu KHz, SCK %lu KHz\n", pr_debug("%s: uwire flags %02x, armper %lu KHz, SCK %lu KHz\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment