Skip to content

Commit 9586b3e

Browse files
mukesh-savaliyavdadhani
authored andcommitted
FROMLIST: dmaengine: qcom: gpi: Add lock/unlock TREs for multi-owner I2C transfers
Some platforms use a QUP-based I2C controller in a configuration where the controller is shared with another system processor (described in DT using qcom,qup-multi-owner). In such setups, GPI hardware lock/unlock TREs can be used to serialize access to the controller. Add support to emit lock and unlock TREs around I2C transfers and increase the maximum TRE count to account for the additional elements. Also simplify the client interface by replacing multiple boolean fields (shared flag and message position tracking) with a single lock_action selector (acquire/release/none), as the GPI driver only needs to know whether to emit lock/unlock TREs for a given transfer. Link: https://lore.kernel.org/all/20260331114742.2896317-3-mukesh.savaliya@oss.qualcomm.com/ Signed-off-by: Mukesh Kumar Savaliya <mukesh.savaliya@oss.qualcomm.com>
1 parent e237543 commit 9586b3e

2 files changed

Lines changed: 62 additions & 2 deletions

File tree

drivers/dma/qcom/gpi.c

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/*
33
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
44
* Copyright (c) 2020, Linaro Limited
5+
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
56
*/
67

78
#include <dt-bindings/dma/qcom-gpi.h>
@@ -67,6 +68,14 @@
6768
#define TRE_DMA_LEN GENMASK(23, 0)
6869
#define TRE_DMA_IMMEDIATE_LEN GENMASK(3, 0)
6970

71+
/* Lock TRE */
72+
#define TRE_LOCK BIT(0)
73+
#define TRE_MINOR_TYPE GENMASK(19, 16)
74+
#define TRE_MAJOR_TYPE GENMASK(23, 20)
75+
76+
/* Unlock TRE */
77+
#define TRE_UNLOCK BIT(8)
78+
7079
/* Register offsets from gpi-top */
7180
#define GPII_n_CH_k_CNTXT_0_OFFS(n, k) (0x20000 + (0x4000 * (n)) + (0x80 * (k)))
7281
#define GPII_n_CH_k_CNTXT_0_EL_SIZE GENMASK(31, 24)
@@ -518,7 +527,7 @@ struct gpii {
518527
bool ieob_set;
519528
};
520529

521-
#define MAX_TRE 3
530+
#define MAX_TRE 5
522531

523532
struct gpi_desc {
524533
struct virt_dma_desc vd;
@@ -1625,12 +1634,27 @@ static int gpi_create_i2c_tre(struct gchan *chan, struct gpi_desc *desc,
16251634
unsigned long flags)
16261635
{
16271636
struct gpi_i2c_config *i2c = chan->config;
1637+
enum gpi_lock_action lock_action = i2c->lock_action;
16281638
struct device *dev = chan->gpii->gpi_dev->dev;
16291639
unsigned int tre_idx = 0;
16301640
dma_addr_t address;
16311641
struct gpi_tre *tre;
16321642
unsigned int i;
16331643

1644+
/* Optional lock TRE before transfer */
1645+
if (lock_action == GPI_LOCK_ACQUIRE) {
1646+
tre = &desc->tre[tre_idx];
1647+
tre_idx++;
1648+
1649+
tre->dword[0] = 0;
1650+
tre->dword[1] = 0;
1651+
tre->dword[2] = 0;
1652+
tre->dword[3] = u32_encode_bits(1, TRE_LOCK);
1653+
tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_IEOB);
1654+
tre->dword[3] |= u32_encode_bits(0, TRE_MINOR_TYPE);
1655+
tre->dword[3] |= u32_encode_bits(3, TRE_MAJOR_TYPE);
1656+
}
1657+
16341658
/* first create config tre if applicable */
16351659
if (i2c->set_config) {
16361660
tre = &desc->tre[tre_idx];
@@ -1690,6 +1714,24 @@ static int gpi_create_i2c_tre(struct gchan *chan, struct gpi_desc *desc,
16901714

16911715
if (!(flags & DMA_PREP_INTERRUPT))
16921716
tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_BEI);
1717+
1718+
/* If multi-owner and this is the release boundary, chain it */
1719+
if (i2c->lock_action == GPI_LOCK_RELEASE)
1720+
tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_CHAIN);
1721+
}
1722+
1723+
/* Optional unlock TRE after transfer */
1724+
if (lock_action == GPI_LOCK_RELEASE && i2c->op != I2C_READ) {
1725+
tre = &desc->tre[tre_idx];
1726+
tre_idx++;
1727+
1728+
tre->dword[0] = 0;
1729+
tre->dword[1] = 0;
1730+
tre->dword[2] = 0;
1731+
tre->dword[3] = u32_encode_bits(1, TRE_UNLOCK);
1732+
tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_IEOB);
1733+
tre->dword[3] |= u32_encode_bits(1, TRE_MINOR_TYPE);
1734+
tre->dword[3] |= u32_encode_bits(3, TRE_MAJOR_TYPE);
16931735
}
16941736

16951737
for (i = 0; i < tre_idx; i++)

include/linux/dma/qcom-gpi-dma.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* SPDX-License-Identifier: GPL-2.0 */
22
/*
33
* Copyright (c) 2020, Linaro Limited
4+
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
45
*/
56

67
#ifndef QCOM_GPI_DMA_H
@@ -54,6 +55,21 @@ enum i2c_op {
5455
I2C_READ,
5556
};
5657

58+
/**
59+
* enum gpi_lock_action - request lock/unlock TRE sequencing
60+
* @GPI_LOCK_NONE: No lock/unlock TRE requested for this transfer
61+
* @GPI_LOCK_ACQUIRE: Emit a lock TRE before the transfer
62+
* @GPI_LOCK_RELEASE: Emit an unlock TRE after the transfer
63+
*
64+
* Used by protocol drivers for multi-owner controller setups (e.g. when
65+
* DeviceTree indicates the controller is shared via qcom,qup-multi-owner).
66+
*/
67+
enum gpi_lock_action {
68+
GPI_LOCK_NONE = 0,
69+
GPI_LOCK_ACQUIRE,
70+
GPI_LOCK_RELEASE,
71+
};
72+
5773
/**
5874
* struct gpi_i2c_config - i2c config for peripheral
5975
*
@@ -67,7 +83,8 @@ enum i2c_op {
6783
* @set_config: set peripheral config
6884
* @rx_len: receive length for buffer
6985
* @op: i2c cmd
70-
* @multi_msg: is part of multi i2c r-w msgs
86+
* @muli-msg: is part of multi i2c r-w msgs
87+
* @lock_action: request lock/unlock TRE sequencing for this transfer
7188
*/
7289
struct gpi_i2c_config {
7390
u8 set_config;
@@ -81,6 +98,7 @@ struct gpi_i2c_config {
8198
u32 rx_len;
8299
enum i2c_op op;
83100
bool multi_msg;
101+
enum gpi_lock_action lock_action;
84102
};
85103

86104
#endif /* QCOM_GPI_DMA_H */

0 commit comments

Comments
 (0)