summaryrefslogtreecommitdiff
path: root/drivers/spi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/davinci_spi.c53
1 files changed, 31 insertions, 22 deletions
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
index d5d7014e6ae2..17269ad54a99 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/davinci_spi.c
@@ -53,6 +53,7 @@
#define SPIFMT_WDELAY_MASK 0x3f000000u
#define SPIFMT_WDELAY_SHIFT 24
#define SPIFMT_CHARLEN_MASK 0x0000001Fu
+#define SPIFMT_PRESCALE_SHIFT 8
/* SPIPC0 */
@@ -267,6 +268,29 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
}
/**
+ * davinci_spi_get_prescale - Calculates the correct prescale value
+ * @maxspeed_hz: the maximum rate the SPI clock can run at
+ *
+ * This function calculates the prescale value that generates a clock rate
+ * less than or equal to the specified maximum.
+ *
+ * Returns: calculated prescale - 1 for easy programming into SPI registers
+ * or negative error number if valid prescalar cannot be updated.
+ */
+static inline int davinci_spi_get_prescale(struct davinci_spi *davinci_spi,
+ u32 max_speed_hz)
+{
+ int ret;
+
+ ret = DIV_ROUND_UP(clk_get_rate(davinci_spi->clk), max_speed_hz);
+
+ if (ret < 3 || ret > 256)
+ return -EINVAL;
+
+ return ret - 1;
+}
+
+/**
* davinci_spi_setup_transfer - This functions will determine transfer method
* @spi: spi device on which data transfer to be done
* @t: spi transfer in which transfer info is filled
@@ -281,7 +305,7 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
struct davinci_spi *davinci_spi;
u8 bits_per_word = 0;
- u32 hz = 0, prescale = 0, clkspeed;
+ u32 hz = 0, prescale = 0;
davinci_spi = spi_master_get_devdata(spi->master);
@@ -312,21 +336,18 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
if (!hz)
hz = spi->max_speed_hz;
+ prescale = davinci_spi_get_prescale(davinci_spi, hz);
+ if (prescale < 0)
+ return prescale;
+
clear_fmt_bits(davinci_spi->base, SPIFMT_CHARLEN_MASK,
spi->chip_select);
set_fmt_bits(davinci_spi->base, bits_per_word & 0x1f,
spi->chip_select);
- clkspeed = clk_get_rate(davinci_spi->clk);
- if (hz > clkspeed / 2)
- prescale = 1 << 8;
- if (hz < clkspeed / 256)
- prescale = 255 << 8;
- if (!prescale)
- prescale = ((clkspeed / hz - 1) << 8) & 0x0000ff00;
-
clear_fmt_bits(davinci_spi->base, 0x0000ff00, spi->chip_select);
- set_fmt_bits(davinci_spi->base, prescale, spi->chip_select);
+ set_fmt_bits(davinci_spi->base,
+ prescale << SPIFMT_PRESCALE_SHIFT, spi->chip_select);
return 0;
}
@@ -413,10 +434,8 @@ static int davinci_spi_setup(struct spi_device *spi)
int retval;
struct davinci_spi *davinci_spi;
struct davinci_spi_dma *davinci_spi_dma;
- struct device *sdev;
davinci_spi = spi_master_get_devdata(spi->master);
- sdev = davinci_spi->bitbang.master->dev.parent;
/* if bits per word length is zero then set it default 8 */
if (!spi->bits_per_word)
@@ -436,16 +455,6 @@ static int davinci_spi_setup(struct spi_device *spi)
}
/*
- * SPI in DaVinci and DA8xx operate between
- * 600 KHz and 50 MHz
- */
- if (spi->max_speed_hz < 600000 || spi->max_speed_hz > 50000000) {
- dev_dbg(sdev, "Operating frequency is not in acceptable "
- "range\n");
- return -EINVAL;
- }
-
- /*
* Set up SPIFMTn register, unique to this chipselect.
*
* NOTE: we could do all of these with one write. Also, some