summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/spi/spi-zynqmp-gqspi.c49
1 files changed, 35 insertions, 14 deletions
diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
index 1b56dd29057f..0fecea338027 100644
--- a/drivers/spi/spi-zynqmp-gqspi.c
+++ b/drivers/spi/spi-zynqmp-gqspi.c
@@ -159,6 +159,7 @@ enum mode_type {GQSPI_MODE_IO, GQSPI_MODE_DMA};
* @mode: Defines the mode in which QSPI is operating
* @data_completion: completion structure
* @op_lock: Operational lock
+ * @speed_hz: Current SPI bus clock speed in hz
*/
struct zynqmp_qspi {
struct spi_controller *ctlr;
@@ -179,6 +180,7 @@ struct zynqmp_qspi {
enum mode_type mode;
struct completion data_completion;
struct mutex op_lock;
+ u32 speed_hz;
};
/**
@@ -273,7 +275,8 @@ static void zynqmp_gqspi_selectslave(struct zynqmp_qspi *instanceptr,
*/
static void zynqmp_qspi_init_hw(struct zynqmp_qspi *xqspi)
{
- u32 config_reg;
+ u32 config_reg, baud_rate_val = 0;
+ ulong clk_rate;
/* Select the GQSPI mode */
zynqmp_gqspi_write(xqspi, GQSPI_SEL_OFST, GQSPI_SEL_MASK);
@@ -318,6 +321,16 @@ static void zynqmp_qspi_init_hw(struct zynqmp_qspi *xqspi)
else
config_reg &= ~GQSPI_CFG_CLK_POL_MASK;
+ /* Set the clock frequency */
+ clk_rate = clk_get_rate(xqspi->refclk);
+ while ((baud_rate_val < GQSPI_BAUD_DIV_MAX) &&
+ (clk_rate /
+ (GQSPI_BAUD_DIV_SHIFT << baud_rate_val)) > xqspi->speed_hz)
+ baud_rate_val++;
+
+ config_reg &= ~GQSPI_CFG_BAUD_RATE_DIV_MASK;
+ config_reg |= (baud_rate_val << GQSPI_CFG_BAUD_RATE_DIV_SHIFT);
+
zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg);
/* Clear the TX and RX FIFO */
@@ -466,22 +479,29 @@ static int zynqmp_qspi_config_op(struct zynqmp_qspi *xqspi,
struct spi_device *qspi)
{
ulong clk_rate;
- u32 config_reg, baud_rate_val = 0;
+ u32 config_reg, req_speed_hz, baud_rate_val = 0;
- /* Set the clock frequency */
- /* If req_hz == 0, default to lowest speed */
- clk_rate = clk_get_rate(xqspi->refclk);
+ req_speed_hz = qspi->max_speed_hz;
- while ((baud_rate_val < GQSPI_BAUD_DIV_MAX) &&
- (clk_rate /
- (GQSPI_BAUD_DIV_SHIFT << baud_rate_val)) > qspi->max_speed_hz)
- baud_rate_val++;
+ if (xqspi->speed_hz != req_speed_hz) {
+ xqspi->speed_hz = req_speed_hz;
- config_reg = zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST);
+ /* Set the clock frequency */
+ /* If req_speed_hz == 0, default to lowest speed */
+ clk_rate = clk_get_rate(xqspi->refclk);
- config_reg &= ~GQSPI_CFG_BAUD_RATE_DIV_MASK;
- config_reg |= (baud_rate_val << GQSPI_CFG_BAUD_RATE_DIV_SHIFT);
- zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg);
+ while ((baud_rate_val < GQSPI_BAUD_DIV_MAX) &&
+ (clk_rate /
+ (GQSPI_BAUD_DIV_SHIFT << baud_rate_val)) >
+ req_speed_hz)
+ baud_rate_val++;
+
+ config_reg = zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST);
+
+ config_reg &= ~GQSPI_CFG_BAUD_RATE_DIV_MASK;
+ config_reg |= (baud_rate_val << GQSPI_CFG_BAUD_RATE_DIV_SHIFT);
+ zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg);
+ }
return 0;
}
@@ -1173,6 +1193,8 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD |
SPI_TX_DUAL | SPI_TX_QUAD;
+ ctlr->max_speed_hz = clk_get_rate(xqspi->refclk) / 2;
+ xqspi->speed_hz = ctlr->max_speed_hz;
/* QSPI controller initializations */
zynqmp_qspi_init_hw(xqspi);
@@ -1209,7 +1231,6 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
ctlr->mem_ops = &zynqmp_qspi_mem_ops;
ctlr->setup = zynqmp_qspi_setup_op;
- ctlr->max_speed_hz = clk_get_rate(xqspi->refclk) / 2;
ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
ctlr->dev.of_node = np;
ctlr->auto_runtime_pm = true;