summaryrefslogtreecommitdiff
path: root/drivers/spi/spi-geni-qcom.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-06-28 13:32:47 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2023-06-28 13:32:47 -0700
commit362067b6d5ca5b59a849a8e1183fb51d616fcf19 (patch)
tree971ebe9fea87d4771b729eb6833f1f3fd65d7a6e /drivers/spi/spi-geni-qcom.c
parent4171a9aa235988fc5cb19d84d493496cb73e6988 (diff)
parent54e47eade73046e860634736d2651ddc118ca694 (diff)
downloadlwn-362067b6d5ca5b59a849a8e1183fb51d616fcf19.tar.gz
lwn-362067b6d5ca5b59a849a8e1183fb51d616fcf19.zip
Merge tag 'regulator-v6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator
Pull regulator updates from Mark Brown: "This release is almost all drivers, there's some small improvements in the core but otherwise everything is updates to drivers, mostly the addition of new ones. There's also a bunch of changes pulled in from the MFD subsystem as dependencies, Rockchip and TI core MFD code that the regulator drivers depend on. I've also yet again managed to put a SPI commit in the regulator tree, I don't know what it is about those two trees (this for spi-geni-qcom). Summary: - Support for Renesas RAA215300, Rockchip RK808, Texas Instruments TPS6594 and TPS6287x, and X-Powers AXP15060 and AXP313a" * tag 'regulator-v6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (43 commits) regulator: Add Renesas PMIC RAA215300 driver regulator: dt-bindings: Add Renesas RAA215300 PMIC bindings regulator: ltc3676: Use maple tree register cache regulator: ltc3589: Use maple tree register cache regulator: helper: Document ramp_delay parameter of regulator_set_ramp_delay_regmap() regulator: mt6358: Use linear voltage helpers for single range regulators regulator: mt6358: Const-ify mt6358_regulator_info data structures regulator: mt6358: Drop *_SSHUB regulators regulator: mt6358: Merge VCN33_* regulators regulator: dt-bindings: mt6358: Drop *_sshub regulators regulator: dt-bindings: mt6358: Merge ldo_vcn33_* regulators regulator: dt-bindings: pwm-regulator: Add missing type for "pwm-dutycycle-unit" regulator: Switch two more i2c drivers back to use .probe() spi: spi-geni-qcom: Do not do DMA map/unmap inside driver, use framework instead soc: qcom: geni-se: Add interfaces geni_se_tx_init_dma() and geni_se_rx_init_dma() regulator: tps6594-regulator: Add driver for TI TPS6594 regulators regulator: axp20x: Add AXP15060 support regulator: axp20x: Add support for AXP313a variant dt-bindings: pfuze100.yaml: Add an entry for interrupts regulator: stm32-pwr: Fix regulator disabling ...
Diffstat (limited to 'drivers/spi/spi-geni-qcom.c')
-rw-r--r--drivers/spi/spi-geni-qcom.c103
1 files changed, 50 insertions, 53 deletions
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index b293428760bc..135cdf394b76 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -97,8 +97,6 @@ struct spi_geni_master {
struct dma_chan *tx;
struct dma_chan *rx;
int cur_xfer_mode;
- dma_addr_t tx_se_dma;
- dma_addr_t rx_se_dma;
};
static int get_spi_clk_cfg(unsigned int speed_hz,
@@ -174,7 +172,7 @@ static void handle_se_timeout(struct spi_master *spi,
unmap_if_dma:
if (mas->cur_xfer_mode == GENI_SE_DMA) {
if (xfer) {
- if (xfer->tx_buf && mas->tx_se_dma) {
+ if (xfer->tx_buf) {
spin_lock_irq(&mas->lock);
reinit_completion(&mas->tx_reset_done);
writel(1, se->base + SE_DMA_TX_FSM_RST);
@@ -182,9 +180,8 @@ unmap_if_dma:
time_left = wait_for_completion_timeout(&mas->tx_reset_done, HZ);
if (!time_left)
dev_err(mas->dev, "DMA TX RESET failed\n");
- geni_se_tx_dma_unprep(se, mas->tx_se_dma, xfer->len);
}
- if (xfer->rx_buf && mas->rx_se_dma) {
+ if (xfer->rx_buf) {
spin_lock_irq(&mas->lock);
reinit_completion(&mas->rx_reset_done);
writel(1, se->base + SE_DMA_RX_FSM_RST);
@@ -192,7 +189,6 @@ unmap_if_dma:
time_left = wait_for_completion_timeout(&mas->rx_reset_done, HZ);
if (!time_left)
dev_err(mas->dev, "DMA RX RESET failed\n");
- geni_se_rx_dma_unprep(se, mas->rx_se_dma, xfer->len);
}
} else {
/*
@@ -523,17 +519,36 @@ static int setup_gsi_xfer(struct spi_transfer *xfer, struct spi_geni_master *mas
return 1;
}
+static u32 get_xfer_len_in_words(struct spi_transfer *xfer,
+ struct spi_geni_master *mas)
+{
+ u32 len;
+
+ if (!(mas->cur_bits_per_word % MIN_WORD_LEN))
+ len = xfer->len * BITS_PER_BYTE / mas->cur_bits_per_word;
+ else
+ len = xfer->len / (mas->cur_bits_per_word / BITS_PER_BYTE + 1);
+ len &= TRANS_LEN_MSK;
+
+ return len;
+}
+
static bool geni_can_dma(struct spi_controller *ctlr,
struct spi_device *slv, struct spi_transfer *xfer)
{
struct spi_geni_master *mas = spi_master_get_devdata(slv->master);
+ u32 len, fifo_size;
- /*
- * Return true if transfer needs to be mapped prior to
- * calling transfer_one which is the case only for GPI_DMA.
- * For SE_DMA mode, map/unmap is done in geni_se_*x_dma_prep.
- */
- return mas->cur_xfer_mode == GENI_GPI_DMA;
+ if (mas->cur_xfer_mode == GENI_GPI_DMA)
+ return true;
+
+ len = get_xfer_len_in_words(xfer, mas);
+ fifo_size = mas->tx_fifo_depth * mas->fifo_width_bits / mas->cur_bits_per_word;
+
+ if (len > fifo_size)
+ return true;
+ else
+ return false;
}
static int spi_geni_prepare_message(struct spi_master *spi,
@@ -774,7 +789,7 @@ static int setup_se_xfer(struct spi_transfer *xfer,
u16 mode, struct spi_master *spi)
{
u32 m_cmd = 0;
- u32 len, fifo_size;
+ u32 len;
struct geni_se *se = &mas->se;
int ret;
@@ -806,11 +821,7 @@ static int setup_se_xfer(struct spi_transfer *xfer,
mas->tx_rem_bytes = 0;
mas->rx_rem_bytes = 0;
- if (!(mas->cur_bits_per_word % MIN_WORD_LEN))
- len = xfer->len * BITS_PER_BYTE / mas->cur_bits_per_word;
- else
- len = xfer->len / (mas->cur_bits_per_word / BITS_PER_BYTE + 1);
- len &= TRANS_LEN_MSK;
+ len = get_xfer_len_in_words(xfer, mas);
mas->cur_xfer = xfer;
if (xfer->tx_buf) {
@@ -825,9 +836,20 @@ static int setup_se_xfer(struct spi_transfer *xfer,
mas->rx_rem_bytes = xfer->len;
}
- /* Select transfer mode based on transfer length */
- fifo_size = mas->tx_fifo_depth * mas->fifo_width_bits / mas->cur_bits_per_word;
- mas->cur_xfer_mode = (len <= fifo_size) ? GENI_SE_FIFO : GENI_SE_DMA;
+ /*
+ * Select DMA mode if sgt are present; and with only 1 entry
+ * This is not a serious limitation because the xfer buffers are
+ * expected to fit into in 1 entry almost always, and if any
+ * doesn't for any reason we fall back to FIFO mode anyway
+ */
+ if (!xfer->tx_sg.nents && !xfer->rx_sg.nents)
+ mas->cur_xfer_mode = GENI_SE_FIFO;
+ else if (xfer->tx_sg.nents > 1 || xfer->rx_sg.nents > 1) {
+ dev_warn_once(mas->dev, "Doing FIFO, cannot handle tx_nents-%d, rx_nents-%d\n",
+ xfer->tx_sg.nents, xfer->rx_sg.nents);
+ mas->cur_xfer_mode = GENI_SE_FIFO;
+ } else
+ mas->cur_xfer_mode = GENI_SE_DMA;
geni_se_select_mode(se, mas->cur_xfer_mode);
/*
@@ -838,35 +860,17 @@ static int setup_se_xfer(struct spi_transfer *xfer,
geni_se_setup_m_cmd(se, m_cmd, FRAGMENTATION);
if (mas->cur_xfer_mode == GENI_SE_DMA) {
- if (m_cmd & SPI_RX_ONLY) {
- ret = geni_se_rx_dma_prep(se, xfer->rx_buf,
- xfer->len, &mas->rx_se_dma);
- if (ret) {
- dev_err(mas->dev, "Failed to setup Rx dma %d\n", ret);
- mas->rx_se_dma = 0;
- goto unlock_and_return;
- }
- }
- if (m_cmd & SPI_TX_ONLY) {
- ret = geni_se_tx_dma_prep(se, (void *)xfer->tx_buf,
- xfer->len, &mas->tx_se_dma);
- if (ret) {
- dev_err(mas->dev, "Failed to setup Tx dma %d\n", ret);
- mas->tx_se_dma = 0;
- if (m_cmd & SPI_RX_ONLY) {
- /* Unmap rx buffer if duplex transfer */
- geni_se_rx_dma_unprep(se, mas->rx_se_dma, xfer->len);
- mas->rx_se_dma = 0;
- }
- goto unlock_and_return;
- }
- }
+ if (m_cmd & SPI_RX_ONLY)
+ geni_se_rx_init_dma(se, sg_dma_address(xfer->rx_sg.sgl),
+ sg_dma_len(xfer->rx_sg.sgl));
+ if (m_cmd & SPI_TX_ONLY)
+ geni_se_tx_init_dma(se, sg_dma_address(xfer->tx_sg.sgl),
+ sg_dma_len(xfer->tx_sg.sgl));
} else if (m_cmd & SPI_TX_ONLY) {
if (geni_spi_handle_tx(mas))
writel(mas->tx_wm, se->base + SE_GENI_TX_WATERMARK_REG);
}
-unlock_and_return:
spin_unlock_irq(&mas->lock);
return ret;
}
@@ -967,14 +971,6 @@ static irqreturn_t geni_spi_isr(int irq, void *data)
if (dma_rx_status & RX_RESET_DONE)
complete(&mas->rx_reset_done);
if (!mas->tx_rem_bytes && !mas->rx_rem_bytes && xfer) {
- if (xfer->tx_buf && mas->tx_se_dma) {
- geni_se_tx_dma_unprep(se, mas->tx_se_dma, xfer->len);
- mas->tx_se_dma = 0;
- }
- if (xfer->rx_buf && mas->rx_se_dma) {
- geni_se_rx_dma_unprep(se, mas->rx_se_dma, xfer->len);
- mas->rx_se_dma = 0;
- }
spi_finalize_current_transfer(spi);
mas->cur_xfer = NULL;
}
@@ -1059,6 +1055,7 @@ static int spi_geni_probe(struct platform_device *pdev)
spi->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
spi->num_chipselect = 4;
spi->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;
spi->can_dma = geni_can_dma;