Commit 81059366 authored by Alexandru Ardelean's avatar Alexandru Ardelean Committed by Mark Brown

spi: tegra114: change format for `spi_set_cs_timing()` function

The initial version of `spi_set_cs_timing()` was implemented with
consideration only for clock-cycles as delay.

For cases like `CS setup` time, it's sometimes needed that micro-seconds
(or nano-seconds) are required, or sometimes even longer delays, for cases
where the device needs a little longer to start transferring that after CS
is asserted.
Signed-off-by: default avatarAlexandru Ardelean <alexandru.ardelean@analog.com>
Link: https://lore.kernel.org/r/20190926105147.7839-15-alexandru.ardelean@analog.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 8e319dd5
...@@ -723,15 +723,31 @@ static void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi, ...@@ -723,15 +723,31 @@ static void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi,
dma_release_channel(dma_chan); dma_release_channel(dma_chan);
} }
static void tegra_spi_set_hw_cs_timing(struct spi_device *spi, u8 setup_dly, static int tegra_spi_set_hw_cs_timing(struct spi_device *spi,
u8 hold_dly, u8 inactive_dly) struct spi_delay *setup,
struct spi_delay *hold,
struct spi_delay *inactive)
{ {
struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master); struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
u8 setup_dly, hold_dly, inactive_dly;
u32 setup_hold; u32 setup_hold;
u32 spi_cs_timing; u32 spi_cs_timing;
u32 inactive_cycles; u32 inactive_cycles;
u8 cs_state; u8 cs_state;
if ((setup && setup->unit != SPI_DELAY_UNIT_SCK) ||
(hold && hold->unit != SPI_DELAY_UNIT_SCK) ||
(inactive && inactive->unit != SPI_DELAY_UNIT_SCK)) {
dev_err(&spi->dev,
"Invalid delay unit %d, should be SPI_DELAY_UNIT_SCK\n",
SPI_DELAY_UNIT_SCK);
return -EINVAL;
}
setup_dly = setup ? setup->value : 0;
hold_dly = hold ? hold->value : 0;
inactive_dly = inactive ? inactive->value : 0;
setup_dly = min_t(u8, setup_dly, MAX_SETUP_HOLD_CYCLES); setup_dly = min_t(u8, setup_dly, MAX_SETUP_HOLD_CYCLES);
hold_dly = min_t(u8, hold_dly, MAX_SETUP_HOLD_CYCLES); hold_dly = min_t(u8, hold_dly, MAX_SETUP_HOLD_CYCLES);
if (setup_dly && hold_dly) { if (setup_dly && hold_dly) {
...@@ -758,6 +774,8 @@ static void tegra_spi_set_hw_cs_timing(struct spi_device *spi, u8 setup_dly, ...@@ -758,6 +774,8 @@ static void tegra_spi_set_hw_cs_timing(struct spi_device *spi, u8 setup_dly,
tspi->spi_cs_timing2 = spi_cs_timing; tspi->spi_cs_timing2 = spi_cs_timing;
tegra_spi_writel(tspi, spi_cs_timing, SPI_CS_TIMING2); tegra_spi_writel(tspi, spi_cs_timing, SPI_CS_TIMING2);
} }
return 0;
} }
static u32 tegra_spi_setup_transfer_one(struct spi_device *spi, static u32 tegra_spi_setup_transfer_one(struct spi_device *spi,
......
...@@ -3269,15 +3269,19 @@ EXPORT_SYMBOL_GPL(spi_setup); ...@@ -3269,15 +3269,19 @@ EXPORT_SYMBOL_GPL(spi_setup);
/** /**
* spi_set_cs_timing - configure CS setup, hold, and inactive delays * spi_set_cs_timing - configure CS setup, hold, and inactive delays
* @spi: the device that requires specific CS timing configuration * @spi: the device that requires specific CS timing configuration
* @setup: CS setup time in terms of clock count * @setup: CS setup time specified via @spi_delay
* @hold: CS hold time in terms of clock count * @hold: CS hold time specified via @spi_delay
* @inactive_dly: CS inactive delay between transfers in terms of clock count * @inactive: CS inactive delay between transfers specified via @spi_delay
*
* Return: zero on success, else a negative error code.
*/ */
void spi_set_cs_timing(struct spi_device *spi, u8 setup, u8 hold, int spi_set_cs_timing(struct spi_device *spi, struct spi_delay *setup,
u8 inactive_dly) struct spi_delay *hold, struct spi_delay *inactive)
{ {
if (spi->controller->set_cs_timing) if (spi->controller->set_cs_timing)
spi->controller->set_cs_timing(spi, setup, hold, inactive_dly); return spi->controller->set_cs_timing(spi, setup, hold,
inactive);
return -ENOTSUPP;
} }
EXPORT_SYMBOL_GPL(spi_set_cs_timing); EXPORT_SYMBOL_GPL(spi_set_cs_timing);
......
...@@ -524,8 +524,8 @@ struct spi_controller { ...@@ -524,8 +524,8 @@ struct spi_controller {
* to configure specific CS timing through spi_set_cs_timing() after * to configure specific CS timing through spi_set_cs_timing() after
* spi_setup(). * spi_setup().
*/ */
void (*set_cs_timing)(struct spi_device *spi, u8 setup_clk_cycles, int (*set_cs_timing)(struct spi_device *spi, struct spi_delay *setup,
u8 hold_clk_cycles, u8 inactive_clk_cycles); struct spi_delay *hold, struct spi_delay *inactive);
/* bidirectional bulk transfers /* bidirectional bulk transfers
* *
...@@ -1068,7 +1068,10 @@ static inline void spi_message_free(struct spi_message *m) ...@@ -1068,7 +1068,10 @@ static inline void spi_message_free(struct spi_message *m)
kfree(m); kfree(m);
} }
extern void spi_set_cs_timing(struct spi_device *spi, u8 setup, u8 hold, u8 inactive_dly); extern int spi_set_cs_timing(struct spi_device *spi,
struct spi_delay *setup,
struct spi_delay *hold,
struct spi_delay *inactive);
extern int spi_setup(struct spi_device *spi); extern int spi_setup(struct spi_device *spi);
extern int spi_async(struct spi_device *spi, struct spi_message *message); extern int spi_async(struct spi_device *spi, struct spi_message *message);
......
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