* [PATCH v3 0/2] Add MCQ support for MTK platform
@ 2023-06-10 8:33 Po-Wen Kao
2023-06-10 8:33 ` [PATCH v3 1/2] scsi: ufs: core: Export symbols for MTK driver module Po-Wen Kao
2023-06-10 8:33 ` [PATCH v3 2/2] scsi: ufs: ufs-mediatek: Add MCQ support for MTK platform Po-Wen Kao
0 siblings, 2 replies; 6+ messages in thread
From: Po-Wen Kao @ 2023-06-10 8:33 UTC (permalink / raw)
To: linux-scsi, linux-kernel, linux-arm-kernel, linux-mediatek,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: wsd_upstream, peter.wang, stanley.chu, powen.kao, alice.chao,
naomi.chu, chun-hung.wu, cc.chou, eddie.huang
v2 -> v3
- Drop SQ to CQ mapping vops introduced in v2
- Refactor commit message
- Update export symbols
v1 -> v2
- Introduce MCQ SQ to CQ mapping vops and provide MTK implementation.
- Update export symbol patch
v1
- Separated from topic "[PATCH v4 0/5] Several UFS MCQ Code Changes".
Here are some changes since last upload
- Store irq in per host array
- Symbol rename
- Use ufshcd_mcq_poll_cqe_lock() instead of ufshcd_mcq_poll_cqe_nolock()
- Handle invalid irq dts property
- Remove ufshcd_disable_intr(hba, MCQ_CQ_EVENT_STATUS) in MCQ mode.
This will become host quirk later.
Po-Wen Kao (2):
scsi: ufs: core: Export symbols for MTK driver module
scsi: ufs: ufs-mediatek: Add MCQ support for MTK platform
drivers/ufs/core/ufs-mcq.c | 3 +
drivers/ufs/core/ufshcd-priv.h | 2 -
drivers/ufs/host/ufs-mediatek.c | 174 +++++++++++++++++++++++++++++++-
drivers/ufs/host/ufs-mediatek.h | 33 ++++++
include/ufs/ufshcd.h | 3 +
5 files changed, 211 insertions(+), 4 deletions(-)
--
2.18.0
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH v3 1/2] scsi: ufs: core: Export symbols for MTK driver module 2023-06-10 8:33 [PATCH v3 0/2] Add MCQ support for MTK platform Po-Wen Kao @ 2023-06-10 8:33 ` Po-Wen Kao 2023-06-12 9:19 ` AngeloGioacchino Del Regno 2023-06-10 8:33 ` [PATCH v3 2/2] scsi: ufs: ufs-mediatek: Add MCQ support for MTK platform Po-Wen Kao 1 sibling, 1 reply; 6+ messages in thread From: Po-Wen Kao @ 2023-06-10 8:33 UTC (permalink / raw) To: linux-scsi, linux-kernel, linux-arm-kernel, linux-mediatek, Alim Akhtar, Avri Altman, Bart Van Assche, James E.J. Bottomley, Martin K. Petersen, Matthias Brugger, AngeloGioacchino Del Regno Cc: wsd_upstream, peter.wang, stanley.chu, powen.kao, alice.chao, naomi.chu, chun-hung.wu, cc.chou, eddie.huang Export symbols for MediaTek UFS driver's PM flow and irq handler. Signed-off-by: Po-Wen Kao <powen.kao@mediatek.com> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Stanley Chu <stanley.chu@mediatek.com> --- drivers/ufs/core/ufs-mcq.c | 3 +++ drivers/ufs/core/ufshcd-priv.h | 2 -- include/ufs/ufshcd.h | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c index 785fc9762cad..63c2a4bdbb4a 100644 --- a/drivers/ufs/core/ufs-mcq.c +++ b/drivers/ufs/core/ufs-mcq.c @@ -99,6 +99,7 @@ void ufshcd_mcq_config_mac(struct ufs_hba *hba, u32 max_active_cmds) val |= FIELD_PREP(MCQ_CFG_MAC_MASK, max_active_cmds); ufshcd_writel(hba, val, REG_UFS_MCQ_CFG); } +EXPORT_SYMBOL_GPL(ufshcd_mcq_config_mac); /** * ufshcd_mcq_req_to_hwq - find the hardware queue on which the @@ -249,6 +250,7 @@ u32 ufshcd_mcq_read_cqis(struct ufs_hba *hba, int i) { return readl(mcq_opr_base(hba, OPR_CQIS, i) + REG_CQIS); } +EXPORT_SYMBOL_GPL(ufshcd_mcq_read_cqis); void ufshcd_mcq_write_cqis(struct ufs_hba *hba, u32 val, int i) { @@ -392,6 +394,7 @@ void ufshcd_mcq_make_queues_operational(struct ufs_hba *hba) MCQ_CFG_n(REG_SQATTR, i)); } } +EXPORT_SYMBOL_GPL(ufshcd_mcq_make_queues_operational); void ufshcd_mcq_enable_esi(struct ufs_hba *hba) { diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h index aa88e60ea1f6..4dee397513d2 100644 --- a/drivers/ufs/core/ufshcd-priv.h +++ b/drivers/ufs/core/ufshcd-priv.h @@ -66,8 +66,6 @@ void ufshcd_compl_one_cqe(struct ufs_hba *hba, int task_tag, int ufshcd_mcq_init(struct ufs_hba *hba); int ufshcd_mcq_decide_queue_depth(struct ufs_hba *hba); int ufshcd_mcq_memory_alloc(struct ufs_hba *hba); -void ufshcd_mcq_make_queues_operational(struct ufs_hba *hba); -void ufshcd_mcq_config_mac(struct ufs_hba *hba, u32 max_active_cmds); void ufshcd_mcq_select_mcq_mode(struct ufs_hba *hba); u32 ufshcd_mcq_read_cqis(struct ufs_hba *hba, int i); void ufshcd_mcq_write_cqis(struct ufs_hba *hba, u32 val, int i); diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index 9b2d1859f885..871985073a8e 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -1242,9 +1242,12 @@ void ufshcd_parse_dev_ref_clk_freq(struct ufs_hba *hba, struct clk *refclk); void ufshcd_update_evt_hist(struct ufs_hba *hba, u32 id, u32 val); void ufshcd_hba_stop(struct ufs_hba *hba); void ufshcd_schedule_eh_work(struct ufs_hba *hba); +void ufshcd_mcq_config_mac(struct ufs_hba *hba, u32 max_active_cmds); +u32 ufshcd_mcq_read_cqis(struct ufs_hba *hba, int i); void ufshcd_mcq_write_cqis(struct ufs_hba *hba, u32 val, int i); unsigned long ufshcd_mcq_poll_cqe_lock(struct ufs_hba *hba, struct ufs_hw_queue *hwq); +void ufshcd_mcq_make_queues_operational(struct ufs_hba *hba); void ufshcd_mcq_enable_esi(struct ufs_hba *hba); void ufshcd_mcq_config_esi(struct ufs_hba *hba, struct msi_msg *msg); -- 2.18.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 1/2] scsi: ufs: core: Export symbols for MTK driver module 2023-06-10 8:33 ` [PATCH v3 1/2] scsi: ufs: core: Export symbols for MTK driver module Po-Wen Kao @ 2023-06-12 9:19 ` AngeloGioacchino Del Regno 0 siblings, 0 replies; 6+ messages in thread From: AngeloGioacchino Del Regno @ 2023-06-12 9:19 UTC (permalink / raw) To: Po-Wen Kao, linux-scsi, linux-kernel, linux-arm-kernel, linux-mediatek, Alim Akhtar, Avri Altman, Bart Van Assche, James E.J. Bottomley, Martin K. Petersen, Matthias Brugger Cc: wsd_upstream, peter.wang, stanley.chu, alice.chao, naomi.chu, chun-hung.wu, cc.chou, eddie.huang Il 10/06/23 10:33, Po-Wen Kao ha scritto: > Export symbols for MediaTek UFS driver's PM flow and irq handler. > > Signed-off-by: Po-Wen Kao <powen.kao@mediatek.com> > Reviewed-by: Bart Van Assche <bvanassche@acm.org> > Reviewed-by: Stanley Chu <stanley.chu@mediatek.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v3 2/2] scsi: ufs: ufs-mediatek: Add MCQ support for MTK platform 2023-06-10 8:33 [PATCH v3 0/2] Add MCQ support for MTK platform Po-Wen Kao 2023-06-10 8:33 ` [PATCH v3 1/2] scsi: ufs: core: Export symbols for MTK driver module Po-Wen Kao @ 2023-06-10 8:33 ` Po-Wen Kao 2023-06-11 13:54 ` Bart Van Assche 2023-06-12 9:19 ` AngeloGioacchino Del Regno 1 sibling, 2 replies; 6+ messages in thread From: Po-Wen Kao @ 2023-06-10 8:33 UTC (permalink / raw) To: linux-scsi, linux-kernel, linux-arm-kernel, linux-mediatek, Stanley Chu, James E.J. Bottomley, Martin K. Petersen, Matthias Brugger, AngeloGioacchino Del Regno Cc: wsd_upstream, peter.wang, powen.kao, alice.chao, naomi.chu, chun-hung.wu, cc.chou, eddie.huang Add UFS MCQ vops and irq handler for MediaTek platform. PM flow is fixed accordingly. Signed-off-by: Po-Wen Kao <powen.kao@mediatek.com> Reviewed-by: Stanley Chu <stanley.chu@mediatek.com> --- drivers/ufs/host/ufs-mediatek.c | 174 +++++++++++++++++++++++++++++++- drivers/ufs/host/ufs-mediatek.h | 33 ++++++ 2 files changed, 205 insertions(+), 2 deletions(-) diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c index 33b301649757..662b06e285c6 100644 --- a/drivers/ufs/host/ufs-mediatek.c +++ b/drivers/ufs/host/ufs-mediatek.c @@ -27,8 +27,14 @@ #include <ufs/unipro.h> #include "ufs-mediatek.h" +static int ufs_mtk_config_mcq(struct ufs_hba *hba, bool irq); + #define CREATE_TRACE_POINTS #include "ufs-mediatek-trace.h" +#undef CREATE_TRACE_POINTS + +#define MAX_SUPP_MAC 64 +#define MCQ_QUEUE_OFFSET(c) ((((c) >> 16) & 0xFF) * 0x200) static const struct ufs_dev_quirk ufs_mtk_dev_fixups[] = { { .wmanufacturerid = UFS_ANY_VENDOR, @@ -840,6 +846,37 @@ static void ufs_mtk_vreg_fix_vccqx(struct ufs_hba *hba) } } +static void ufs_mtk_init_mcq_irq(struct ufs_hba *hba) +{ + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + struct platform_device *pdev; + int i; + int irq; + + host->mcq_nr_intr = UFSHCD_MAX_Q_NR; + pdev = container_of(hba->dev, struct platform_device, dev); + + /* invalidate irq info */ + for (i = 0; i < host->mcq_nr_intr; i++) + host->mcq_intr_info[i].irq = MTK_MCQ_INVALID_IRQ; + + for (i = 0; i < host->mcq_nr_intr; i++) { + /* irq index 0 is legacy irq, sq/cq irq start from index 1 */ + irq = platform_get_irq(pdev, i + 1); + if (irq < 0) { + dev_err(hba->dev, "get platform mcq irq fail: %d\n", i); + goto failed; + } + host->mcq_intr_info[i].hba = hba; + host->mcq_intr_info[i].irq = irq; + dev_info(hba->dev, "get platform mcq irq: %d, %d\n", i, irq); + } + + return; +failed: + host->mcq_nr_intr = 0; +} + /** * ufs_mtk_init - find other essential mmio bases * @hba: host controller instance @@ -876,6 +913,8 @@ static int ufs_mtk_init(struct ufs_hba *hba) /* Initialize host capability */ ufs_mtk_init_host_caps(hba); + ufs_mtk_init_mcq_irq(hba); + err = ufs_mtk_bind_mphy(hba); if (err) goto out_variant_clear; @@ -1171,7 +1210,16 @@ static int ufs_mtk_link_set_hpm(struct ufs_hba *hba) else return err; - err = ufshcd_make_hba_operational(hba); + if (!hba->mcq_enabled) { + err = ufshcd_make_hba_operational(hba); + } else { + ufs_mtk_config_mcq(hba, false); + ufshcd_mcq_make_queues_operational(hba); + ufshcd_mcq_config_mac(hba, hba->nutrs); + ufshcd_writel(hba, ufshcd_readl(hba, REG_UFS_MEM_CFG) | 0x1, + REG_UFS_MEM_CFG); + } + if (err) return err; @@ -1495,6 +1543,123 @@ static int ufs_mtk_clk_scale_notify(struct ufs_hba *hba, bool scale_up, return 0; } +static int ufs_mtk_get_hba_mac(struct ufs_hba *hba) +{ + return MAX_SUPP_MAC; +} + +static int ufs_mtk_op_runtime_config(struct ufs_hba *hba) +{ + struct ufshcd_mcq_opr_info_t *opr; + int i; + + for (i = 0; i < OPR_MAX; i++) { + opr = &hba->mcq_opr[i]; + opr->stride = REG_UFS_MCQ_STRIDE; + } + + hba->mcq_opr[OPR_SQD].offset = REG_UFS_MTK_SQD; + hba->mcq_opr[OPR_SQIS].offset = REG_UFS_MTK_SQIS; + hba->mcq_opr[OPR_CQD].offset = REG_UFS_MTK_CQD; + hba->mcq_opr[OPR_CQIS].offset = REG_UFS_MTK_CQIS; + + hba->mcq_opr[OPR_SQD].base = hba->mmio_base + REG_UFS_MTK_SQD; + hba->mcq_opr[OPR_SQIS].base = hba->mmio_base + REG_UFS_MTK_SQIS; + hba->mcq_opr[OPR_CQD].base = hba->mmio_base + REG_UFS_MTK_CQD; + hba->mcq_opr[OPR_CQIS].base = hba->mmio_base + REG_UFS_MTK_CQIS; + + return 0; +} + +static int ufs_mtk_mcq_config_resource(struct ufs_hba *hba) +{ + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + + /* fail mcq initialization if interrupt is not filled properly */ + if (!host->mcq_nr_intr) { + dev_info(hba->dev, "IRQs not ready. MCQ disabled."); + return -EINVAL; + } + + hba->mcq_base = hba->mmio_base + MCQ_QUEUE_OFFSET(hba->mcq_capabilities); + return 0; +} + +static irqreturn_t ufs_mtk_mcq_intr(int irq, void *__intr_info) +{ + struct ufs_mtk_mcq_intr_info *mcq_intr_info = __intr_info; + struct ufs_hba *hba = mcq_intr_info->hba; + struct ufs_hw_queue *hwq; + u32 events; + int i = mcq_intr_info->qid; + + hwq = &hba->uhq[i]; + + events = ufshcd_mcq_read_cqis(hba, i); + if (events) + ufshcd_mcq_write_cqis(hba, events, i); + + if (events & UFSHCD_MCQ_CQIS_TAIL_ENT_PUSH_STS) + ufshcd_mcq_poll_cqe_lock(hba, hwq); + + return IRQ_HANDLED; +} + +static int ufs_mtk_config_mcq_irq(struct ufs_hba *hba) +{ + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + u32 irq, i; + int ret; + + for (i = 0; i < host->mcq_nr_intr; i++) { + irq = host->mcq_intr_info[i].irq; + if (irq == MTK_MCQ_INVALID_IRQ) { + dev_err(hba->dev, "invalid irq. %d\n", i); + return -ENOPARAM; + } + + host->mcq_intr_info[i].qid = i; + ret = devm_request_irq(hba->dev, irq, ufs_mtk_mcq_intr, 0, UFSHCD, + &host->mcq_intr_info[i]); + + dev_info(hba->dev, "request irq %d intr %s\n", irq, ret ? "failed" : ""); + + if (ret) + return ret; + } + + return 0; +} + +static int ufs_mtk_config_mcq(struct ufs_hba *hba, bool irq) +{ + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + int ret = 0; + + if (!host->mcq_set_intr) { + /* Disable irq option register */ + ufshcd_rmwl(hba, MCQ_INTR_EN_MSK, 0, REG_UFS_MMIO_OPT_CTRL_0); + + if (irq) + ret = ufs_mtk_config_mcq_irq(hba); + + if (ret) + return ret; + + host->mcq_set_intr = true; + } + + ufshcd_rmwl(hba, MCQ_AH8, MCQ_AH8, REG_UFS_MMIO_OPT_CTRL_0); + ufshcd_rmwl(hba, MCQ_INTR_EN_MSK, MCQ_MULTI_INTR_EN, REG_UFS_MMIO_OPT_CTRL_0); + + return 0; +} + +static int ufs_mtk_config_esi(struct ufs_hba *hba) +{ + return ufs_mtk_config_mcq(hba, true); +} + /* * struct ufs_hba_mtk_vops - UFS MTK specific variant operations * @@ -1518,6 +1683,11 @@ static const struct ufs_hba_variant_ops ufs_hba_mtk_vops = { .event_notify = ufs_mtk_event_notify, .config_scaling_param = ufs_mtk_config_scaling_param, .clk_scale_notify = ufs_mtk_clk_scale_notify, + /* mcq vops */ + .get_hba_mac = ufs_mtk_get_hba_mac, + .op_runtime_config = ufs_mtk_op_runtime_config, + .mcq_config_resource = ufs_mtk_mcq_config_resource, + .config_esi = ufs_mtk_config_esi, }; /** @@ -1564,7 +1734,7 @@ static int ufs_mtk_probe(struct platform_device *pdev) out: if (err) - dev_info(dev, "probe failed %d\n", err); + dev_err(dev, "probe failed %d\n", err); of_node_put(reset_node); return err; diff --git a/drivers/ufs/host/ufs-mediatek.h b/drivers/ufs/host/ufs-mediatek.h index 2fc6d7b87694..6e41550e1830 100644 --- a/drivers/ufs/host/ufs-mediatek.h +++ b/drivers/ufs/host/ufs-mediatek.h @@ -10,11 +10,27 @@ #include <linux/pm_qos.h> #include <linux/soc/mediatek/mtk_sip_svc.h> +/* + * MCQ define and struct + */ +#define UFSHCD_MAX_Q_NR 8 +#define MTK_MCQ_INVALID_IRQ 0xFFFF + +/* REG_UFS_MMIO_OPT_CTRL_0 160h */ +#define EHS_EN 0x1 +#define PFM_IMPV 0x2 +#define MCQ_MULTI_INTR_EN 0x4 +#define MCQ_CMB_INTR_EN 0x8 +#define MCQ_AH8 0x10 + +#define MCQ_INTR_EN_MSK (MCQ_MULTI_INTR_EN | MCQ_CMB_INTR_EN) + /* * Vendor specific UFSHCI Registers */ #define REG_UFS_XOUFS_CTRL 0x140 #define REG_UFS_REFCLK_CTRL 0x144 +#define REG_UFS_MMIO_OPT_CTRL_0 0x160 #define REG_UFS_EXTREG 0x2100 #define REG_UFS_MPHYCTRL 0x2200 #define REG_UFS_MTK_IP_VER 0x2240 @@ -26,6 +42,13 @@ #define REG_UFS_DEBUG_SEL_B2 0x22D8 #define REG_UFS_DEBUG_SEL_B3 0x22DC +#define REG_UFS_MTK_SQD 0x2800 +#define REG_UFS_MTK_SQIS 0x2814 +#define REG_UFS_MTK_CQD 0x281C +#define REG_UFS_MTK_CQIS 0x2824 + +#define REG_UFS_MCQ_STRIDE 0x30 + /* * Ref-clk control * @@ -136,6 +159,12 @@ struct ufs_mtk_hw_ver { u8 major; }; +struct ufs_mtk_mcq_intr_info { + struct ufs_hba *hba; + u32 irq; + u8 qid; +}; + struct ufs_mtk_host { struct phy *mphy; struct pm_qos_request pm_qos_req; @@ -155,6 +184,10 @@ struct ufs_mtk_host { u16 ref_clk_ungating_wait_us; u16 ref_clk_gating_wait_us; u32 ip_ver; + + bool mcq_set_intr; + int mcq_nr_intr; + struct ufs_mtk_mcq_intr_info mcq_intr_info[UFSHCD_MAX_Q_NR]; }; /* -- 2.18.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 2/2] scsi: ufs: ufs-mediatek: Add MCQ support for MTK platform 2023-06-10 8:33 ` [PATCH v3 2/2] scsi: ufs: ufs-mediatek: Add MCQ support for MTK platform Po-Wen Kao @ 2023-06-11 13:54 ` Bart Van Assche 2023-06-12 9:19 ` AngeloGioacchino Del Regno 1 sibling, 0 replies; 6+ messages in thread From: Bart Van Assche @ 2023-06-11 13:54 UTC (permalink / raw) To: Po-Wen Kao, linux-scsi, linux-kernel, linux-arm-kernel, linux-mediatek, Stanley Chu, James E.J. Bottomley, Martin K. Petersen, Matthias Brugger, AngeloGioacchino Del Regno Cc: wsd_upstream, peter.wang, alice.chao, naomi.chu, chun-hung.wu, cc.chou, eddie.huang On 6/10/23 01:33, Po-Wen Kao wrote: > Add UFS MCQ vops and irq handler for MediaTek platform. > PM flow is fixed accordingly. Reviewed-by: Bart Van Assche <bvanassche@acm.org> ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 2/2] scsi: ufs: ufs-mediatek: Add MCQ support for MTK platform 2023-06-10 8:33 ` [PATCH v3 2/2] scsi: ufs: ufs-mediatek: Add MCQ support for MTK platform Po-Wen Kao 2023-06-11 13:54 ` Bart Van Assche @ 2023-06-12 9:19 ` AngeloGioacchino Del Regno 1 sibling, 0 replies; 6+ messages in thread From: AngeloGioacchino Del Regno @ 2023-06-12 9:19 UTC (permalink / raw) To: Po-Wen Kao, linux-scsi, linux-kernel, linux-arm-kernel, linux-mediatek, Stanley Chu, James E.J. Bottomley, Martin K. Petersen, Matthias Brugger Cc: wsd_upstream, peter.wang, alice.chao, naomi.chu, chun-hung.wu, cc.chou, eddie.huang Il 10/06/23 10:33, Po-Wen Kao ha scritto: > Add UFS MCQ vops and irq handler for MediaTek platform. > PM flow is fixed accordingly. > > Signed-off-by: Po-Wen Kao <powen.kao@mediatek.com> > Reviewed-by: Stanley Chu <stanley.chu@mediatek.com> > --- > drivers/ufs/host/ufs-mediatek.c | 174 +++++++++++++++++++++++++++++++- > drivers/ufs/host/ufs-mediatek.h | 33 ++++++ > 2 files changed, 205 insertions(+), 2 deletions(-) > > diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c > index 33b301649757..662b06e285c6 100644 > --- a/drivers/ufs/host/ufs-mediatek.c > +++ b/drivers/ufs/host/ufs-mediatek.c > @@ -27,8 +27,14 @@ > #include <ufs/unipro.h> > #include "ufs-mediatek.h" > > +static int ufs_mtk_config_mcq(struct ufs_hba *hba, bool irq); > + > #define CREATE_TRACE_POINTS > #include "ufs-mediatek-trace.h" > +#undef CREATE_TRACE_POINTS > + > +#define MAX_SUPP_MAC 64 > +#define MCQ_QUEUE_OFFSET(c) ((((c) >> 16) & 0xFF) * 0x200) > > static const struct ufs_dev_quirk ufs_mtk_dev_fixups[] = { > { .wmanufacturerid = UFS_ANY_VENDOR, > @@ -840,6 +846,37 @@ static void ufs_mtk_vreg_fix_vccqx(struct ufs_hba *hba) > } > } > > +static void ufs_mtk_init_mcq_irq(struct ufs_hba *hba) > +{ > + struct ufs_mtk_host *host = ufshcd_get_variant(hba); > + struct platform_device *pdev; > + int i; > + int irq; > + > + host->mcq_nr_intr = UFSHCD_MAX_Q_NR; > + pdev = container_of(hba->dev, struct platform_device, dev); > + > + /* invalidate irq info */ > + for (i = 0; i < host->mcq_nr_intr; i++) > + host->mcq_intr_info[i].irq = MTK_MCQ_INVALID_IRQ; You can avoid double-writing by moving this one... > + > + for (i = 0; i < host->mcq_nr_intr; i++) { > + /* irq index 0 is legacy irq, sq/cq irq start from index 1 */ > + irq = platform_get_irq(pdev, i + 1); > + if (irq < 0) { > + dev_err(hba->dev, "get platform mcq irq fail: %d\n", i); > + goto failed; > + } > + host->mcq_intr_info[i].hba = hba; > + host->mcq_intr_info[i].irq = irq; > + dev_info(hba->dev, "get platform mcq irq: %d, %d\n", i, irq); > + } > + > + return; > +failed: ...here > + host->mcq_nr_intr = 0; > +} > + > /** > * ufs_mtk_init - find other essential mmio bases > * @hba: host controller instance > @@ -876,6 +913,8 @@ static int ufs_mtk_init(struct ufs_hba *hba) > /* Initialize host capability */ > ufs_mtk_init_host_caps(hba); > > + ufs_mtk_init_mcq_irq(hba); > + > err = ufs_mtk_bind_mphy(hba); > if (err) > goto out_variant_clear; > @@ -1171,7 +1210,16 @@ static int ufs_mtk_link_set_hpm(struct ufs_hba *hba) > else > return err; > > - err = ufshcd_make_hba_operational(hba); > + if (!hba->mcq_enabled) { > + err = ufshcd_make_hba_operational(hba); > + } else { > + ufs_mtk_config_mcq(hba, false); > + ufshcd_mcq_make_queues_operational(hba); > + ufshcd_mcq_config_mac(hba, hba->nutrs); > + ufshcd_writel(hba, ufshcd_readl(hba, REG_UFS_MEM_CFG) | 0x1, What is that 0x1? Please add a definition for it. > + REG_UFS_MEM_CFG); > + } > + > if (err) > return err; > > @@ -1495,6 +1543,123 @@ static int ufs_mtk_clk_scale_notify(struct ufs_hba *hba, bool scale_up, > return 0; > } > > +static int ufs_mtk_get_hba_mac(struct ufs_hba *hba) > +{ > + return MAX_SUPP_MAC; > +} > + > +static int ufs_mtk_op_runtime_config(struct ufs_hba *hba) > +{ > + struct ufshcd_mcq_opr_info_t *opr; > + int i; > + > + for (i = 0; i < OPR_MAX; i++) { > + opr = &hba->mcq_opr[i]; > + opr->stride = REG_UFS_MCQ_STRIDE; > + } > + > + hba->mcq_opr[OPR_SQD].offset = REG_UFS_MTK_SQD; > + hba->mcq_opr[OPR_SQIS].offset = REG_UFS_MTK_SQIS; > + hba->mcq_opr[OPR_CQD].offset = REG_UFS_MTK_CQD; > + hba->mcq_opr[OPR_CQIS].offset = REG_UFS_MTK_CQIS; If you move offset init before the for loop, you could do... for (i = 0; i < OPR_MAX; i++) { opr = &hba->mcq_opr[i]; opr->stride = REG_UFS_MCQ_STRIDE; opr->base = hba->mmio_base + opr->offset; } > + > + hba->mcq_opr[OPR_SQD].base = hba->mmio_base + REG_UFS_MTK_SQD; > + hba->mcq_opr[OPR_SQIS].base = hba->mmio_base + REG_UFS_MTK_SQIS; > + hba->mcq_opr[OPR_CQD].base = hba->mmio_base + REG_UFS_MTK_CQD; > + hba->mcq_opr[OPR_CQIS].base = hba->mmio_base + REG_UFS_MTK_CQIS; > + > + return 0; > +} > + > +static int ufs_mtk_mcq_config_resource(struct ufs_hba *hba) > +{ > + struct ufs_mtk_host *host = ufshcd_get_variant(hba); > + > + /* fail mcq initialization if interrupt is not filled properly */ > + if (!host->mcq_nr_intr) { > + dev_info(hba->dev, "IRQs not ready. MCQ disabled."); > + return -EINVAL; > + } > + > + hba->mcq_base = hba->mmio_base + MCQ_QUEUE_OFFSET(hba->mcq_capabilities); > + return 0; > +} > + > +static irqreturn_t ufs_mtk_mcq_intr(int irq, void *__intr_info) > +{ > + struct ufs_mtk_mcq_intr_info *mcq_intr_info = __intr_info; > + struct ufs_hba *hba = mcq_intr_info->hba; > + struct ufs_hw_queue *hwq; > + u32 events; > + int i = mcq_intr_info->qid; Renaming this to `int qid` will increase human readability. > + > + hwq = &hba->uhq[i]; > + > + events = ufshcd_mcq_read_cqis(hba, i); > + if (events) > + ufshcd_mcq_write_cqis(hba, events, i); > + > + if (events & UFSHCD_MCQ_CQIS_TAIL_ENT_PUSH_STS) > + ufshcd_mcq_poll_cqe_lock(hba, hwq); > + > + return IRQ_HANDLED; > +} > + > +static int ufs_mtk_config_mcq_irq(struct ufs_hba *hba) > +{ > + struct ufs_mtk_host *host = ufshcd_get_variant(hba); > + u32 irq, i; > + int ret; > + > + for (i = 0; i < host->mcq_nr_intr; i++) { > + irq = host->mcq_intr_info[i].irq; > + if (irq == MTK_MCQ_INVALID_IRQ) { > + dev_err(hba->dev, "invalid irq. %d\n", i); > + return -ENOPARAM; > + } > + > + host->mcq_intr_info[i].qid = i; > + ret = devm_request_irq(hba->dev, irq, ufs_mtk_mcq_intr, 0, UFSHCD, > + &host->mcq_intr_info[i]); > + > + dev_info(hba->dev, "request irq %d intr %s\n", irq, ret ? "failed" : ""); That's too chatty... you can fix that by doing if (ret) { dev_err(hba->dev, "Cannot request irq %d\n", ret); return ret; } > + > + if (ret) > + return ret; > + } > + > + return 0; > +} > + > +static int ufs_mtk_config_mcq(struct ufs_hba *hba, bool irq) > +{ > + struct ufs_mtk_host *host = ufshcd_get_variant(hba); > + int ret = 0; int ret; > + > + if (!host->mcq_set_intr) { > + /* Disable irq option register */ > + ufshcd_rmwl(hba, MCQ_INTR_EN_MSK, 0, REG_UFS_MMIO_OPT_CTRL_0); > + > + if (irq) > + ret = ufs_mtk_config_mcq_irq(hba); > + > + if (ret) > + return ret; if (irq) { ret = ... if (ret) return ret; } > + > + host->mcq_set_intr = true; > + } > + > + ufshcd_rmwl(hba, MCQ_AH8, MCQ_AH8, REG_UFS_MMIO_OPT_CTRL_0); > + ufshcd_rmwl(hba, MCQ_INTR_EN_MSK, MCQ_MULTI_INTR_EN, REG_UFS_MMIO_OPT_CTRL_0); > + > + return 0; > +} > + > +static int ufs_mtk_config_esi(struct ufs_hba *hba) > +{ > + return ufs_mtk_config_mcq(hba, true); > +} > + > /* > * struct ufs_hba_mtk_vops - UFS MTK specific variant operations > * > @@ -1518,6 +1683,11 @@ static const struct ufs_hba_variant_ops ufs_hba_mtk_vops = { > .event_notify = ufs_mtk_event_notify, > .config_scaling_param = ufs_mtk_config_scaling_param, > .clk_scale_notify = ufs_mtk_clk_scale_notify, > + /* mcq vops */ > + .get_hba_mac = ufs_mtk_get_hba_mac, > + .op_runtime_config = ufs_mtk_op_runtime_config, > + .mcq_config_resource = ufs_mtk_mcq_config_resource, > + .config_esi = ufs_mtk_config_esi, > }; > > /** > @@ -1564,7 +1734,7 @@ static int ufs_mtk_probe(struct platform_device *pdev) > > out: > if (err) > - dev_info(dev, "probe failed %d\n", err); > + dev_err(dev, "probe failed %d\n", err); > > of_node_put(reset_node); > return err; > diff --git a/drivers/ufs/host/ufs-mediatek.h b/drivers/ufs/host/ufs-mediatek.h > index 2fc6d7b87694..6e41550e1830 100644 > --- a/drivers/ufs/host/ufs-mediatek.h > +++ b/drivers/ufs/host/ufs-mediatek.h > @@ -10,11 +10,27 @@ > #include <linux/pm_qos.h> > #include <linux/soc/mediatek/mtk_sip_svc.h> > > +/* > + * MCQ define and struct > + */ > +#define UFSHCD_MAX_Q_NR 8 > +#define MTK_MCQ_INVALID_IRQ 0xFFFF > + > +/* REG_UFS_MMIO_OPT_CTRL_0 160h */ > +#define EHS_EN 0x1 > +#define PFM_IMPV 0x2 > +#define MCQ_MULTI_INTR_EN 0x4 > +#define MCQ_CMB_INTR_EN 0x8 > +#define MCQ_AH8 0x10 These really look like being BIT(x), specifically, bits 0, 1, 2, 3, 4. > + > +#define MCQ_INTR_EN_MSK (MCQ_MULTI_INTR_EN | MCQ_CMB_INTR_EN) > + After that, looks fine to me. Regards, Angelo ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2023-06-12 9:26 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2023-06-10 8:33 [PATCH v3 0/2] Add MCQ support for MTK platform Po-Wen Kao 2023-06-10 8:33 ` [PATCH v3 1/2] scsi: ufs: core: Export symbols for MTK driver module Po-Wen Kao 2023-06-12 9:19 ` AngeloGioacchino Del Regno 2023-06-10 8:33 ` [PATCH v3 2/2] scsi: ufs: ufs-mediatek: Add MCQ support for MTK platform Po-Wen Kao 2023-06-11 13:54 ` Bart Van Assche 2023-06-12 9:19 ` AngeloGioacchino Del Regno
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®