提交 7fe0092b 编写于 作者: B Brian Niebuhr 提交者: Sekhar Nori

spi: davinci: simplify prescalar calculation

Simplify pre-scalar calculation and move it into a seprate
function.

Refuse to correct invalid pre-scalar values silently as this
might lead to unexpected bugs and lower performance. Instead
an error will force users to dig into the root-cause of the
issue.

While at it, remove some device specific checks on the maximum
SPI frequency. As the driver supports the SPI interface
implemented on various devices, it should only take care of core
SPI limitations and leave the device specific handling to platform
code.
Signed-off-by: NBrian Niebuhr <bniebuhr@efjohnson.com>
Tested-By: NMichael Williamson <michael.williamson@criticallink.com>
Signed-off-by: NSekhar Nori <nsekhar@ti.com>
上级 23853973
......@@ -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 */
......@@ -266,6 +267,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
......@@ -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)
......@@ -435,16 +454,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.
*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册