Loading soc/swr-mstr-ctrl.c +72 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,8 @@ #define SWRM_DP_PORT_CTRL_OFFSET2_SHFT 0x10 #define SWRM_DP_PORT_CTRL_OFFSET1_SHFT 0x08 #define SWR_OVERFLOW_RETRY_COUNT 30 /* pm runtime auto suspend timer in msecs */ static int auto_suspend_timer = 500; module_param(auto_suspend_timer, int, 0664); Loading Loading @@ -108,6 +110,11 @@ enum { LPASS_AUDIO_CORE, }; enum { SWRM_WR_CHECK_AVAIL, SWRM_RD_CHECK_AVAIL, }; #define TRUE 1 #define FALSE 0 Loading Loading @@ -790,6 +797,54 @@ static u32 swrm_get_packed_reg_val(u8 *cmd_id, u8 cmd_data, return val; } static void swrm_wait_for_fifo_avail(struct swr_mstr_ctrl *swrm, int swrm_rd_wr) { u32 fifo_outstanding_cmd; u32 fifo_retry_count = SWR_OVERFLOW_RETRY_COUNT; if (swrm_rd_wr) { /* Check for fifo underflow during read */ /* Check no of outstanding commands in fifo before read */ fifo_outstanding_cmd = ((swr_master_read(swrm, SWRM_CMD_FIFO_STATUS) & 0x001F0000) >> 16); if (fifo_outstanding_cmd == 0) { while (fifo_retry_count) { usleep_range(500, 510); fifo_outstanding_cmd = ((swr_master_read (swrm, SWRM_CMD_FIFO_STATUS) & 0x001F0000) >> 16); fifo_retry_count--; if (fifo_outstanding_cmd > 0) break; } } if (fifo_outstanding_cmd == 0) dev_err_ratelimited(swrm->dev, "%s err read underflow\n", __func__); } else { /* Check for fifo overflow during write */ /* Check no of outstanding commands in fifo before write */ fifo_outstanding_cmd = ((swr_master_read(swrm, SWRM_CMD_FIFO_STATUS) & 0x00001F00) >> 8); if (fifo_outstanding_cmd == swrm->wr_fifo_depth) { while (fifo_retry_count) { usleep_range(500, 510); fifo_outstanding_cmd = ((swr_master_read(swrm, SWRM_CMD_FIFO_STATUS) & 0x00001F00) >> 8); fifo_retry_count--; if (fifo_outstanding_cmd < swrm->wr_fifo_depth) break; } } if (fifo_outstanding_cmd == swrm->wr_fifo_depth) dev_err_ratelimited(swrm->dev, "%s err write overflow\n", __func__); } } static int swrm_cmd_fifo_rd_cmd(struct swr_mstr_ctrl *swrm, int *cmd_data, u8 dev_addr, u8 cmd_id, u16 reg_addr, u32 len) Loading @@ -803,12 +858,19 @@ static int swrm_cmd_fifo_rd_cmd(struct swr_mstr_ctrl *swrm, int *cmd_data, /* skip delay if read is handled in platform driver */ swr_master_write(swrm, SWRM_CMD_FIFO_RD_CMD, val); } else { /* * Check for outstanding cmd wrt. write fifo depth to avoid * overflow as read will also increase write fifo cnt. */ swrm_wait_for_fifo_avail(swrm, SWRM_WR_CHECK_AVAIL); /* wait for FIFO RD to complete to avoid overflow */ usleep_range(100, 105); swr_master_write(swrm, SWRM_CMD_FIFO_RD_CMD, val); /* wait for FIFO RD CMD complete to avoid overflow */ usleep_range(250, 255); } /* Check if slave responds properly after FIFO RD is complete */ swrm_wait_for_fifo_avail(swrm, SWRM_RD_CHECK_AVAIL); retry_read: *cmd_data = swr_master_read(swrm, SWRM_CMD_FIFO_RD_FIFO); dev_dbg(swrm->dev, "%s: reg: 0x%x, cmd_id: 0x%x, rcmd_id: 0x%x, \ Loading Loading @@ -855,6 +917,11 @@ static int swrm_cmd_fifo_wr_cmd(struct swr_mstr_ctrl *swrm, u8 cmd_data, dev_dbg(swrm->dev, "%s: reg: 0x%x, cmd_id: 0x%x,wcmd_id: 0x%x, \ dev_num: 0x%x, cmd_data: 0x%x\n", __func__, reg_addr, cmd_id, swrm->wcmd_id,dev_addr, cmd_data); /* * Check for outstanding cmd wrt. write fifo depth to avoid * overflow. */ swrm_wait_for_fifo_avail(swrm, SWRM_WR_CHECK_AVAIL); swr_master_write(swrm, SWRM_CMD_FIFO_WR_CMD, val); /* * wait for FIFO WR command to complete to avoid overflow Loading Loading @@ -2700,6 +2767,11 @@ static int swrm_probe(struct platform_device *pdev) if (pdev->dev.of_node) of_register_swr_devices(&swrm->master); swrm->rd_fifo_depth = ((swr_master_read(swrm, SWRM_COMP_PARAMS) & SWRM_COMP_PARAMS_RD_FIFO_DEPTH) >> 15); swrm->wr_fifo_depth = ((swr_master_read(swrm, SWRM_COMP_PARAMS) & SWRM_COMP_PARAMS_WR_FIFO_DEPTH) >> 10); #ifdef CONFIG_DEBUG_FS swrm->debugfs_swrm_dent = debugfs_create_dir(dev_name(&pdev->dev), 0); if (!IS_ERR(swrm->debugfs_swrm_dent)) { Loading soc/swr-mstr-ctrl.h +2 −0 Original line number Diff line number Diff line Loading @@ -190,6 +190,8 @@ struct swr_mstr_ctrl { int aud_core_clk_en; int clk_src; u32 disable_div2_clk_switch; u32 rd_fifo_depth; u32 wr_fifo_depth; #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_swrm_dent; struct dentry *debugfs_peek; Loading soc/swr-mstr-registers.h +4 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2015, 2018-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2015, 2018-2020 The Linux Foundation. All rights reserved. */ #ifndef _SWRM_REGISTERS_H Loading Loading @@ -108,4 +108,7 @@ #define SWRM_INTERRUPT_STATUS_EXT_CLK_STOP_WAKEUP 0x10000 #define SWRM_INTERRUPT_MAX 0x11 #define SWRM_COMP_PARAMS_WR_FIFO_DEPTH 0x00007C00 #define SWRM_COMP_PARAMS_RD_FIFO_DEPTH 0x000F8000 #endif /* _SWRM_REGISTERS_H */ Loading
soc/swr-mstr-ctrl.c +72 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,8 @@ #define SWRM_DP_PORT_CTRL_OFFSET2_SHFT 0x10 #define SWRM_DP_PORT_CTRL_OFFSET1_SHFT 0x08 #define SWR_OVERFLOW_RETRY_COUNT 30 /* pm runtime auto suspend timer in msecs */ static int auto_suspend_timer = 500; module_param(auto_suspend_timer, int, 0664); Loading Loading @@ -108,6 +110,11 @@ enum { LPASS_AUDIO_CORE, }; enum { SWRM_WR_CHECK_AVAIL, SWRM_RD_CHECK_AVAIL, }; #define TRUE 1 #define FALSE 0 Loading Loading @@ -790,6 +797,54 @@ static u32 swrm_get_packed_reg_val(u8 *cmd_id, u8 cmd_data, return val; } static void swrm_wait_for_fifo_avail(struct swr_mstr_ctrl *swrm, int swrm_rd_wr) { u32 fifo_outstanding_cmd; u32 fifo_retry_count = SWR_OVERFLOW_RETRY_COUNT; if (swrm_rd_wr) { /* Check for fifo underflow during read */ /* Check no of outstanding commands in fifo before read */ fifo_outstanding_cmd = ((swr_master_read(swrm, SWRM_CMD_FIFO_STATUS) & 0x001F0000) >> 16); if (fifo_outstanding_cmd == 0) { while (fifo_retry_count) { usleep_range(500, 510); fifo_outstanding_cmd = ((swr_master_read (swrm, SWRM_CMD_FIFO_STATUS) & 0x001F0000) >> 16); fifo_retry_count--; if (fifo_outstanding_cmd > 0) break; } } if (fifo_outstanding_cmd == 0) dev_err_ratelimited(swrm->dev, "%s err read underflow\n", __func__); } else { /* Check for fifo overflow during write */ /* Check no of outstanding commands in fifo before write */ fifo_outstanding_cmd = ((swr_master_read(swrm, SWRM_CMD_FIFO_STATUS) & 0x00001F00) >> 8); if (fifo_outstanding_cmd == swrm->wr_fifo_depth) { while (fifo_retry_count) { usleep_range(500, 510); fifo_outstanding_cmd = ((swr_master_read(swrm, SWRM_CMD_FIFO_STATUS) & 0x00001F00) >> 8); fifo_retry_count--; if (fifo_outstanding_cmd < swrm->wr_fifo_depth) break; } } if (fifo_outstanding_cmd == swrm->wr_fifo_depth) dev_err_ratelimited(swrm->dev, "%s err write overflow\n", __func__); } } static int swrm_cmd_fifo_rd_cmd(struct swr_mstr_ctrl *swrm, int *cmd_data, u8 dev_addr, u8 cmd_id, u16 reg_addr, u32 len) Loading @@ -803,12 +858,19 @@ static int swrm_cmd_fifo_rd_cmd(struct swr_mstr_ctrl *swrm, int *cmd_data, /* skip delay if read is handled in platform driver */ swr_master_write(swrm, SWRM_CMD_FIFO_RD_CMD, val); } else { /* * Check for outstanding cmd wrt. write fifo depth to avoid * overflow as read will also increase write fifo cnt. */ swrm_wait_for_fifo_avail(swrm, SWRM_WR_CHECK_AVAIL); /* wait for FIFO RD to complete to avoid overflow */ usleep_range(100, 105); swr_master_write(swrm, SWRM_CMD_FIFO_RD_CMD, val); /* wait for FIFO RD CMD complete to avoid overflow */ usleep_range(250, 255); } /* Check if slave responds properly after FIFO RD is complete */ swrm_wait_for_fifo_avail(swrm, SWRM_RD_CHECK_AVAIL); retry_read: *cmd_data = swr_master_read(swrm, SWRM_CMD_FIFO_RD_FIFO); dev_dbg(swrm->dev, "%s: reg: 0x%x, cmd_id: 0x%x, rcmd_id: 0x%x, \ Loading Loading @@ -855,6 +917,11 @@ static int swrm_cmd_fifo_wr_cmd(struct swr_mstr_ctrl *swrm, u8 cmd_data, dev_dbg(swrm->dev, "%s: reg: 0x%x, cmd_id: 0x%x,wcmd_id: 0x%x, \ dev_num: 0x%x, cmd_data: 0x%x\n", __func__, reg_addr, cmd_id, swrm->wcmd_id,dev_addr, cmd_data); /* * Check for outstanding cmd wrt. write fifo depth to avoid * overflow. */ swrm_wait_for_fifo_avail(swrm, SWRM_WR_CHECK_AVAIL); swr_master_write(swrm, SWRM_CMD_FIFO_WR_CMD, val); /* * wait for FIFO WR command to complete to avoid overflow Loading Loading @@ -2700,6 +2767,11 @@ static int swrm_probe(struct platform_device *pdev) if (pdev->dev.of_node) of_register_swr_devices(&swrm->master); swrm->rd_fifo_depth = ((swr_master_read(swrm, SWRM_COMP_PARAMS) & SWRM_COMP_PARAMS_RD_FIFO_DEPTH) >> 15); swrm->wr_fifo_depth = ((swr_master_read(swrm, SWRM_COMP_PARAMS) & SWRM_COMP_PARAMS_WR_FIFO_DEPTH) >> 10); #ifdef CONFIG_DEBUG_FS swrm->debugfs_swrm_dent = debugfs_create_dir(dev_name(&pdev->dev), 0); if (!IS_ERR(swrm->debugfs_swrm_dent)) { Loading
soc/swr-mstr-ctrl.h +2 −0 Original line number Diff line number Diff line Loading @@ -190,6 +190,8 @@ struct swr_mstr_ctrl { int aud_core_clk_en; int clk_src; u32 disable_div2_clk_switch; u32 rd_fifo_depth; u32 wr_fifo_depth; #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_swrm_dent; struct dentry *debugfs_peek; Loading
soc/swr-mstr-registers.h +4 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2015, 2018-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2015, 2018-2020 The Linux Foundation. All rights reserved. */ #ifndef _SWRM_REGISTERS_H Loading Loading @@ -108,4 +108,7 @@ #define SWRM_INTERRUPT_STATUS_EXT_CLK_STOP_WAKEUP 0x10000 #define SWRM_INTERRUPT_MAX 0x11 #define SWRM_COMP_PARAMS_WR_FIFO_DEPTH 0x00007C00 #define SWRM_COMP_PARAMS_RD_FIFO_DEPTH 0x000F8000 #endif /* _SWRM_REGISTERS_H */