[05/19] soundwire: amd: add soundwire interrupt handling
Commit Message
Add support for handling soundwire controller interrupts.
Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
Signed-off-by: Mastan Katragadda <Mastan.Katragadda@amd.com>
---
drivers/soundwire/amd_master.c | 156 ++++++++++++++++++++++++++++++
drivers/soundwire/amd_master.h | 1 +
include/linux/soundwire/sdw_amd.h | 3 +
3 files changed, 160 insertions(+)
Comments
>
> +static void amd_sdwc_process_ping_status(u64 response, struct amd_sdwc_ctrl *ctrl)
> +{
> + u64 slave_stat = 0;
> + u32 val = 0;
> + u16 dev_index;
> +
> + /* slave status from ping response*/
response */
> + slave_stat = FIELD_GET(AMD_SDW_MCP_SLAVE_STAT_0_3, response);
> + slave_stat |= FIELD_GET(AMD_SDW_MCP_SLAVE_STAT_4_11, response) << 8;
> +
> + dev_dbg(ctrl->dev, "%s: slave_stat:0x%llx\n", __func__, slave_stat);
> + for (dev_index = 0; dev_index <= SDW_MAX_DEVICES; ++dev_index) {
> + val = (slave_stat >> (dev_index * 2)) & AMD_SDW_MCP_SLAVE_STATUS_MASK;
> + dev_dbg(ctrl->dev, "%s val:0x%x\n", __func__, val);
> + switch (val) {
> + case SDW_SLAVE_ATTACHED:
> + ctrl->status[dev_index] = SDW_SLAVE_ATTACHED;
> + break;
> + case SDW_SLAVE_UNATTACHED:
> + ctrl->status[dev_index] = SDW_SLAVE_UNATTACHED;
> + break;
> + case SDW_SLAVE_ALERT:
> + ctrl->status[dev_index] = SDW_SLAVE_ALERT;
> + break;
> + default:
> + ctrl->status[dev_index] = SDW_SLAVE_RESERVED;
> + break;
> + }
> + }
> +}
> +
> +static void amd_sdwc_read_and_process_ping_status(struct amd_sdwc_ctrl *ctrl)
> +{
> + u64 response = 0;
> +
> + mutex_lock(&ctrl->bus.msg_lock);
> + response = amd_sdwc_send_cmd_get_resp(ctrl, 0, 0);
> + mutex_unlock(&ctrl->bus.msg_lock);
> + amd_sdwc_process_ping_status(response, ctrl);
Is this saying that you actually need to send a PING frame manually
every time the manager needs to check the device status, including
interrupts?
> +}
> +
> static u32 amd_sdwc_read_ping_status(struct sdw_bus *bus)
> {
> struct amd_sdwc_ctrl *ctrl = to_amd_sdw(bus);
> @@ -1132,6 +1173,119 @@ static int amd_sdwc_register_dais(struct amd_sdwc_ctrl *ctrl)
> dais, num_dais);
> }
>
> +static void amd_sdwc_update_slave_status_work(struct work_struct *work)
> +{
> + struct amd_sdwc_ctrl *ctrl =
> + container_of(work, struct amd_sdwc_ctrl, amd_sdw_work);
> + u32 sw_status_change_mask_0to7_reg;
> + u32 sw_status_change_mask_8to11_reg;
> +
> + switch (ctrl->instance) {
> + case ACP_SDW0:
> + sw_status_change_mask_0to7_reg = SW_STATE_CHANGE_STATUS_MASK_0TO7;
> + sw_status_change_mask_8to11_reg = SW_STATE_CHANGE_STATUS_MASK_8TO11;
> + break;
> + case ACP_SDW1:
> + sw_status_change_mask_0to7_reg = P1_SW_STATE_CHANGE_STATUS_MASK_0TO7;
> + sw_status_change_mask_8to11_reg = P1_SW_STATE_CHANGE_STATUS_MASK_8TO11;
> + break;
> + default:
> + dev_err(ctrl->dev, "Invalid Soundwire controller instance\n");
> + return;
> + }
> +
> + if (ctrl->status[0] == SDW_SLAVE_ATTACHED) {
> + acp_reg_writel(0, ctrl->mmio + sw_status_change_mask_0to7_reg);
> + acp_reg_writel(0, ctrl->mmio + sw_status_change_mask_8to11_reg);
> + }
> +
> +update_status:
> + sdw_handle_slave_status(&ctrl->bus, ctrl->status);
> + if (ctrl->status[0] == SDW_SLAVE_ATTACHED) {
> + acp_reg_writel(AMD_SDW_IRQ_MASK_0TO7, ctrl->mmio + sw_status_change_mask_0to7_reg);
> + acp_reg_writel(AMD_SDW_IRQ_MASK_8TO11,
> + ctrl->mmio + sw_status_change_mask_8to11_reg);
> + amd_sdwc_read_and_process_ping_status(ctrl);
> + goto update_status;
> + }
well no, you have to use some sort of retry count. You cannot handle
interrupts in a loop like this, a faulty or chatty device would keep
signaling an issue and you would be stuck here for a while.
In addition, it's not clear if this is really needed. We added this loop
in cadence_master.c because of issues with multiple devices becoming
attached at the same time and how the hardware works. As it turns out,
this update_status loop seems to be a paranoid case, the actually cause
for devices de-attaching was found by Cirrus Logic and fixed in
"soundwire: cadence: fix updating slave status when a bus has multiple
peripherals"
You would need to explain how the status is detected and if any race
conditions can occur.
Hi Vijendar,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on broonie-sound/for-next]
[also build test WARNING on next-20230119]
[cannot apply to vkoul-dmaengine/next linus/master v6.2-rc4]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Vijendar-Mukunda/ASoC-amd-ps-create-platform-devices-based-on-acp-config/20230111-170749
base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
patch link: https://lore.kernel.org/r/20230111090222.2016499-6-Vijendar.Mukunda%40amd.com
patch subject: [PATCH 05/19] soundwire: amd: add soundwire interrupt handling
config: i386-allyesconfig (https://download.01.org/0day-ci/archive/20230120/202301200537.eS27M0By-lkp@intel.com/config)
compiler: clang version 14.0.6 (https://github.com/llvm/llvm-project f28c006a5895fc0e329fe15fead81e37457cb1d1)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/ee04e2b3a1ee45081b430ae161c53aa8964d5c36
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Vijendar-Mukunda/ASoC-amd-ps-create-platform-devices-based-on-acp-config/20230111-170749
git checkout ee04e2b3a1ee45081b430ae161c53aa8964d5c36
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=i386 olddefconfig
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=i386 SHELL=/bin/bash drivers/soundwire/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
^~~~~~~~~
drivers/soundwire/amd_master.c:610:26: warning: shift count is negative [-Wshift-count-negative]
slave_stat |= FIELD_GET(AMD_SDW_MCP_SLAVE_STAT_4_11, response) << 8;
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/soundwire/amd_master.h:184:38: note: expanded from macro 'AMD_SDW_MCP_SLAVE_STAT_4_11'
#define AMD_SDW_MCP_SLAVE_STAT_4_11 GENMASK(39, 24)
^
include/linux/bits.h:38:31: note: expanded from macro 'GENMASK'
(GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))
^
include/linux/bits.h:36:11: note: expanded from macro '__GENMASK'
(~UL(0) >> (BITS_PER_LONG - 1 - (h))))
^
note: (skipping 6 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
include/linux/compiler_types.h:358:22: note: expanded from macro 'compiletime_assert'
_compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/compiler_types.h:346:23: note: expanded from macro '_compiletime_assert'
__compiletime_assert(condition, msg, prefix, suffix)
~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/compiler_types.h:338:9: note: expanded from macro '__compiletime_assert'
if (!(condition)) \
^~~~~~~~~
drivers/soundwire/amd_master.c:610:26: warning: shift count is negative [-Wshift-count-negative]
slave_stat |= FIELD_GET(AMD_SDW_MCP_SLAVE_STAT_4_11, response) << 8;
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/soundwire/amd_master.h:184:38: note: expanded from macro 'AMD_SDW_MCP_SLAVE_STAT_4_11'
#define AMD_SDW_MCP_SLAVE_STAT_4_11 GENMASK(39, 24)
^
include/linux/bits.h:38:31: note: expanded from macro 'GENMASK'
(GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))
^
include/linux/bits.h:36:11: note: expanded from macro '__GENMASK'
(~UL(0) >> (BITS_PER_LONG - 1 - (h))))
^
note: (skipping 5 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
include/linux/compiler_types.h:358:22: note: expanded from macro 'compiletime_assert'
_compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/compiler_types.h:346:23: note: expanded from macro '_compiletime_assert'
__compiletime_assert(condition, msg, prefix, suffix)
~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/compiler_types.h:338:9: note: expanded from macro '__compiletime_assert'
if (!(condition)) \
^~~~~~~~~
drivers/soundwire/amd_master.c:610:26: warning: shift count is negative [-Wshift-count-negative]
slave_stat |= FIELD_GET(AMD_SDW_MCP_SLAVE_STAT_4_11, response) << 8;
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/soundwire/amd_master.h:184:38: note: expanded from macro 'AMD_SDW_MCP_SLAVE_STAT_4_11'
#define AMD_SDW_MCP_SLAVE_STAT_4_11 GENMASK(39, 24)
^
include/linux/bits.h:38:31: note: expanded from macro 'GENMASK'
(GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))
^
include/linux/bits.h:36:11: note: expanded from macro '__GENMASK'
(~UL(0) >> (BITS_PER_LONG - 1 - (h))))
^
note: (skipping 6 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
include/linux/compiler_types.h:358:22: note: expanded from macro 'compiletime_assert'
_compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/compiler_types.h:346:23: note: expanded from macro '_compiletime_assert'
__compiletime_assert(condition, msg, prefix, suffix)
~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/compiler_types.h:338:9: note: expanded from macro '__compiletime_assert'
if (!(condition)) \
^~~~~~~~~
drivers/soundwire/amd_master.c:610:26: warning: shift count is negative [-Wshift-count-negative]
slave_stat |= FIELD_GET(AMD_SDW_MCP_SLAVE_STAT_4_11, response) << 8;
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/soundwire/amd_master.h:184:38: note: expanded from macro 'AMD_SDW_MCP_SLAVE_STAT_4_11'
#define AMD_SDW_MCP_SLAVE_STAT_4_11 GENMASK(39, 24)
^
include/linux/bits.h:38:31: note: expanded from macro 'GENMASK'
(GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))
^
include/linux/bits.h:36:11: note: expanded from macro '__GENMASK'
(~UL(0) >> (BITS_PER_LONG - 1 - (h))))
^
include/linux/bitfield.h:129:30: note: expanded from macro 'FIELD_GET'
(typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
^~~~~
drivers/soundwire/amd_master.c:610:26: warning: shift count is negative [-Wshift-count-negative]
slave_stat |= FIELD_GET(AMD_SDW_MCP_SLAVE_STAT_4_11, response) << 8;
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/soundwire/amd_master.h:184:38: note: expanded from macro 'AMD_SDW_MCP_SLAVE_STAT_4_11'
#define AMD_SDW_MCP_SLAVE_STAT_4_11 GENMASK(39, 24)
^
include/linux/bits.h:38:31: note: expanded from macro 'GENMASK'
(GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))
^
include/linux/bits.h:36:11: note: expanded from macro '__GENMASK'
(~UL(0) >> (BITS_PER_LONG - 1 - (h))))
^
include/linux/bitfield.h:129:50: note: expanded from macro 'FIELD_GET'
(typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
~~~~~~~~~^~~~~~
include/linux/bitfield.h:45:38: note: expanded from macro '__bf_shf'
#define __bf_shf(x) (__builtin_ffsll(x) - 1)
^
>> drivers/soundwire/amd_master.c:1223:80: warning: shift count >= width of type [-Wshift-count-overflow]
slave_stat |= FIELD_GET(AMD_SDW_MCP_SLAVE_STATUS_8TO_11, status_change_8to11) << 32;
^ ~~
23 warnings generated.
vim +1223 drivers/soundwire/amd_master.c
1212
1213 static void amd_sdwc_update_slave_status(u32 status_change_0to7, u32 status_change_8to11,
1214 struct amd_sdwc_ctrl *ctrl)
1215 {
1216 u64 slave_stat = 0;
1217 u32 val = 0;
1218 int dev_index;
1219
1220 if (status_change_0to7 == AMD_SDW_SLAVE_0_ATTACHED)
1221 memset(ctrl->status, 0, sizeof(ctrl->status));
1222 slave_stat = status_change_0to7;
> 1223 slave_stat |= FIELD_GET(AMD_SDW_MCP_SLAVE_STATUS_8TO_11, status_change_8to11) << 32;
1224 dev_dbg(ctrl->dev, "%s: status_change_0to7:0x%x status_change_8to11:0x%x\n",
1225 __func__, status_change_0to7, status_change_8to11);
1226 if (slave_stat) {
1227 for (dev_index = 0; dev_index <= SDW_MAX_DEVICES; ++dev_index) {
1228 if (slave_stat & AMD_SDW_MCP_SLAVE_STATUS_VALID_MASK(dev_index)) {
1229 val = (slave_stat >> AMD_SDW_MCP_SLAVE_STAT_SHIFT_MASK(dev_index)) &
1230 AMD_SDW_MCP_SLAVE_STATUS_MASK;
1231 switch (val) {
1232 case SDW_SLAVE_ATTACHED:
1233 ctrl->status[dev_index] = SDW_SLAVE_ATTACHED;
1234 break;
1235 case SDW_SLAVE_UNATTACHED:
1236 ctrl->status[dev_index] = SDW_SLAVE_UNATTACHED;
1237 break;
1238 case SDW_SLAVE_ALERT:
1239 ctrl->status[dev_index] = SDW_SLAVE_ALERT;
1240 break;
1241 default:
1242 ctrl->status[dev_index] = SDW_SLAVE_RESERVED;
1243 break;
1244 }
1245 }
1246 }
1247 }
1248 }
1249
@@ -557,6 +557,47 @@ amd_reset_page_addr(struct sdw_bus *bus, unsigned int dev_num)
return amd_program_scp_addr(ctrl, &msg);
}
+static void amd_sdwc_process_ping_status(u64 response, struct amd_sdwc_ctrl *ctrl)
+{
+ u64 slave_stat = 0;
+ u32 val = 0;
+ u16 dev_index;
+
+ /* slave status from ping response*/
+ slave_stat = FIELD_GET(AMD_SDW_MCP_SLAVE_STAT_0_3, response);
+ slave_stat |= FIELD_GET(AMD_SDW_MCP_SLAVE_STAT_4_11, response) << 8;
+
+ dev_dbg(ctrl->dev, "%s: slave_stat:0x%llx\n", __func__, slave_stat);
+ for (dev_index = 0; dev_index <= SDW_MAX_DEVICES; ++dev_index) {
+ val = (slave_stat >> (dev_index * 2)) & AMD_SDW_MCP_SLAVE_STATUS_MASK;
+ dev_dbg(ctrl->dev, "%s val:0x%x\n", __func__, val);
+ switch (val) {
+ case SDW_SLAVE_ATTACHED:
+ ctrl->status[dev_index] = SDW_SLAVE_ATTACHED;
+ break;
+ case SDW_SLAVE_UNATTACHED:
+ ctrl->status[dev_index] = SDW_SLAVE_UNATTACHED;
+ break;
+ case SDW_SLAVE_ALERT:
+ ctrl->status[dev_index] = SDW_SLAVE_ALERT;
+ break;
+ default:
+ ctrl->status[dev_index] = SDW_SLAVE_RESERVED;
+ break;
+ }
+ }
+}
+
+static void amd_sdwc_read_and_process_ping_status(struct amd_sdwc_ctrl *ctrl)
+{
+ u64 response = 0;
+
+ mutex_lock(&ctrl->bus.msg_lock);
+ response = amd_sdwc_send_cmd_get_resp(ctrl, 0, 0);
+ mutex_unlock(&ctrl->bus.msg_lock);
+ amd_sdwc_process_ping_status(response, ctrl);
+}
+
static u32 amd_sdwc_read_ping_status(struct sdw_bus *bus)
{
struct amd_sdwc_ctrl *ctrl = to_amd_sdw(bus);
@@ -1132,6 +1173,119 @@ static int amd_sdwc_register_dais(struct amd_sdwc_ctrl *ctrl)
dais, num_dais);
}
+static void amd_sdwc_update_slave_status_work(struct work_struct *work)
+{
+ struct amd_sdwc_ctrl *ctrl =
+ container_of(work, struct amd_sdwc_ctrl, amd_sdw_work);
+ u32 sw_status_change_mask_0to7_reg;
+ u32 sw_status_change_mask_8to11_reg;
+
+ switch (ctrl->instance) {
+ case ACP_SDW0:
+ sw_status_change_mask_0to7_reg = SW_STATE_CHANGE_STATUS_MASK_0TO7;
+ sw_status_change_mask_8to11_reg = SW_STATE_CHANGE_STATUS_MASK_8TO11;
+ break;
+ case ACP_SDW1:
+ sw_status_change_mask_0to7_reg = P1_SW_STATE_CHANGE_STATUS_MASK_0TO7;
+ sw_status_change_mask_8to11_reg = P1_SW_STATE_CHANGE_STATUS_MASK_8TO11;
+ break;
+ default:
+ dev_err(ctrl->dev, "Invalid Soundwire controller instance\n");
+ return;
+ }
+
+ if (ctrl->status[0] == SDW_SLAVE_ATTACHED) {
+ acp_reg_writel(0, ctrl->mmio + sw_status_change_mask_0to7_reg);
+ acp_reg_writel(0, ctrl->mmio + sw_status_change_mask_8to11_reg);
+ }
+
+update_status:
+ sdw_handle_slave_status(&ctrl->bus, ctrl->status);
+ if (ctrl->status[0] == SDW_SLAVE_ATTACHED) {
+ acp_reg_writel(AMD_SDW_IRQ_MASK_0TO7, ctrl->mmio + sw_status_change_mask_0to7_reg);
+ acp_reg_writel(AMD_SDW_IRQ_MASK_8TO11,
+ ctrl->mmio + sw_status_change_mask_8to11_reg);
+ amd_sdwc_read_and_process_ping_status(ctrl);
+ goto update_status;
+ }
+}
+
+static void amd_sdwc_update_slave_status(u32 status_change_0to7, u32 status_change_8to11,
+ struct amd_sdwc_ctrl *ctrl)
+{
+ u64 slave_stat = 0;
+ u32 val = 0;
+ int dev_index;
+
+ if (status_change_0to7 == AMD_SDW_SLAVE_0_ATTACHED)
+ memset(ctrl->status, 0, sizeof(ctrl->status));
+ slave_stat = status_change_0to7;
+ slave_stat |= FIELD_GET(AMD_SDW_MCP_SLAVE_STATUS_8TO_11, status_change_8to11) << 32;
+ dev_dbg(ctrl->dev, "%s: status_change_0to7:0x%x status_change_8to11:0x%x\n",
+ __func__, status_change_0to7, status_change_8to11);
+ if (slave_stat) {
+ for (dev_index = 0; dev_index <= SDW_MAX_DEVICES; ++dev_index) {
+ if (slave_stat & AMD_SDW_MCP_SLAVE_STATUS_VALID_MASK(dev_index)) {
+ val = (slave_stat >> AMD_SDW_MCP_SLAVE_STAT_SHIFT_MASK(dev_index)) &
+ AMD_SDW_MCP_SLAVE_STATUS_MASK;
+ switch (val) {
+ case SDW_SLAVE_ATTACHED:
+ ctrl->status[dev_index] = SDW_SLAVE_ATTACHED;
+ break;
+ case SDW_SLAVE_UNATTACHED:
+ ctrl->status[dev_index] = SDW_SLAVE_UNATTACHED;
+ break;
+ case SDW_SLAVE_ALERT:
+ ctrl->status[dev_index] = SDW_SLAVE_ALERT;
+ break;
+ default:
+ ctrl->status[dev_index] = SDW_SLAVE_RESERVED;
+ break;
+ }
+ }
+ }
+ }
+}
+
+static void amd_sdwc_irq_thread(struct work_struct *work)
+{
+ struct amd_sdwc_ctrl *ctrl =
+ container_of(work, struct amd_sdwc_ctrl, amd_sdw_irq_thread);
+ u32 sw_status_change_0to7_reg;
+ u32 sw_status_change_8to11_reg;
+ u32 status_change_8to11;
+ u32 status_change_0to7;
+
+ switch (ctrl->instance) {
+ case ACP_SDW0:
+ sw_status_change_0to7_reg = SW_STATE_CHANGE_STATUS_0TO7;
+ sw_status_change_8to11_reg = SW_STATE_CHANGE_STATUS_8TO11;
+ break;
+ case ACP_SDW1:
+ sw_status_change_0to7_reg = P1_SW_STATE_CHANGE_STATUS_0TO7;
+ sw_status_change_8to11_reg = P1_SW_STATE_CHANGE_STATUS_8TO11;
+ break;
+ default:
+ dev_err(ctrl->dev, "Invalid Soundwire controller instance\n");
+ return;
+ }
+
+ status_change_8to11 = acp_reg_readl(ctrl->mmio + sw_status_change_8to11_reg);
+ status_change_0to7 = acp_reg_readl(ctrl->mmio + sw_status_change_0to7_reg);
+ dev_dbg(ctrl->dev, "%s [SDW%d] SDW INT: 0to7=0x%x, 8to11=0x%x\n",
+ __func__, ctrl->instance, status_change_0to7, status_change_8to11);
+ if (status_change_8to11 & AMD_SDW_PREQ_INTR_STAT) {
+ amd_sdwc_read_and_process_ping_status(ctrl);
+ } else {
+ /* Check for the updated status on Slave device */
+ amd_sdwc_update_slave_status(status_change_0to7, status_change_8to11, ctrl);
+ }
+ if (status_change_8to11 || status_change_0to7)
+ schedule_work(&ctrl->amd_sdw_work);
+ acp_reg_writel(0x00, ctrl->mmio + sw_status_change_8to11_reg);
+ acp_reg_writel(0x00, ctrl->mmio + sw_status_change_0to7_reg);
+}
+
static void amd_sdwc_probe_work(struct work_struct *work)
{
struct amd_sdwc_ctrl *ctrl = container_of(work, struct amd_sdwc_ctrl, probe_work);
@@ -1229,6 +1383,8 @@ static int amd_sdwc_probe(struct platform_device *pdev)
sdw_bus_master_delete(&ctrl->bus);
return ret;
}
+ INIT_WORK(&ctrl->amd_sdw_irq_thread, amd_sdwc_irq_thread);
+ INIT_WORK(&ctrl->amd_sdw_work, amd_sdwc_update_slave_status_work);
INIT_WORK(&ctrl->probe_work, amd_sdwc_probe_work);
schedule_work(&ctrl->probe_work);
return 0;
@@ -236,6 +236,7 @@
#define AMD_SDW1_PAD_KEEPER_EN_MASK 0x10
#define AMD_SDW0_PAD_KEEPER_DISABLE_MASK 0x1E
#define AMD_SDW1_PAD_KEEPER_DISABLE_MASK 0xF
+#define AMD_SDW_PREQ_INTR_STAT BIT(19)
enum amd_sdw_channel {
/* SDW0 */
@@ -24,9 +24,12 @@ struct amd_sdwc_ctrl {
struct sdw_bus bus;
struct device *dev;
void __iomem *mmio;
+ struct work_struct amd_sdw_irq_thread;
+ struct work_struct amd_sdw_work;
struct work_struct probe_work;
struct mutex *sdw_lock;
struct sdw_stream_runtime *sruntime[AMD_SDW_MAX_DAIS];
+ enum sdw_slave_status status[SDW_MAX_DEVICES + 1];
int num_din_ports;
int num_dout_ports;
int cols_index;