* @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;
enum mode_type mode;
struct completion data_completion;
struct mutex op_lock;
+ u32 speed_hz;
};
/**
*/
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);
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 */
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;
}
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);
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;