diff -ruN a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -2,6 +2,7 @@ // Copyright (c) 2017-2018, The Linux foundation. All rights reserved. #include +#include #include #include #include @@ -75,9 +76,68 @@ #define GSI_CPHA BIT(4) #define GSI_CPOL BIT(5) +/* QSPI 1-4-4 support (added on top of the standard SPI controller). */ +#define QSPI_SE_PROTO 9 + +#define GENI_IO_MUX_1_EN BIT(1) +#define GENI_IO_MUX_2_EN BIT(2) +#define GENI_IO_MUX_3_EN BIT(3) +#define GENI_QSPI_IO_MUX_EN (GENI_IO_MUX_0_EN | GENI_IO_MUX_1_EN | \ + GENI_IO_MUX_2_EN | GENI_IO_MUX_3_EN) + +#define SE_GSI_EVENT_EN 0xe18 +#define SE_IRQ_EN 0xe1c +#define SE_DMA_TX_IRQ_CLR 0xc44 +#define SE_DMA_TX_IRQ_EN_SET 0xc4c +#define SE_DMA_TX_IRQ_EN_CLR 0xc50 +#define SE_DMA_RX_IRQ_CLR 0xd44 +#define SE_DMA_RX_IRQ_EN_SET 0xd4c +#define SE_DMA_RX_IRQ_EN_CLR 0xd50 + +#define DMA_RX_EVENT_EN BIT(0) +#define DMA_TX_EVENT_EN BIT(1) +#define GENI_M_EVENT_EN BIT(2) +#define GENI_S_EVENT_EN BIT(3) + +#define QSPI_M_IRQ_EN_GPI 0x33c00046 +#define QSPI_S_IRQ_EN_GPI 0x03001e06 +#define QSPI_DMA_TX_IRQ_EN 0x0d +#define QSPI_DMA_RX_IRQ_EN 0x1d + +#define QSPI_SINGLE_SDR 0x000 +#define QSPI_QUAD_SDR BIT(9) + +/* Defaults for a quad read with 1-byte opcode + 3-byte address. */ +#define QSPI_DEFAULT_READ_OPCODE 0xEB +#define QSPI_DEFAULT_DUMMY_CLK_CNT 8 +#define QSPI_DEFAULT_TX_CMD_LEN 4 +#define QSPI_DEFAULT_MAX_SPEED_HZ 20000000 + +/** + * struct spi_geni_data - per-compatible behavioral flags + * @qspi_mode: controller runs in QSPI 1-4-4 mode with 4 data lanes + */ +struct spi_geni_data { + bool qspi_mode; +}; + +/** + * struct spi_geni_qspi_params - per-SE QSPI tunables read from DT + * @read_opcode: first TX byte that identifies a read transfer (e.g. 0xEB) + * @dummy_clk_cnt: dummy clocks inserted between address and read data + * @tx_cmd_len: number of TX bytes forming the read command (opcode+address) + */ +struct spi_geni_qspi_params { + u32 read_opcode; + u32 dummy_clk_cnt; + u32 tx_cmd_len; +}; + struct spi_geni_master { struct geni_se se; struct device *dev; + const struct spi_geni_data *data; + struct spi_geni_qspi_params qspi; u32 tx_fifo_depth; u32 fifo_width_bits; u32 tx_wm; @@ -104,6 +164,52 @@ int cur_xfer_mode; }; +static inline bool spi_geni_is_qspi(const struct spi_geni_master *mas) +{ + return mas->data && mas->data->qspi_mode; +} + +/* Enable all 4 data lanes on the GENI output mux for QSPI. */ +static void qspi_setup_io_mux(struct spi_geni_master *mas) +{ + struct geni_se *se = &mas->se; + u32 out; + + out = readl(se->base + GENI_OUTPUT_CTRL); + out |= GENI_QSPI_IO_MUX_EN; + writel(out, se->base + GENI_OUTPUT_CTRL); +} + +/* + * Reprogram the SE IRQ / DMA / event registers for GPI DMA. + * + * geni_se_resources_on() (called from runtime_resume) writes a fixed set of + * values into SE_IRQ_EN that are correct for FIFO/SE_DMA mode but clobber the + * GPI configuration. The QSPI SE_PROTO (9) also needs different masks than + * the defaults. Call this from prepare_message (post resume, pre transfer) + * to restore the GPI-friendly values. + */ +static void prep_se_for_gpi_dma(struct spi_geni_master *mas) +{ + void __iomem *base = mas->se.base; + + writel(GENI_DMA_MODE_EN, base + SE_GENI_DMA_MODE_EN); + writel(0, base + SE_IRQ_EN); + writel(DMA_RX_EVENT_EN | DMA_TX_EVENT_EN | + GENI_M_EVENT_EN | GENI_S_EVENT_EN, + base + SE_GSI_EVENT_EN); + writel(QSPI_M_IRQ_EN_GPI, base + SE_GENI_M_IRQ_EN); + writel(QSPI_S_IRQ_EN_GPI, base + SE_GENI_S_IRQ_EN); + writel(0xf, base + SE_DMA_TX_IRQ_EN_CLR); + writel(QSPI_DMA_TX_IRQ_EN, base + SE_DMA_TX_IRQ_EN_SET); + writel(0xfff, base + SE_DMA_RX_IRQ_EN_CLR); + writel(QSPI_DMA_RX_IRQ_EN, base + SE_DMA_RX_IRQ_EN_SET); + writel(0xffc07fff, base + SE_GENI_M_IRQ_CLEAR); + writel(0x0fc07f3f, base + SE_GENI_S_IRQ_CLEAR); + writel(0xf, base + SE_DMA_TX_IRQ_CLR); + writel(0xfff, base + SE_DMA_RX_IRQ_CLR); +} + static void spi_slv_setup(struct spi_geni_master *mas) { struct geni_se *se = &mas->se; @@ -411,7 +517,20 @@ } if (xfer->tx_buf && xfer->rx_buf) { - peripheral.cmd = SPI_DUPLEX; + /* + * QSPI uses SPI_TX_RX (7) for TX-opcode-then-RX-data transfers; + * standard SPI uses SPI_DUPLEX (3) for true full-duplex. + * + * For QSPI_TX_RX the GSI firmware needs an explicit rx_len so + * it knows how many bytes to clock in after the TX command + * phase. SPI_DUPLEX uses xfer->len implicitly. + */ + if (spi_geni_is_qspi(mas)) { + peripheral.cmd = SPI_TX_RX; + peripheral.rx_len = (xfer->len << 3) / xfer->bits_per_word; + } else { + peripheral.cmd = SPI_DUPLEX; + } } else if (xfer->tx_buf) { peripheral.cmd = SPI_TX; peripheral.rx_len = 0; @@ -445,6 +564,44 @@ peripheral.fragmentation = FRAGMENTATION; } + if (spi_geni_is_qspi(mas)) { + bool multi = !list_is_singular(&spi->cur_msg->transfers); + + peripheral.qspi_mode = true; + + /* + * In a multi-transfer message the first write uses SINGLE_SDR + * (opcode+addr lane transition) while subsequent TX-only + * transfers stay in QUAD. + */ + if (multi && xfer->tx_buf && !xfer->rx_buf && + &xfer->transfer_list == spi->cur_msg->transfers.next) + peripheral.qspi_lane_flags = QSPI_SINGLE_SDR; + else + peripheral.qspi_lane_flags = QSPI_QUAD_SDR; + + if (peripheral.cmd == SPI_TX_RX && xfer->tx_buf) { + const u8 *tx = xfer->tx_buf; + + /* + * The configured read opcode is followed by an address + * then dummy clocks before the device drives the data + * lanes. Any other first byte means the host is issuing + * a write command, so downgrade to TX-only. + */ + if (tx[0] == mas->qspi.read_opcode) { + peripheral.dummy_clk_cnt = mas->qspi.dummy_clk_cnt; + peripheral.tx_cmd_len = mas->qspi.tx_cmd_len; + } else { + peripheral.cmd = SPI_TX; + peripheral.dummy_clk_cnt = 0; + peripheral.rx_len = 0; + } + } else if (peripheral.cmd == SPI_RX) { + peripheral.dummy_clk_cnt = mas->qspi.dummy_clk_cnt; + } + } + if (peripheral.cmd & SPI_RX) { dmaengine_slave_config(mas->rx, &config); rx_desc = dmaengine_prep_slave_sg(mas->rx, xfer->rx_sg.sgl, xfer->rx_sg.nents, @@ -467,8 +624,18 @@ return -EIO; } - tx_desc->callback_result = spi_gsi_callback_result; - tx_desc->callback_param = spi; + /* + * In QSPI mode the Go TRE on the TX channel has no DMA TRE for SPI_RX + * (and for TX_RX completes TX-side early), so the real completion + * event is the IEOT on the RX channel. Attach the callback there. + */ + if (spi_geni_is_qspi(mas) && (peripheral.cmd & SPI_RX)) { + rx_desc->callback_result = spi_gsi_callback_result; + rx_desc->callback_param = spi; + } else { + tx_desc->callback_result = spi_gsi_callback_result; + tx_desc->callback_param = spi; + } if (peripheral.cmd & SPI_RX) dmaengine_submit(rx_desc); @@ -534,7 +701,13 @@ return ret; case GENI_GPI_DMA: - /* nothing to do for GPI DMA */ + /* + * In QSPI mode, runtime_resume's call to geni_se_resources_on() + * clobbers the GPI-specific IRQ/DMA register layout. Restore + * it before every message. + */ + if (spi_geni_is_qspi(mas)) + prep_se_for_gpi_dma(mas); return 0; } @@ -609,6 +782,18 @@ goto out_pm; } spi_slv_setup(mas); + } else if (spi_geni_is_qspi(mas)) { + /* + * QSPI SEs report protocol 9 in hardware. The GENI_SE_SPI + * firmware loader cannot be used here (no firmware for proto 9 + * is shipped), so reject anything else. + */ + if (proto != QSPI_SE_PROTO) { + dev_err(mas->dev, "Expected QSPI proto %d, got %d\n", + QSPI_SE_PROTO, proto); + goto out_pm; + } + qspi_setup_io_mux(mas); } else if (proto == GENI_SE_INVALID_PROTO) { ret = geni_load_se_firmware(se, GENI_SE_SPI); if (ret) { @@ -640,9 +825,28 @@ else mas->oversampling = 1; + /* + * QSPI SEs cannot use FIFO mode (the FIFO path would try to drive + * a single-lane word format on a 4-lane QSPI bus), so force GPI DMA + * regardless of what GENI_IF_DISABLE_RO reports. + */ fifo_disable = readl(se->base + GENI_IF_DISABLE_RO) & FIFO_IF_DISABLE; + if (spi_geni_is_qspi(mas)) + fifo_disable = 1; + switch (fifo_disable) { case 1: + /* + * For QSPI, bring the SE up in SE_DMA first (which arms the + * DMA-related registers) and let it settle before switching + * to GPI_DMA and grabbing the GPII channels. Without this + * intermediate step the first GPI command after probe can + * hang on the CH STOP completion. + */ + if (spi_geni_is_qspi(mas)) { + geni_se_select_mode(se, GENI_SE_DMA); + msleep(10); + } ret = spi_geni_grab_gpi_chan(mas); if (!ret) { /* success case */ mas->cur_xfer_mode = GENI_GPI_DMA; @@ -653,6 +857,16 @@ goto out_pm; } /* + * For QSPI there is no usable FIFO fallback: FIFO mode cannot + * drive a 4-lane QSPI bus. Fail the probe instead of silently + * producing garbage. + */ + if (spi_geni_is_qspi(mas)) { + dev_err(mas->dev, "Failed to grab GPI DMA channels for QSPI: %d\n", + ret); + goto out_pm; + } + /* * in case of failure to get gpi dma channel, we can still do the * FIFO mode, so fallthrough */ @@ -1052,11 +1266,24 @@ mas = spi_controller_get_devdata(spi); mas->irq = irq; mas->dev = dev; + mas->data = device_get_match_data(dev); mas->se.dev = dev; mas->se.wrapper = dev_get_drvdata(dev->parent); mas->se.base = base; mas->se.clk = clk; + if (spi_geni_is_qspi(mas)) { + mas->qspi.read_opcode = QSPI_DEFAULT_READ_OPCODE; + mas->qspi.dummy_clk_cnt = QSPI_DEFAULT_DUMMY_CLK_CNT; + mas->qspi.tx_cmd_len = QSPI_DEFAULT_TX_CMD_LEN; + device_property_read_u32(dev, "qcom,qspi-read-opcode", + &mas->qspi.read_opcode); + device_property_read_u32(dev, "qcom,qspi-read-dummy-clocks", + &mas->qspi.dummy_clk_cnt); + device_property_read_u32(dev, "qcom,qspi-read-cmd-bytes", + &mas->qspi.tx_cmd_len); + } + ret = devm_pm_opp_set_clkname(&pdev->dev, "se"); if (ret) return ret; @@ -1069,9 +1296,12 @@ spi->bus_num = -1; spi->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP | SPI_CS_HIGH; + if (spi_geni_is_qspi(mas)) + spi->mode_bits |= SPI_TX_QUAD | SPI_RX_QUAD; spi->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); spi->num_chipselect = 4; - spi->max_speed_hz = 50000000; + spi->max_speed_hz = spi_geni_is_qspi(mas) ? QSPI_DEFAULT_MAX_SPEED_HZ + : 50000000; spi->max_dma_len = 0xffff0; /* 24 bits for tx/rx dma length */ spi->prepare_message = spi_geni_prepare_message; spi->transfer_one = spi_geni_transfer_one; @@ -1197,8 +1427,13 @@ SET_SYSTEM_SLEEP_PM_OPS(spi_geni_suspend, spi_geni_resume) }; +static const struct spi_geni_data spi_geni_qspi_data = { + .qspi_mode = true, +}; + static const struct of_device_id spi_geni_dt_match[] = { { .compatible = "qcom,geni-spi" }, + { .compatible = "qcom,geni-spi-qspi", .data = &spi_geni_qspi_data }, {} }; MODULE_DEVICE_TABLE(of, spi_geni_dt_match);