2022-08-02 14:08:45

by Stanley Chu

[permalink] [raw]
Subject: [PATCH v4 0/5] scsi: ufs-mediatek: Provide features and fixes in MediaTek platforms

Hi Martin,

This series provides some features and fixes in MediaTek UFS platforms.
Please consider this patch series for kernel v5.20.

Changes since v3:
- Fix some type errors caught by Coverity Tool

Changes since v2:
- Remove Change-ID tag in patch "scsi: ufs: ufs-mediatek: Remove redundant header files" (Bart)
- Move const string table to ufs-mediatek.c from ufs-mediatek.h (Bart)

Changes since v1:
- Remove unnecessary changes in patch "scsi: ufs: ufs-mediatek: Fix performance scaling"

Peter Wang (2):
scsi: ufs: ufs-mediatek: Dump more registers
scsi: ufs: ufs-mediatek: Fix performance scaling

Po-Wen Kao (1):
scsi: ufs: ufs-medaitek: Support clk-scaling to optimize power
consumption

Stanley Chu (2):
scsi: ufs: ufs-mediatek: Remove redundant header files
scsi: ufs: ufs-mediatek: Provide detailed description for UIC errors

drivers/ufs/host/ufs-mediatek-trace.h | 27 +++-
drivers/ufs/host/ufs-mediatek.c | 205 +++++++++++++++++++++++++-
drivers/ufs/host/ufs-mediatek.h | 7 +
3 files changed, 230 insertions(+), 9 deletions(-)

--
2.18.0



2022-08-02 14:12:06

by Stanley Chu

[permalink] [raw]
Subject: [PATCH v4 4/5] scsi: ufs: ufs-mediatek: Fix performance scaling

From: Peter Wang <[email protected]>

If clk-scaling is enabled, performance scaling can be bound
to the decision of clk-scaling to avoid unnecessary boosting.

Meanwhile, fix missing initialization of pm-qos request.

Reviewed-by: Stanley Chu <[email protected]>
Signed-off-by: Peter Wang <[email protected]>
Signed-off-by: Stanley Chu <[email protected]>
---
drivers/ufs/host/ufs-mediatek.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c
index 2b85d2406714..e1f131a93792 100644
--- a/drivers/ufs/host/ufs-mediatek.c
+++ b/drivers/ufs/host/ufs-mediatek.c
@@ -635,6 +635,12 @@ static void ufs_mtk_boost_pm_qos(struct ufs_hba *hba, bool boost)
boost ? 0 : PM_QOS_DEFAULT_VALUE);
}

+static void ufs_mtk_scale_perf(struct ufs_hba *hba, bool scale_up)
+{
+ ufs_mtk_boost_crypt(hba, scale_up);
+ ufs_mtk_boost_pm_qos(hba, scale_up);
+}
+
static void ufs_mtk_pwr_ctrl(struct ufs_hba *hba, bool on)
{
struct ufs_mtk_host *host = ufshcd_get_variant(hba);
@@ -642,11 +648,11 @@ static void ufs_mtk_pwr_ctrl(struct ufs_hba *hba, bool on)
if (on) {
phy_power_on(host->mphy);
ufs_mtk_setup_ref_clk(hba, on);
- ufs_mtk_boost_crypt(hba, on);
- ufs_mtk_boost_pm_qos(hba, on);
+ if (!ufshcd_is_clkscaling_supported(hba))
+ ufs_mtk_scale_perf(hba, on);
} else {
- ufs_mtk_boost_pm_qos(hba, on);
- ufs_mtk_boost_crypt(hba, on);
+ if (!ufshcd_is_clkscaling_supported(hba))
+ ufs_mtk_scale_perf(hba, on);
ufs_mtk_setup_ref_clk(hba, on);
phy_power_off(host->mphy);
}
@@ -870,6 +876,10 @@ static int ufs_mtk_init(struct ufs_hba *hba)

host->ip_ver = ufshcd_readl(hba, REG_UFS_MTK_IP_VER);

+ /* Initialize pm-qos request */
+ cpu_latency_qos_add_request(&host->pm_qos_req, PM_QOS_DEFAULT_VALUE);
+ host->pm_qos_init = true;
+
goto out;

out_variant_clear:
--
2.18.0


2022-08-02 14:32:53

by Stanley Chu

[permalink] [raw]
Subject: [PATCH v4 3/5] scsi: ufs: ufs-mediatek: Dump more registers

From: Peter Wang <[email protected]>

Dump more proprietary UFSHCI status registers for
easier issue breakdown.

Reviewed-by: Stanley Chu <[email protected]>
Signed-off-by: Peter Wang <[email protected]>
Signed-off-by: Stanley Chu <[email protected]>
---
drivers/ufs/host/ufs-mediatek.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c
index 62bc3b791b38..2b85d2406714 100644
--- a/drivers/ufs/host/ufs-mediatek.c
+++ b/drivers/ufs/host/ufs-mediatek.c
@@ -1284,13 +1284,16 @@ static int ufs_mtk_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)

static void ufs_mtk_dbg_register_dump(struct ufs_hba *hba)
{
- ufshcd_dump_regs(hba, REG_UFS_REFCLK_CTRL, 0x4, "Ref-Clk Ctrl ");
+ /* Dump ufshci register 0x140 ~ 0x14C */
+ ufshcd_dump_regs(hba, REG_UFS_XOUFS_CTRL, 0x10,
+ "XOUFS Ctrl (0x140): ");

ufshcd_dump_regs(hba, REG_UFS_EXTREG, 0x4, "Ext Reg ");

+ /* Dump ufshci register 0x2200 ~ 0x22AC */
ufshcd_dump_regs(hba, REG_UFS_MPHYCTRL,
REG_UFS_REJECT_MON - REG_UFS_MPHYCTRL + 4,
- "MPHY Ctrl ");
+ "MPHY Ctrl (0x2200): ");

/* Direct debugging information to REG_MTK_PROBE */
ufs_mtk_dbg_sel(hba);
--
2.18.0


2022-08-02 14:40:05

by Stanley Chu

[permalink] [raw]
Subject: [PATCH v4 5/5] scsi: ufs: ufs-medaitek: Support clk-scaling to optimize power consumption

From: Po-Wen Kao <[email protected]>

Provide clk-scaling feature in MediaTek UFS platforms.

MediaTek platform supports clk-scaling by switching parent clock
mux of UFSHCI main clocks: ufs_sel.

The driver needs to prevent changing the rate of ufs_sel because
its parent PLL clock may be shared between multiple IPs. In order
to achieve this goal, the maximum and minimum clock rates of ufs_sel
defined in dts should match the rate of "ufs_sel_max_src" and
"ufs_sel_min_src" respectively.

Reviewed-by: Stanley Chu <[email protected]>
Signed-off-by: Po-Wen Kao <[email protected]>
Signed-off-by: Stanley Chu <[email protected]>
---
drivers/ufs/host/ufs-mediatek-trace.h | 27 +++++-
drivers/ufs/host/ufs-mediatek.c | 121 ++++++++++++++++++++++++++
drivers/ufs/host/ufs-mediatek.h | 7 ++
3 files changed, 153 insertions(+), 2 deletions(-)

diff --git a/drivers/ufs/host/ufs-mediatek-trace.h b/drivers/ufs/host/ufs-mediatek-trace.h
index 7e010848dc99..b5f2ec314074 100644
--- a/drivers/ufs/host/ufs-mediatek-trace.h
+++ b/drivers/ufs/host/ufs-mediatek-trace.h
@@ -24,9 +24,32 @@ TRACE_EVENT(ufs_mtk_event,
__entry->data = data;
),

- TP_printk("ufs:event=%u data=%u",
+ TP_printk("ufs: event=%u data=%u",
__entry->type, __entry->data)
- );
+);
+
+TRACE_EVENT(ufs_mtk_clk_scale,
+ TP_PROTO(const char *name, bool scale_up, unsigned long clk_rate),
+ TP_ARGS(name, scale_up, clk_rate),
+
+ TP_STRUCT__entry(
+ __field(const char*, name)
+ __field(bool, scale_up)
+ __field(unsigned long, clk_rate)
+ ),
+
+ TP_fast_assign(
+ __entry->name = name;
+ __entry->scale_up = scale_up;
+ __entry->clk_rate = clk_rate;
+ ),
+
+ TP_printk("ufs: clk (%s) scaled %s @ %lu",
+ __entry->name,
+ __entry->scale_up ? "up" : "down",
+ __entry->clk_rate)
+);
+
#endif

#undef TRACE_INCLUDE_PATH
diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c
index e1f131a93792..7309f3f87eac 100644
--- a/drivers/ufs/host/ufs-mediatek.c
+++ b/drivers/ufs/host/ufs-mediatek.c
@@ -738,6 +738,46 @@ static u32 ufs_mtk_get_ufs_hci_version(struct ufs_hba *hba)
return hba->ufs_version;
}

+/**
+ * ufs_mtk_init_clocks - Init mtk driver private clocks
+ *
+ * @hba: per adapter instance
+ */
+static void ufs_mtk_init_clocks(struct ufs_hba *hba)
+{
+ struct ufs_mtk_host *host = ufshcd_get_variant(hba);
+ struct list_head *head = &hba->clk_list_head;
+ struct ufs_mtk_clk *mclk = &host->mclk;
+ struct ufs_clk_info *clki, *clki_tmp;
+
+ /*
+ * Find private clocks and store them in struct ufs_mtk_clk.
+ * Remove "ufs_sel_min_src" and "ufs_sel_min_src" from list to avoid
+ * being switched on/off in clock gating.
+ */
+ list_for_each_entry_safe(clki, clki_tmp, head, list) {
+ if (!strcmp(clki->name, "ufs_sel")) {
+ host->mclk.ufs_sel_clki = clki;
+ } else if (!strcmp(clki->name, "ufs_sel_max_src")) {
+ host->mclk.ufs_sel_max_clki = clki;
+ clk_disable_unprepare(clki->clk);
+ list_del(&clki->list);
+ } else if (!strcmp(clki->name, "ufs_sel_min_src")) {
+ host->mclk.ufs_sel_min_clki = clki;
+ clk_disable_unprepare(clki->clk);
+ list_del(&clki->list);
+ }
+ }
+
+ if (!mclk->ufs_sel_clki || !mclk->ufs_sel_max_clki ||
+ !mclk->ufs_sel_min_clki) {
+ hba->caps &= ~UFSHCD_CAP_CLK_SCALING;
+ dev_info(hba->dev,
+ "%s: Clk-scaling not ready. Feature disabled.",
+ __func__);
+ }
+}
+
#define MAX_VCC_NAME 30
static int ufs_mtk_vreg_fix_vcc(struct ufs_hba *hba)
{
@@ -858,12 +898,18 @@ static int ufs_mtk_init(struct ufs_hba *hba)

/* Enable WriteBooster */
hba->caps |= UFSHCD_CAP_WB_EN;
+
+ /* Enable clk scaling*/
+ hba->caps |= UFSHCD_CAP_CLK_SCALING;
+
hba->quirks |= UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL;
hba->vps->wb_flush_threshold = UFS_WB_BUF_REMAIN_PERCENT(80);

if (host->caps & UFS_MTK_CAP_DISABLE_AH8)
hba->caps |= UFSHCD_CAP_HIBERN8_WITH_CLK_GATING;

+ ufs_mtk_init_clocks(hba);
+
/*
* ufshcd_vops_init() is invoked after
* ufshcd_setup_clock(true) in ufshcd_hba_init() thus
@@ -1384,6 +1430,79 @@ static void ufs_mtk_event_notify(struct ufs_hba *hba,
}
}

+static void ufs_mtk_config_scaling_param(struct ufs_hba *hba,
+ struct devfreq_dev_profile *profile,
+ struct devfreq_simple_ondemand_data *data)
+{
+ /* Customize min gear in clk scaling */
+ hba->clk_scaling.min_gear = UFS_HS_G4;
+
+ hba->vps->devfreq_profile.polling_ms = 200;
+ hba->vps->ondemand_data.upthreshold = 50;
+ hba->vps->ondemand_data.downdifferential = 20;
+}
+
+/**
+ * ufs_mtk_clk_scale - Internal clk scaling operation
+ *
+ * MTK platform supports clk scaling by switching parent of ufs_sel(mux).
+ * The ufs_sel downstream to ufs_ck which feeds directly to UFS hardware.
+ * Max and min clocks rate of ufs_sel defined in dts should match rate of
+ * "ufs_sel_max_src" and "ufs_sel_min_src" respectively.
+ * This prevent changing rate of pll clock that is shared between modules.
+ *
+ * @hba: per adapter instance
+ * @scale_up: True for scaling up and false for scaling down
+ */
+static void ufs_mtk_clk_scale(struct ufs_hba *hba, bool scale_up)
+{
+ struct ufs_mtk_host *host = ufshcd_get_variant(hba);
+ struct ufs_mtk_clk *mclk = &host->mclk;
+ struct ufs_clk_info *clki = mclk->ufs_sel_clki;
+ int ret = 0;
+
+ ret = clk_prepare_enable(clki->clk);
+ if (ret) {
+ dev_info(hba->dev,
+ "clk_prepare_enable() fail, ret: %d\n", ret);
+ return;
+ }
+
+ if (scale_up) {
+ ret = clk_set_parent(clki->clk, mclk->ufs_sel_max_clki->clk);
+ clki->curr_freq = clki->max_freq;
+ } else {
+ ret = clk_set_parent(clki->clk, mclk->ufs_sel_min_clki->clk);
+ clki->curr_freq = clki->min_freq;
+ }
+
+ if (ret) {
+ dev_info(hba->dev,
+ "Failed to set ufs_sel_clki, ret: %d\n", ret);
+ }
+
+ clk_disable_unprepare(clki->clk);
+
+ trace_ufs_mtk_clk_scale(clki->name, scale_up, clk_get_rate(clki->clk));
+}
+
+static int ufs_mtk_clk_scale_notify(struct ufs_hba *hba, bool scale_up,
+ enum ufs_notify_change_status status)
+{
+ if (!ufshcd_is_clkscaling_supported(hba))
+ return 0;
+
+ if (status == PRE_CHANGE) {
+ /* Switch parent before clk_set_rate() */
+ ufs_mtk_clk_scale(hba, scale_up);
+ } else {
+ /* Request interrupt latency QoS accordingly */
+ ufs_mtk_scale_perf(hba, scale_up);
+ }
+
+ return 0;
+}
+
/*
* struct ufs_hba_mtk_vops - UFS MTK specific variant operations
*
@@ -1405,6 +1524,8 @@ static const struct ufs_hba_variant_ops ufs_hba_mtk_vops = {
.dbg_register_dump = ufs_mtk_dbg_register_dump,
.device_reset = ufs_mtk_device_reset,
.event_notify = ufs_mtk_event_notify,
+ .config_scaling_param = ufs_mtk_config_scaling_param,
+ .clk_scale_notify = ufs_mtk_clk_scale_notify,
};

/**
diff --git a/drivers/ufs/host/ufs-mediatek.h b/drivers/ufs/host/ufs-mediatek.h
index aa26d415527b..2fc6d7b87694 100644
--- a/drivers/ufs/host/ufs-mediatek.h
+++ b/drivers/ufs/host/ufs-mediatek.h
@@ -124,6 +124,12 @@ struct ufs_mtk_crypt_cfg {
int vcore_volt;
};

+struct ufs_mtk_clk {
+ struct ufs_clk_info *ufs_sel_clki; /* Mux */
+ struct ufs_clk_info *ufs_sel_max_clki; /* Max src */
+ struct ufs_clk_info *ufs_sel_min_clki; /* Min src */
+};
+
struct ufs_mtk_hw_ver {
u8 step;
u8 minor;
@@ -139,6 +145,7 @@ struct ufs_mtk_host {
struct reset_control *crypto_reset;
struct ufs_hba *hba;
struct ufs_mtk_crypt_cfg *crypt;
+ struct ufs_mtk_clk mclk;
struct ufs_mtk_hw_ver hw_ver;
enum ufs_mtk_host_caps caps;
bool mphy_powered_on;
--
2.18.0


2022-08-02 14:40:43

by Stanley Chu

[permalink] [raw]
Subject: [PATCH v4 2/5] scsi: ufs: ufs-mediatek: Provide detailed description for UIC errors

Provide detailed description in logs for UIC errors for
eaiser issue breakdown.

Signed-off-by: Stanley Chu <[email protected]>
---
drivers/ufs/host/ufs-mediatek.c | 58 +++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)

diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c
index ff6fd8f52ebc..62bc3b791b38 100644
--- a/drivers/ufs/host/ufs-mediatek.c
+++ b/drivers/ufs/host/ufs-mediatek.c
@@ -46,6 +46,44 @@ static const struct of_device_id ufs_mtk_of_match[] = {
{},
};

+/*
+ * Details of UIC Errors
+ */
+static const char *const ufs_uic_err_str[] = {
+ "PHY Adapter Layer",
+ "Data Link Layer",
+ "Network Link Layer",
+ "Transport Link Layer",
+ "DME"
+};
+
+static const char *const ufs_uic_pa_err_str[] = {
+ "PHY error on Lane 0",
+ "PHY error on Lane 1",
+ "PHY error on Lane 2",
+ "PHY error on Lane 3",
+ "Generic PHY Adapter Error. This should be the LINERESET indication"
+};
+
+static const char *const ufs_uic_dl_err_str[] = {
+ "NAC_RECEIVED",
+ "TCx_REPLAY_TIMER_EXPIRED",
+ "AFCx_REQUEST_TIMER_EXPIRED",
+ "FCx_PROTECTION_TIMER_EXPIRED",
+ "CRC_ERROR",
+ "RX_BUFFER_OVERFLOW",
+ "MAX_FRAME_LENGTH_EXCEEDED",
+ "WRONG_SEQUENCE_NUMBER",
+ "AFC_FRAME_SYNTAX_ERROR",
+ "NAC_FRAME_SYNTAX_ERROR",
+ "EOF_SYNTAX_ERROR",
+ "FRAME_SYNTAX_ERROR",
+ "BAD_CTRL_SYMBOL_TYPE",
+ "PA_INIT_ERROR",
+ "PA_ERROR_IND_RECEIVED",
+ "PA_INIT"
+};
+
static bool ufs_mtk_is_boost_crypt_enabled(struct ufs_hba *hba)
{
struct ufs_mtk_host *host = ufshcd_get_variant(hba);
@@ -1309,8 +1347,28 @@ static void ufs_mtk_event_notify(struct ufs_hba *hba,
enum ufs_event_type evt, void *data)
{
unsigned int val = *(u32 *)data;
+ unsigned long reg;
+ u8 bit;

trace_ufs_mtk_event(evt, val);
+
+ /* Print details of UIC Errors */
+ if (evt <= UFS_EVT_DME_ERR) {
+ dev_info(hba->dev,
+ "Host UIC Error Code (%s): %08x\n",
+ ufs_uic_err_str[evt], val);
+ reg = val;
+ }
+
+ if (evt == UFS_EVT_PA_ERR) {
+ for_each_set_bit(bit, &reg, ARRAY_SIZE(ufs_uic_pa_err_str))
+ dev_info(hba->dev, "%s\n", ufs_uic_pa_err_str[bit]);
+ }
+
+ if (evt == UFS_EVT_DL_ERR) {
+ for_each_set_bit(bit, &reg, ARRAY_SIZE(ufs_uic_dl_err_str))
+ dev_info(hba->dev, "%s\n", ufs_uic_dl_err_str[bit]);
+ }
}

/*
--
2.18.0


2022-08-02 14:40:54

by Stanley Chu

[permalink] [raw]
Subject: [PATCH v4 1/5] scsi: ufs: ufs-mediatek: Remove redundant header files

Remove redundant header files like
<linux/sched/clock.h>

Reviewed-by: Bart Van Assche <[email protected]>
Signed-off-by: Stanley Chu <[email protected]>
---
drivers/ufs/host/ufs-mediatek.c | 1 -
1 file changed, 1 deletion(-)

diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c
index c958279bdd8f..ff6fd8f52ebc 100644
--- a/drivers/ufs/host/ufs-mediatek.c
+++ b/drivers/ufs/host/ufs-mediatek.c
@@ -19,7 +19,6 @@
#include <linux/pm_qos.h>
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
-#include <linux/sched/clock.h>
#include <linux/soc/mediatek/mtk_sip_svc.h>

#include <ufs/ufshcd.h>
--
2.18.0


2022-08-02 18:49:47

by Bart Van Assche

[permalink] [raw]
Subject: Re: [PATCH v4 5/5] scsi: ufs: ufs-medaitek: Support clk-scaling to optimize power consumption

On 8/2/22 06:54, Stanley Chu wrote:
>

There is a typo in the subject of this patch: I think that ufs-medaitek
should be changed into ufs-mediatek.

Thanks,

Bart.

2022-08-03 00:16:03

by Stanley Jhu

[permalink] [raw]
Subject: Re: [PATCH v4 5/5] scsi: ufs: ufs-medaitek: Support clk-scaling to optimize power consumption

Hi Bart,

On Wed, Aug 3, 2022 at 2:48 AM Bart Van Assche <[email protected]> wrote:
>
> On 8/2/22 06:54, Stanley Chu wrote:
> >
>
> There is a typo in the subject of this patch: I think that ufs-medaitek
> should be changed into ufs-mediatek.
>

Thanks for the review. Will fix this in the next version.