Skip to content

Commit 1d04871

Browse files
committed
soundwire: qcom: add EE-aware register layout and cpu selection
Some Qualcomm SoundWire masters expose interrupt, FIFO and status registers in EE-specific register windows on v2.0 and newer hardware. Add support for selecting the SoundWire execution environment from DT and use it to program the correct register window for the active EE. The driver now reads the EE value from the new qcom,swr-master-ee-val property, with qcom,ee as a fallback for backward compatibility. For v2.0+ hardware, the IRQ/FIFO/status register layout is adjusted by the EE window stride so the driver programs the correct bank for the selected EE. The interrupt enable path is also updated to always use the selected EE window. This change allows SoundWire interrupt routing and register accesses to work correctly on platforms where the master is not mapped to the default EE1 window. Signed-off-by: Mohammad Rafi Shaik <mohs@qti.qualcomm.com>
1 parent 3688afe commit 1d04871

1 file changed

Lines changed: 77 additions & 26 deletions

File tree

drivers/soundwire/qcom.c

Lines changed: 77 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#define SWRM_COMP_STATUS 0x014
2727
#define SWRM_LINK_MANAGER_EE 0x018
2828
#define SWRM_EE_CPU 1
29+
#define SWRM_MAX_EE 1
2930
#define SWRM_FRM_GEN_ENABLED BIT(0)
3031
#define SWRM_VERSION_1_3_0 0x01030000
3132
#define SWRM_VERSION_1_5_1 0x01050001
@@ -118,6 +119,7 @@
118119
#define SWRM_V2_0_CLK_CTRL 0x5060
119120
#define SWRM_V2_0_CLK_CTRL_CLK_START BIT(0)
120121
#define SWRM_V2_0_LINK_STATUS 0x5064
122+
#define SWRM_V2_REG_EE_STRIDE 0x1000
121123

122124
#define SWRM_DP_PORT_CTRL_EN_CHAN_SHFT 0x18
123125
#define SWRM_DP_PORT_CTRL_OFFSET2_SHFT 0x10
@@ -202,6 +204,7 @@ struct qcom_swrm_ctrl {
202204
struct mutex port_lock;
203205
struct clk *hclk;
204206
int irq;
207+
u32 ee;
205208
unsigned int version;
206209
int wake_irq;
207210
int num_din_ports;
@@ -222,6 +225,7 @@ struct qcom_swrm_ctrl {
222225
u32 slave_status;
223226
u32 wr_fifo_depth;
224227
bool clock_stop_not_supported;
228+
unsigned int reg_layout_local[SWRM_OFFSET_DP_SAMPLECTRL2_BANK + 1];
225229
};
226230

227231
struct qcom_swrm_data {
@@ -328,6 +332,36 @@ static const struct qcom_swrm_data swrm_v3_0_data = {
328332
};
329333
#define to_qcom_sdw(b) container_of(b, struct qcom_swrm_ctrl, bus)
330334

335+
static void qcom_swrm_set_ee_register_layout(struct qcom_swrm_ctrl *ctrl,
336+
const struct qcom_swrm_data *data)
337+
{
338+
int ee_offset;
339+
340+
memcpy(ctrl->reg_layout_local, data->reg_layout,
341+
sizeof(ctrl->reg_layout_local));
342+
ctrl->reg_layout = ctrl->reg_layout_local;
343+
344+
if (ctrl->version < SWRM_VERSION_2_0_0)
345+
return;
346+
347+
/*
348+
* Current register constants map EE1. For EE0, use the EE register
349+
* window stride to access status/IRQ/FIFO registers.
350+
*/
351+
ee_offset = ((int)ctrl->ee - SWRM_EE_CPU) * SWRM_V2_REG_EE_STRIDE;
352+
if (!ee_offset)
353+
return;
354+
355+
ctrl->reg_layout_local[SWRM_REG_FRAME_GEN_ENABLED] += ee_offset;
356+
ctrl->reg_layout_local[SWRM_REG_INTERRUPT_STATUS] += ee_offset;
357+
ctrl->reg_layout_local[SWRM_REG_INTERRUPT_CLEAR] += ee_offset;
358+
ctrl->reg_layout_local[SWRM_REG_INTERRUPT_CPU_EN] += ee_offset;
359+
ctrl->reg_layout_local[SWRM_REG_CMD_FIFO_WR_CMD] += ee_offset;
360+
ctrl->reg_layout_local[SWRM_REG_CMD_FIFO_RD_CMD] += ee_offset;
361+
ctrl->reg_layout_local[SWRM_REG_CMD_FIFO_STATUS] += ee_offset;
362+
ctrl->reg_layout_local[SWRM_REG_CMD_FIFO_RD_FIFO_ADDR] += ee_offset;
363+
}
364+
331365
static int qcom_swrm_ahb_reg_read(struct qcom_swrm_ctrl *ctrl, int reg,
332366
u32 *val)
333367
{
@@ -904,12 +938,13 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
904938
ctrl->reg_write(ctrl, SWRM_MCP_CFG_ADDR, val);
905939

906940
if (ctrl->version == SWRM_VERSION_1_7_0) {
907-
ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU);
941+
ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, ctrl->ee);
908942
ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL,
909-
SWRM_MCP_BUS_CLK_START << SWRM_EE_CPU);
943+
SWRM_MCP_BUS_CLK_START << ctrl->ee);
910944
} else if (ctrl->version >= SWRM_VERSION_2_0_0) {
911-
ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU);
912-
ctrl->reg_write(ctrl, SWRM_V2_0_CLK_CTRL,
945+
ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, ctrl->ee);
946+
ctrl->reg_write(ctrl, SWRM_V2_0_CLK_CTRL +
947+
((int)ctrl->ee - SWRM_EE_CPU) * SWRM_V2_REG_EE_STRIDE,
913948
SWRM_V2_0_CLK_CTRL_CLK_START);
914949
} else {
915950
ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START);
@@ -935,11 +970,9 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
935970
ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CLEAR],
936971
0xFFFFFFFF);
937972

938-
/* enable CPU IRQs */
939-
if (ctrl->mmio) {
940-
ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN],
941-
SWRM_INTERRUPT_STATUS_RMSK);
942-
}
973+
/* enable CPU IRQs for the selected EE window */
974+
ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CPU_EN],
975+
SWRM_INTERRUPT_STATUS_RMSK);
943976

944977
/* Set IRQ to PULSE */
945978
ctrl->reg_write(ctrl, SWRM_COMP_CFG_ADDR,
@@ -1545,7 +1578,22 @@ static int qcom_swrm_probe(struct platform_device *pdev)
15451578
return -ENOMEM;
15461579

15471580
data = of_device_get_match_data(dev);
1581+
ctrl->ee = SWRM_EE_CPU;
1582+
ret = of_property_read_u32(dev->of_node, "qcom,swr-master-ee-val", &ctrl->ee);
1583+
if (ret)
1584+
ret = of_property_read_u32(dev->of_node, "qcom,ee", &ctrl->ee);
1585+
if (ret)
1586+
ctrl->ee = SWRM_EE_CPU;
1587+
if (ctrl->ee > SWRM_MAX_EE) {
1588+
dev_warn(dev, "invalid SoundWire EE %u, using EE%u\n",
1589+
ctrl->ee, SWRM_EE_CPU);
1590+
ctrl->ee = SWRM_EE_CPU;
1591+
}
15481592
ctrl->max_reg = data->max_reg;
1593+
/*
1594+
* Defer EE register window selection until HW version is known.
1595+
* For v2.0+ the IRQ/FIFO window is EE-banked.
1596+
*/
15491597
ctrl->reg_layout = data->reg_layout;
15501598
ctrl->rows_index = sdw_find_row_index(data->default_rows);
15511599
ctrl->cols_index = sdw_find_col_index(data->default_cols);
@@ -1623,6 +1671,7 @@ static int qcom_swrm_probe(struct platform_device *pdev)
16231671
prop->default_row = data->default_rows;
16241672

16251673
ctrl->reg_read(ctrl, SWRM_COMP_HW_VERSION, &ctrl->version);
1674+
qcom_swrm_set_ee_register_layout(ctrl, data);
16261675

16271676
ret = devm_request_threaded_irq(dev, ctrl->irq, NULL,
16281677
qcom_swrm_irq_handler,
@@ -1724,24 +1773,26 @@ static int __maybe_unused swrm_runtime_resume(struct device *dev)
17241773
if (!swrm_wait_for_frame_gen_enabled(ctrl))
17251774
dev_err(ctrl->dev, "link failed to connect\n");
17261775

1727-
/* wait for hw enumeration to complete */
1728-
wait_for_completion_timeout(&ctrl->enumeration,
1729-
msecs_to_jiffies(TIMEOUT_MS));
1730-
qcom_swrm_get_device_status(ctrl);
1731-
sdw_handle_slave_status(&ctrl->bus, ctrl->status);
1732-
} else {
1733-
reset_control_reset(ctrl->audio_cgcr);
1734-
1735-
if (ctrl->version == SWRM_VERSION_1_7_0) {
1736-
ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU);
1737-
ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL,
1738-
SWRM_MCP_BUS_CLK_START << SWRM_EE_CPU);
1739-
} else if (ctrl->version >= SWRM_VERSION_2_0_0) {
1740-
ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU);
1741-
ctrl->reg_write(ctrl, SWRM_V2_0_CLK_CTRL,
1742-
SWRM_V2_0_CLK_CTRL_CLK_START);
1776+
/* wait for hw enumeration to complete */
1777+
wait_for_completion_timeout(&ctrl->enumeration,
1778+
msecs_to_jiffies(TIMEOUT_MS));
1779+
qcom_swrm_get_device_status(ctrl);
1780+
sdw_handle_slave_status(&ctrl->bus, ctrl->status);
17431781
} else {
1744-
ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START);
1782+
reset_control_reset(ctrl->audio_cgcr);
1783+
1784+
if (ctrl->version == SWRM_VERSION_1_7_0) {
1785+
ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, ctrl->ee);
1786+
ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL,
1787+
SWRM_MCP_BUS_CLK_START << ctrl->ee);
1788+
} else if (ctrl->version >= SWRM_VERSION_2_0_0) {
1789+
ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, ctrl->ee);
1790+
ctrl->reg_write(ctrl, SWRM_V2_0_CLK_CTRL +
1791+
((int)ctrl->ee - SWRM_EE_CPU) *
1792+
SWRM_V2_REG_EE_STRIDE,
1793+
SWRM_V2_0_CLK_CTRL_CLK_START);
1794+
} else {
1795+
ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START);
17451796
}
17461797
ctrl->reg_write(ctrl, ctrl->reg_layout[SWRM_REG_INTERRUPT_CLEAR],
17471798
SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET);

0 commit comments

Comments
 (0)