Re: [PATCH 3/4] iio: adc: mediatek: SET_LATE_SYSTEM_SLEEP_PM_OPS support
Hi Jonathan: Thanks for the prompt reply, On Sat, 2019-05-18 at 11:35 +0100, Jonathan Cameron wrote: > On Thu, 16 May 2019 16:10:46 +0800 > Chun-Hung Wu wrote: > > > Move suspend/resume to late_suspend and > > early_resume to gurantee users can use auxadc > guarantee > will fix it in next version. > > driver at suspend/resume stage. > No problem with the patch content, but we need a reason why they may > want to do so? Our thermal drivers uses auxadc at suspend/resume stage. In order to avoid auxadc suspended prior to thermal driver, we move auxadc to late_suspend and early_resume. Thanks, Chun-Hung > > Thanks, > > Jonathan > > > > Signed-off-by: Chun-Hung Wu > > --- > > drivers/iio/adc/mt6577_auxadc.c | 7 --- > > 1 file changed, 4 insertions(+), 3 deletions(-) > > > > diff --git a/drivers/iio/adc/mt6577_auxadc.c > > b/drivers/iio/adc/mt6577_auxadc.c > > index e1bdcc0..58d7cb2 100644 > > --- a/drivers/iio/adc/mt6577_auxadc.c > > +++ b/drivers/iio/adc/mt6577_auxadc.c > > @@ -326,9 +326,10 @@ static int mt6577_auxadc_remove(struct platform_device > > *pdev) > > return 0; > > } > > > > -static SIMPLE_DEV_PM_OPS(mt6577_auxadc_pm_ops, > > -mt6577_auxadc_suspend, > > -mt6577_auxadc_resume); > > +static const struct dev_pm_ops mt6577_auxadc_pm_ops = { > > + SET_LATE_SYSTEM_SLEEP_PM_OPS(mt6577_auxadc_suspend, > > +mt6577_auxadc_resume) > > +}; > > > > static const struct of_device_id mt6577_auxadc_of_match[] = { > > { .compatible = "mediatek,mt2701-auxadc", .data = &mt8173_compat}, >
Re: [PATCH 4/4] iio: auxadc: mediatek: change to subsys_initcall
Hi Jonathan, On Sat, 2019-05-18 at 11:36 +0100, Jonathan Cameron wrote: > On Thu, 16 May 2019 16:10:47 +0800 > Chun-Hung Wu wrote: > > > Move auxadc platform_driver_register() from module_init > > to subsys_initcall because auxadc user drivers > > are all moudle drivers, need to gurantee > > auxadc driver ready before module_init. > > > Is it not possible to make them use deferred handling to come > back later if this isn't yet available? > > subsys_initcall often ends up being a more fragile approach. Agreed, I will ask auxadc driver users to add deferred handling instead of moving auxadc platform_driver_register() from module_init to subsys_initcall. Thanks, Chun-hung > > Thanks, > > Jonathan > > > Signed-off-by: Chun-Hung Wu > > --- > > drivers/iio/adc/mt6577_auxadc.c | 14 +- > > 1 file changed, 13 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/iio/adc/mt6577_auxadc.c > > b/drivers/iio/adc/mt6577_auxadc.c > > index 58d7cb2..cb8e3dd 100644 > > --- a/drivers/iio/adc/mt6577_auxadc.c > > +++ b/drivers/iio/adc/mt6577_auxadc.c > > @@ -350,7 +350,19 @@ static int mt6577_auxadc_remove(struct platform_device > > *pdev) > > .probe = mt6577_auxadc_probe, > > .remove = mt6577_auxadc_remove, > > }; > > -module_platform_driver(mt6577_auxadc_driver); > > + > > +static int __init mt6577_auxadc_init(void) > > +{ > > + return platform_driver_register(&mt6577_auxadc_driver); > > +} > > + > > +static void __exit mt6577_auxadc_exit(void) > > +{ > > + platform_driver_unregister(&mt6577_auxadc_driver); > > +} > > + > > +subsys_initcall(mt6577_auxadc_init); > > +module_exit(mt6577_auxadc_exit); > > > > MODULE_AUTHOR("Zhiyong Tao "); > > MODULE_DESCRIPTION("MTK AUXADC Device Driver"); >
Re: [PATCH 1/4] dt-bindings: iio: adc: mediatek: Add document for mt6765
Hi Jonathan, On Sat, 2019-05-18 at 11:33 +0100, Jonathan Cameron wrote: > On Thu, 16 May 2019 16:10:44 +0800 > Chun-Hung Wu wrote: > > > Add compatible node for mt6765 auxadc > > > > Signed-off-by: Chun-Hung Wu > Applied, but in numeric order. There was also another clashing patch > that caused some fuzz. No problem, thanks! regards, Chun-Hung > > thanks, > > Jonathan > > > --- > > Documentation/devicetree/bindings/iio/adc/mt6577_auxadc.txt | 1 + > > 1 file changed, 1 insertion(+) > > > > diff --git a/Documentation/devicetree/bindings/iio/adc/mt6577_auxadc.txt > > b/Documentation/devicetree/bindings/iio/adc/mt6577_auxadc.txt > > index 0df9bef..ab7efab 100644 > > --- a/Documentation/devicetree/bindings/iio/adc/mt6577_auxadc.txt > > +++ b/Documentation/devicetree/bindings/iio/adc/mt6577_auxadc.txt > > @@ -15,6 +15,7 @@ Required properties: > > - "mediatek,mt2712-auxadc": For MT2712 family of SoCs > > - "mediatek,mt7622-auxadc": For MT7622 family of SoCs > > - "mediatek,mt8173-auxadc": For MT8173 family of SoCs > > +- "mediatek,mt6765-auxadc": For MT6765 family of SoCs > >- reg: Address range of the AUXADC unit. > >- clocks: Should contain a clock specifier for each entry in clock-names > >- clock-names: Should contain "main". >
[PATCH v1 1/2] mmc: cqhci: add new cqhci_host_ops pre_enable() and post_disable()
Add pre_enable() and post_disable() for cqhci_host_ops. Add hook functions before cqhci enable and after cqhci disable for platforms need them. Signed-off-by: Chun-Hung Wu --- drivers/mmc/host/cqhci.c |6 ++ drivers/mmc/host/cqhci.h |2 ++ 2 files changed, 8 insertions(+) diff --git a/drivers/mmc/host/cqhci.c b/drivers/mmc/host/cqhci.c index cfa87df..697fe40 100644 --- a/drivers/mmc/host/cqhci.c +++ b/drivers/mmc/host/cqhci.c @@ -376,6 +376,9 @@ static void cqhci_off(struct mmc_host *mmc) else pr_debug("%s: cqhci: CQE off\n", mmc_hostname(mmc)); + if (cq_host->ops->post_disable) + cq_host->ops->post_disable(mmc); + mmc->cqe_on = false; } @@ -580,6 +583,9 @@ static int cqhci_request(struct mmc_host *mmc, struct mmc_request *mrq) __cqhci_enable(cq_host); if (!mmc->cqe_on) { + if (cq_host->ops->pre_enable) + cq_host->ops->pre_enable(mmc); + cqhci_writel(cq_host, 0, CQHCI_CTL); mmc->cqe_on = true; pr_debug("%s: cqhci: CQE on\n", mmc_hostname(mmc)); diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h index 4377001..89bf6ad 100644 --- a/drivers/mmc/host/cqhci.h +++ b/drivers/mmc/host/cqhci.h @@ -206,6 +206,8 @@ struct cqhci_host_ops { void (*disable)(struct mmc_host *mmc, bool recovery); void (*update_dcmd_desc)(struct mmc_host *mmc, struct mmc_request *mrq, u64 *data); + void (*pre_enable)(struct mmc_host *mmc); + void (*post_disable)(struct mmc_host *mmc); }; static inline void cqhci_writel(struct cqhci_host *host, u32 val, int reg) -- 1.7.9.5
[PATCH v1 0/2] mmc: cqhci: Add pre_enable() and post_disable() hook function
This series provides MediaTek cqhci implementations as below: - Add cqhci_host_ops->pre_enable() and cqhci_host_ops->post_disable() - Implement MediaTek's hook functions Chun-Hung Wu (2): mmc: cqhci: add new cqhci_host_ops pre_enable() and post_disable() mmc: mediatek: add pre_enable() and post_disable() hook function drivers/mmc/host/cqhci.c |6 ++ drivers/mmc/host/cqhci.h |2 ++ drivers/mmc/host/mtk-sd.c | 22 ++ 3 files changed, 30 insertions(+) -- 1.7.9.5
[PATCH v1 2/2] mmc: mediatek: add pre_enable() and post_disable() hook function
CQHCI_ENABLE bit in CQHCI_CFG should be disabled after msdc_cqe_disable(), and should be enabled before msdc_ceq_enable() for MTK platform. Add hook functions for cqhci_host_ops->pre_enable() and cqhci_host_ops->post_disable(). Signed-off-by: Chun-Hung Wu --- drivers/mmc/host/mtk-sd.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 4e2583f..f53e11b 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -2282,6 +2282,26 @@ static void msdc_cqe_disable(struct mmc_host *mmc, bool recovery) } } +static void msdc_cqe_pre_enable(struct mmc_host *mmc) +{ + struct cqhci_host *cq_host = mmc->cqe_private; + u32 reg; + + reg = cqhci_readl(cq_host, CQHCI_CFG); + reg |= CQHCI_ENABLE; + cqhci_writel(cq_host, reg, CQHCI_CFG); +} + +static void msdc_cqe_post_disable(struct mmc_host *mmc) +{ + struct cqhci_host *cq_host = mmc->cqe_private; + u32 reg; + + reg = cqhci_readl(cq_host, CQHCI_CFG); + reg &= ~CQHCI_ENABLE; + cqhci_writel(cq_host, reg, CQHCI_CFG); +} + static const struct mmc_host_ops mt_msdc_ops = { .post_req = msdc_post_req, .pre_req = msdc_pre_req, @@ -2301,6 +2321,8 @@ static void msdc_cqe_disable(struct mmc_host *mmc, bool recovery) static const struct cqhci_host_ops msdc_cmdq_ops = { .enable = msdc_cqe_enable, .disable= msdc_cqe_disable, + .pre_enable = msdc_cqe_pre_enable, + .post_disable = msdc_cqe_post_disable, }; static void msdc_of_property_parse(struct platform_device *pdev, -- 1.7.9.5
[PATCH v7 4/4] dt-bindings: mmc: mediatek: Add document for mt6779
Add compatible node for mt6779 mmc. Signed-off-by: Chun-Hung Wu --- Documentation/devicetree/bindings/mmc/mtk-sd.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.txt b/Documentation/devicetree/bindings/mmc/mtk-sd.txt index 8a532f4..0c9cf6a 100644 --- a/Documentation/devicetree/bindings/mmc/mtk-sd.txt +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.txt @@ -12,6 +12,7 @@ Required properties: "mediatek,mt8173-mmc": for mmc host ip compatible with mt8173 "mediatek,mt8183-mmc": for mmc host ip compatible with mt8183 "mediatek,mt8516-mmc": for mmc host ip compatible with mt8516 + "mediatek,mt6779-mmc": for mmc host ip compatible with mt6779 "mediatek,mt2701-mmc": for mmc host ip compatible with mt2701 "mediatek,mt2712-mmc": for mmc host ip compatible with mt2712 "mediatek,mt7622-mmc": for MT7622 SoC -- 1.9.1
[PATCH v7 1/4] mmc: mediatek: add MT6779 MMC driver support
Add new code to support MT6779 mmc driver. Signed-off-by: Chun-Hung Wu --- drivers/mmc/host/mtk-sd.c | 13 + 1 file changed, 13 insertions(+) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 39e7fc5..ed37a3c 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -538,6 +538,18 @@ struct msdc_host { .use_internal_cd = true, }; +static const struct mtk_mmc_compatible mt6779_compat = { + .clk_div_bits = 12, + .hs400_tune = false, + .pad_tune_reg = MSDC_PAD_TUNE0, + .async_fifo = true, + .data_tune = true, + .busy_check = true, + .stop_clk_fix = true, + .enhance_rx = true, + .support_64g = true, +}; + static const struct of_device_id msdc_of_ids[] = { { .compatible = "mediatek,mt8135-mmc", .data = &mt8135_compat}, { .compatible = "mediatek,mt8173-mmc", .data = &mt8173_compat}, @@ -547,6 +559,7 @@ struct msdc_host { { .compatible = "mediatek,mt7622-mmc", .data = &mt7622_compat}, { .compatible = "mediatek,mt8516-mmc", .data = &mt8516_compat}, { .compatible = "mediatek,mt7620-mmc", .data = &mt7620_compat}, + { .compatible = "mediatek,mt6779-mmc", .data = &mt6779_compat}, {} }; MODULE_DEVICE_TABLE(of, msdc_of_ids); -- 1.9.1
[PATCH v7 0/4] mmc: mediatek: add mmc cqhci support
This series provides MediaTek cqhci implementations as below: - Refine msdc timeout api to reduce redundant code - MediaTek command queue support - dt-bindings for mt6779 v1 -> v2: - Add more patch details in commit message - Separate msdc timeout api refine to individual patch v2 -> v3: - Remove CR-Id, Change-Id and Feature in patches - Add Signed-off-by in patches v3 -> v4: - Refine CQE bindings in mmc_of_parse (Ulf Hansson) - Remove redundant host CQE bindings (Linux Walleij) v4 -> v5: - Add Acked-by and more maintainers v5 -> v6: - Move CQE bindings back to vendor driver - Add mt6779 mmc support as an individual patch - Error handling for cq_host devm_kzallo() v6 -> v7: - Select MMC_CQHCI for MMC_MTK - Remove unnecessary option MMC_CQHCI in mtk-sd.c - Add error handling for cqhci_init() - Use native cqhci dt-bindings 'supports-cqe' Chun-Hung Wu (4): [1/4] mmc: mediatek: add MT6779 MMC driver support [2/4] mmc: mediatek: refine msdc timeout api [3/4] mmc: mediatek: command queue support [4/4] dt-bindings: mmc: mediatek: Add document for mt6779 Documentation/devicetree/bindings/mmc/mtk-sd.txt | 1 + drivers/mmc/host/Kconfig | 1 + drivers/mmc/host/mtk-sd.c| 160 +-- 3 files changed, 152 insertions(+), 10 deletions(-) -- 1.9.1
[PATCH v7 2/4] mmc: mediatek: refine msdc timeout api
Extract msdc timeout api common part to have better code architecture and avoid redundant code. Signed-off-by: Chun-Hung Wu --- drivers/mmc/host/mtk-sd.c | 32 ++-- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index ed37a3c..347ed72 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -723,21 +723,21 @@ static void msdc_unprepare_data(struct msdc_host *host, struct mmc_request *mrq) } } -/* clock control primitives */ -static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks) +static u64 msdc_timeout_cal(struct msdc_host *host, u64 ns, u64 clks) { - u32 timeout, clk_ns; + u64 timeout, clk_ns; u32 mode = 0; - host->timeout_ns = ns; - host->timeout_clks = clks; if (host->mmc->actual_clock == 0) { timeout = 0; } else { - clk_ns = 10UL / host->mmc->actual_clock; - timeout = (ns + clk_ns - 1) / clk_ns + clks; + clk_ns = 10ULL; + do_div(clk_ns, host->mmc->actual_clock); + timeout = ns + clk_ns - 1; + do_div(timeout, clk_ns); + timeout += clks; /* in 1048576 sclk cycle unit */ - timeout = (timeout + (0x1 << 20) - 1) >> 20; + timeout = DIV_ROUND_UP(timeout, (0x1 << 20)); if (host->dev_comp->clk_div_bits == 8) sdr_get_field(host->base + MSDC_CFG, MSDC_CFG_CKMOD, &mode); @@ -747,9 +747,21 @@ static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks) /*DDR mode will double the clk cycles for data timeout */ timeout = mode >= 2 ? timeout * 2 : timeout; timeout = timeout > 1 ? timeout - 1 : 0; - timeout = timeout > 255 ? 255 : timeout; } - sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, timeout); + return timeout; +} + +/* clock control primitives */ +static void msdc_set_timeout(struct msdc_host *host, u64 ns, u64 clks) +{ + u64 timeout; + + host->timeout_ns = ns; + host->timeout_clks = clks; + + timeout = msdc_timeout_cal(host, ns, clks); + sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, + (u32)(timeout > 255 ? 255 : timeout)); } static void msdc_gate_clock(struct msdc_host *host) -- 1.9.1
[PATCH v7 3/4] mmc: mediatek: command queue support
Support command queue for mt6779 platform. a. Add msdc_set_busy_timeout() to calculate emmc write timeout. b. Connect mtk msdc driver to cqhci driver through host->cq_host->ops = &msdc_cmdq_ops; c. msdc_cmdq_irq() will link up with cqchi_irq(). Besides, it provides more irq error messages like RSPCRCERR/CMDTO/DATACRCERR/DATTMO. d. Select kernel config MMC_CQHCI for MMC_MTK Signed-off-by: Chun-Hung Wu --- drivers/mmc/host/Kconfig | 1 + drivers/mmc/host/mtk-sd.c | 115 ++ 2 files changed, 116 insertions(+) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 3b706af..9c89a5b 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -1009,6 +1009,7 @@ config MMC_MTK tristate "MediaTek SD/MMC Card Interface support" depends on HAS_DMA select REGULATOR + select MMC_CQHCI help This selects the MediaTek(R) Secure digital and Multimedia card Interface. If you have a machine with a integrated SD/MMC card reader, say Y or M here. diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 347ed72..e560a06 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -31,6 +31,8 @@ #include #include +#include "cqhci.h" + #define MAX_BD_NUM 1024 /*--*/ @@ -152,6 +154,7 @@ #define MSDC_INT_DMA_BDCSERR(0x1 << 17)/* W1C */ #define MSDC_INT_DMA_GPDCSERR (0x1 << 18)/* W1C */ #define MSDC_INT_DMA_PROTECT(0x1 << 19)/* W1C */ +#define MSDC_INT_CMDQ (0x1 << 28)/* W1C */ /* MSDC_INTEN mask */ #define MSDC_INTEN_MMCIRQ (0x1 << 0) /* RW */ @@ -182,6 +185,7 @@ /* SDC_CFG mask */ #define SDC_CFG_SDIOINTWKUP (0x1 << 0) /* RW */ #define SDC_CFG_INSWKUP (0x1 << 1) /* RW */ +#define SDC_CFG_WRDTOC (0x1fff << 2) /* RW */ #define SDC_CFG_BUSWIDTH(0x3 << 16)/* RW */ #define SDC_CFG_SDIO(0x1 << 19)/* RW */ #define SDC_CFG_SDIOIDE (0x1 << 20)/* RW */ @@ -230,6 +234,7 @@ #define MSDC_PATCH_BIT_DECRCTMO (0x1 << 30) /* RW */ #define MSDC_PATCH_BIT1_CMDTA (0x7 << 3)/* RW */ +#define MSDC_PB1_BUSY_CHECK_SEL (0x1 << 7)/* RW */ #define MSDC_PATCH_BIT1_STOP_DLY (0xf << 8)/* RW */ #define MSDC_PATCH_BIT2_CFGRESP (0x1 << 15) /* RW */ @@ -431,9 +436,11 @@ struct msdc_host { /* cmd response sample selection for HS400 */ bool hs400_mode;/* current eMMC will run at hs400 mode */ bool internal_cd; /* Use internal card-detect logic */ + bool cqhci; /* support eMMC hw cmdq */ struct msdc_save_para save_para; /* used when gate HCLK */ struct msdc_tune_para def_tune_para; /* default tune setting */ struct msdc_tune_para saved_tune_para; /* tune result of CMD21/CMD19 */ + struct cqhci_host *cq_host; }; static const struct mtk_mmc_compatible mt8135_compat = { @@ -764,6 +771,15 @@ static void msdc_set_timeout(struct msdc_host *host, u64 ns, u64 clks) (u32)(timeout > 255 ? 255 : timeout)); } +static void msdc_set_busy_timeout(struct msdc_host *host, u64 ns, u64 clks) +{ + u64 timeout; + + timeout = msdc_timeout_cal(host, ns, clks); + sdr_set_field(host->base + SDC_CFG, SDC_CFG_WRDTOC, + (u32)(timeout > 8191 ? 8191 : timeout)); +} + static void msdc_gate_clock(struct msdc_host *host) { clk_disable_unprepare(host->src_clk_cg); @@ -1481,6 +1497,34 @@ static void msdc_enable_sdio_irq(struct mmc_host *mmc, int enb) pm_runtime_put_noidle(host->dev); } +static irqreturn_t msdc_cmdq_irq(struct msdc_host *host, u32 intsts) +{ + int cmd_err = 0, dat_err = 0; + + if (intsts & MSDC_INT_RSPCRCERR) { + cmd_err = -EILSEQ; + dev_err(host->dev, "%s: CMD CRC ERR", __func__); + } else if (intsts & MSDC_INT_CMDTMO) { + cmd_err = -ETIMEDOUT; + dev_err(host->dev, "%s: CMD TIMEOUT ERR", __func__); + } + + if (intsts & MSDC_INT_DATCRCERR) { + dat_err = -EILSEQ; + dev_err(host->dev, "%s: DATA CRC ERR", __func__); + } else if (intsts & MSDC_INT_DATTMO) { + dat_err = -ETIMEDOUT; + dev_err(host->dev, "%s: DATA TIMEOUT ERR", __func__); + } + + if (cmd_err || dat_err) { + dev_err(host->dev, "cmd_err = %d, dat_err =%d, intsts = 0x%x", + cmd_err, dat_err, intsts); + } + + return cqhci_irq(host->mmc, 0, cmd_err, dat_err); +} + static
Re: [PATCH 3/4] iio: adc: mediatek: SET_LATE_SYSTEM_SLEEP_PM_OPS support
Hi Matthias: Thanks for your suggestion, I think device_links is a good way to make dependency of module's suspend/resume order. Hi Jonathan: Is it ok to keep using late_suspend and early_resume, or do you think it's better to use device_links? Thanks, Chun-Hung On Wed, 2019-05-22 at 18:28 +0200, Matthias Brugger wrote: > > On 20/05/2019 08:03, Chun-Hung Wu wrote: > > Hi Jonathan: > > > > Thanks for the prompt reply, > > > > On Sat, 2019-05-18 at 11:35 +0100, Jonathan Cameron wrote: > >> On Thu, 16 May 2019 16:10:46 +0800 > >> Chun-Hung Wu wrote: > >> > >>> Move suspend/resume to late_suspend and > >>> early_resume to gurantee users can use auxadc > >> guarantee > >> > > will fix it in next version. > >>> driver at suspend/resume stage. > >> No problem with the patch content, but we need a reason why they may > >> want to do so? > > Our thermal drivers uses auxadc at suspend/resume stage. > > In order to avoid auxadc suspended prior to thermal driver, > > we move auxadc to late_suspend and early_resume. > > > > That sounds like a user of device_links [1] to me. > > [1] https://www.kernel.org/doc/html/latest/driver-api/device_link.html > > > Thanks, > > Chun-Hung > >> > >> Thanks, > >> > >> Jonathan > >>> > >>> Signed-off-by: Chun-Hung Wu > >>> --- > >>> drivers/iio/adc/mt6577_auxadc.c | 7 --- > >>> 1 file changed, 4 insertions(+), 3 deletions(-) > >>> > >>> diff --git a/drivers/iio/adc/mt6577_auxadc.c > >>> b/drivers/iio/adc/mt6577_auxadc.c > >>> index e1bdcc0..58d7cb2 100644 > >>> --- a/drivers/iio/adc/mt6577_auxadc.c > >>> +++ b/drivers/iio/adc/mt6577_auxadc.c > >>> @@ -326,9 +326,10 @@ static int mt6577_auxadc_remove(struct > >>> platform_device *pdev) > >>> return 0; > >>> } > >>> > >>> -static SIMPLE_DEV_PM_OPS(mt6577_auxadc_pm_ops, > >>> - mt6577_auxadc_suspend, > >>> - mt6577_auxadc_resume); > >>> +static const struct dev_pm_ops mt6577_auxadc_pm_ops = { > >>> + SET_LATE_SYSTEM_SLEEP_PM_OPS(mt6577_auxadc_suspend, > >>> + mt6577_auxadc_resume) > >>> +}; > >>> > >>> static const struct of_device_id mt6577_auxadc_of_match[] = { > >>> { .compatible = "mediatek,mt2701-auxadc", .data = &mt8173_compat}, > >> > > > >
[PATCH 2/4] iio: adc: mediatek: mt6765 upstream driver
1. Add calibrated sample data support 2. Use of_match_table to decide each platform's feature set Signed-off-by: Chun-Hung Wu --- drivers/iio/adc/mt6577_auxadc.c | 54 +++-- 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/drivers/iio/adc/mt6577_auxadc.c b/drivers/iio/adc/mt6577_auxadc.c index 95d76ab..e1bdcc0 100644 --- a/drivers/iio/adc/mt6577_auxadc.c +++ b/drivers/iio/adc/mt6577_auxadc.c @@ -42,10 +42,26 @@ #define MT6577_AUXADC_POWER_READY_MS 1 #define MT6577_AUXADC_SAMPLE_READY_US 25 +struct mtk_auxadc_compatible { + bool sample_data_cali; + bool check_global_idle; +}; + struct mt6577_auxadc_device { void __iomem *reg_base; struct clk *adc_clk; struct mutex lock; + const struct mtk_auxadc_compatible *dev_comp; +}; + +static const struct mtk_auxadc_compatible mt8173_compat = { + .sample_data_cali = false, + .check_global_idle = true, +}; + +static const struct mtk_auxadc_compatible mt6765_compat = { + .sample_data_cali = true, + .check_global_idle = false, }; #define MT6577_AUXADC_CHANNEL(idx) { \ @@ -74,6 +90,11 @@ struct mt6577_auxadc_device { MT6577_AUXADC_CHANNEL(15), }; +static int mt_auxadc_get_cali_data(int rawdata, bool enable_cali) +{ + return rawdata; +} + static inline void mt6577_auxadc_mod_reg(void __iomem *reg, u32 or_mask, u32 and_mask) { @@ -120,15 +141,17 @@ static int mt6577_auxadc_read(struct iio_dev *indio_dev, /* we must delay here for hardware sample channel data */ udelay(MT6577_AUXADC_SAMPLE_READY_US); - /* check MTK_AUXADC_CON2 if auxadc is idle */ - ret = readl_poll_timeout(adc_dev->reg_base + MT6577_AUXADC_CON2, val, -((val & MT6577_AUXADC_STA) == 0), -MT6577_AUXADC_SLEEP_US, -MT6577_AUXADC_TIMEOUT_US); - if (ret < 0) { - dev_err(indio_dev->dev.parent, - "wait for auxadc idle time out\n"); - goto err_timeout; + if (adc_dev->dev_comp->check_global_idle) { + /* check MTK_AUXADC_CON2 if auxadc is idle */ + ret = readl_poll_timeout(adc_dev->reg_base + MT6577_AUXADC_CON2, +val, ((val & MT6577_AUXADC_STA) == 0), +MT6577_AUXADC_SLEEP_US, +MT6577_AUXADC_TIMEOUT_US); + if (ret < 0) { + dev_err(indio_dev->dev.parent, + "wait for auxadc idle time out\n"); + goto err_timeout; + } } /* read channel and make sure ready bit == 1 */ @@ -163,6 +186,8 @@ static int mt6577_auxadc_read_raw(struct iio_dev *indio_dev, int *val2, long info) { + struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev); + switch (info) { case IIO_CHAN_INFO_PROCESSED: *val = mt6577_auxadc_read(indio_dev, chan); @@ -172,6 +197,8 @@ static int mt6577_auxadc_read_raw(struct iio_dev *indio_dev, chan->channel); return *val; } + if (adc_dev->dev_comp->sample_data_cali) + *val = mt_auxadc_get_cali_data(*val, true); return IIO_VAL_INT; default: @@ -304,10 +331,11 @@ static SIMPLE_DEV_PM_OPS(mt6577_auxadc_pm_ops, mt6577_auxadc_resume); static const struct of_device_id mt6577_auxadc_of_match[] = { - { .compatible = "mediatek,mt2701-auxadc", }, - { .compatible = "mediatek,mt2712-auxadc", }, - { .compatible = "mediatek,mt7622-auxadc", }, - { .compatible = "mediatek,mt8173-auxadc", }, + { .compatible = "mediatek,mt2701-auxadc", .data = &mt8173_compat}, + { .compatible = "mediatek,mt2712-auxadc", .data = &mt8173_compat}, + { .compatible = "mediatek,mt7622-auxadc", .data = &mt8173_compat}, + { .compatible = "mediatek,mt8173-auxadc", .data = &mt8173_compat}, + { .compatible = "mediatek,mt6765-auxadc", .data = &mt6765_compat}, { } }; MODULE_DEVICE_TABLE(of, mt6577_auxadc_of_match); -- 1.9.1
[PATCH 1/4] dt-bindings: iio: adc: mediatek: Add document for mt6765
Add compatible node for mt6765 auxadc Signed-off-by: Chun-Hung Wu --- Documentation/devicetree/bindings/iio/adc/mt6577_auxadc.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/iio/adc/mt6577_auxadc.txt b/Documentation/devicetree/bindings/iio/adc/mt6577_auxadc.txt index 0df9bef..ab7efab 100644 --- a/Documentation/devicetree/bindings/iio/adc/mt6577_auxadc.txt +++ b/Documentation/devicetree/bindings/iio/adc/mt6577_auxadc.txt @@ -15,6 +15,7 @@ Required properties: - "mediatek,mt2712-auxadc": For MT2712 family of SoCs - "mediatek,mt7622-auxadc": For MT7622 family of SoCs - "mediatek,mt8173-auxadc": For MT8173 family of SoCs +- "mediatek,mt6765-auxadc": For MT6765 family of SoCs - reg: Address range of the AUXADC unit. - clocks: Should contain a clock specifier for each entry in clock-names - clock-names: Should contain "main". -- 1.9.1
[PATCH 4/4] iio: auxadc: mediatek: change to subsys_initcall
Move auxadc platform_driver_register() from module_init to subsys_initcall because auxadc user drivers are all moudle drivers, need to gurantee auxadc driver ready before module_init. Signed-off-by: Chun-Hung Wu --- drivers/iio/adc/mt6577_auxadc.c | 14 +- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/mt6577_auxadc.c b/drivers/iio/adc/mt6577_auxadc.c index 58d7cb2..cb8e3dd 100644 --- a/drivers/iio/adc/mt6577_auxadc.c +++ b/drivers/iio/adc/mt6577_auxadc.c @@ -350,7 +350,19 @@ static int mt6577_auxadc_remove(struct platform_device *pdev) .probe = mt6577_auxadc_probe, .remove = mt6577_auxadc_remove, }; -module_platform_driver(mt6577_auxadc_driver); + +static int __init mt6577_auxadc_init(void) +{ + return platform_driver_register(&mt6577_auxadc_driver); +} + +static void __exit mt6577_auxadc_exit(void) +{ + platform_driver_unregister(&mt6577_auxadc_driver); +} + +subsys_initcall(mt6577_auxadc_init); +module_exit(mt6577_auxadc_exit); MODULE_AUTHOR("Zhiyong Tao "); MODULE_DESCRIPTION("MTK AUXADC Device Driver"); -- 1.9.1
[PATCH 0/4] iio: adc: mediatek: add mt6765 driver support
This patch adds support of auxadc to MT6765 SoC. Chun-Hung Wu (4): dt-bindings: iio: adc: mediatek: Add document for mt6765 iio: adc: mediatek: mt6765 upstream driver iio: adc: mediatek: SET_LATE_SYSTEM_SLEEP_PM_OPS support iio: auxadc: mediatek: change to subsys_initcall .../devicetree/bindings/iio/adc/mt6577_auxadc.txt | 1 + drivers/iio/adc/mt6577_auxadc.c| 75 +- 2 files changed, 59 insertions(+), 17 deletions(-) -- 1.9.1
[PATCH 3/4] iio: adc: mediatek: SET_LATE_SYSTEM_SLEEP_PM_OPS support
Move suspend/resume to late_suspend and early_resume to gurantee users can use auxadc driver at suspend/resume stage. Signed-off-by: Chun-Hung Wu --- drivers/iio/adc/mt6577_auxadc.c | 7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/mt6577_auxadc.c b/drivers/iio/adc/mt6577_auxadc.c index e1bdcc0..58d7cb2 100644 --- a/drivers/iio/adc/mt6577_auxadc.c +++ b/drivers/iio/adc/mt6577_auxadc.c @@ -326,9 +326,10 @@ static int mt6577_auxadc_remove(struct platform_device *pdev) return 0; } -static SIMPLE_DEV_PM_OPS(mt6577_auxadc_pm_ops, -mt6577_auxadc_suspend, -mt6577_auxadc_resume); +static const struct dev_pm_ops mt6577_auxadc_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(mt6577_auxadc_suspend, +mt6577_auxadc_resume) +}; static const struct of_device_id mt6577_auxadc_of_match[] = { { .compatible = "mediatek,mt2701-auxadc", .data = &mt8173_compat}, -- 1.9.1
[PATCH v6 2/4] mmc: mediatek: refine msdc timeout api
Extract msdc timeout api common part to have better code architecture and avoid redundant code. Signed-off-by: Chun-Hung Wu --- drivers/mmc/host/mtk-sd.c | 32 ++-- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 8ada675..84a7bd44 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -723,21 +723,21 @@ static void msdc_unprepare_data(struct msdc_host *host, struct mmc_request *mrq) } } -/* clock control primitives */ -static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks) +static u64 msdc_timeout_cal(struct msdc_host *host, u64 ns, u64 clks) { - u32 timeout, clk_ns; + u64 timeout, clk_ns; u32 mode = 0; - host->timeout_ns = ns; - host->timeout_clks = clks; if (host->mmc->actual_clock == 0) { timeout = 0; } else { - clk_ns = 10UL / host->mmc->actual_clock; - timeout = (ns + clk_ns - 1) / clk_ns + clks; + clk_ns = 10ULL; + do_div(clk_ns, host->mmc->actual_clock); + timeout = ns + clk_ns - 1; + do_div(timeout, clk_ns); + timeout += clks; /* in 1048576 sclk cycle unit */ - timeout = (timeout + (0x1 << 20) - 1) >> 20; + timeout = DIV_ROUND_UP(timeout, (0x1 << 20)); if (host->dev_comp->clk_div_bits == 8) sdr_get_field(host->base + MSDC_CFG, MSDC_CFG_CKMOD, &mode); @@ -747,9 +747,21 @@ static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks) /*DDR mode will double the clk cycles for data timeout */ timeout = mode >= 2 ? timeout * 2 : timeout; timeout = timeout > 1 ? timeout - 1 : 0; - timeout = timeout > 255 ? 255 : timeout; } - sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, timeout); + return timeout; +} + +/* clock control primitives */ +static void msdc_set_timeout(struct msdc_host *host, u64 ns, u64 clks) +{ + u64 timeout; + + host->timeout_ns = ns; + host->timeout_clks = clks; + + timeout = msdc_timeout_cal(host, ns, clks); + sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, + (u32)(timeout > 255 ? 255 : timeout)); } static void msdc_gate_clock(struct msdc_host *host) -- 1.9.1
[PATCH v6 0/4] mmc: mediatek: add mmc cqhci support
This series provides MediaTek cqhci implementations as below: - Extend mmc_of_parse() to parse CQE bindings - Remove redundant host CQE bindings - Refine msdc timeout api to reduce redundant code - MediaTek command queue support - dt-bindings for mt6779 v1 -> v2: - Add more patch details in commit message - Separate msdc timeout api refine to individual patch v2 -> v3: - Remove CR-Id, Change-Id and Feature in patches - Add Signed-off-by in patches v3 -> v4: - Refine CQE bindings in mmc_of_parse (Ulf Hansson) - Remove redundant host CQE bindings (Linux Walleij) v4 -> v5: - Add Acked-by and more maintainers v5 -> v6: - Move CQE bindings back to vendor driver - Add mt6779 mmc support as an individual patch - Error handling for cq_host devm_kzallo() Chun-Hung Wu (4): [1/4] mmc: mediatek: add MT6779 MMC driver support [2/4] mmc: mediatek: refine msdc timeout api [3/4] mmc: mediatek: command queue support [4/4] dt-bindings: mmc: mediatek: Add document for mt6779 Documentation/devicetree/bindings/mmc/mtk-sd.txt | 4 + drivers/mmc/host/mtk-sd.c| 164 +-- 2 files changed, 158 insertions(+), 10 deletions(-) -- 1.9.1
[PATCH v6 3/4] mmc: mediatek: command queue support
Support command queue for mt6779 platform. a. Add msdc_set_busy_timeout() to calculate emmc write timeout. b. Connect mtk msdc driver to cqhci driver through host->cq_host->ops = &msdc_cmdq_ops; c. msdc_cmdq_irq() will link up with cqchi_irq(). Besides, it provides more irq error messages like RSPCRCERR/CMDTO/DATACRCERR/DATTMO. d. Use the options below to separate support for CQHCI or not, because some of our platform does not support CQHCI hence no kernel option: CONFIG_MMC_CQHCI. #if IS_ENABLED(CONFIG_MMC_CQHCI) XXX //Support CQHCI #else XXX //Not support CQHCI #endif Signed-off-by: Chun-Hung Wu --- drivers/mmc/host/mtk-sd.c | 119 ++ 1 file changed, 119 insertions(+) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 84a7bd44..9d69269 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -31,6 +31,8 @@ #include #include +#include "cqhci.h" + #define MAX_BD_NUM 1024 /*--*/ @@ -152,6 +154,7 @@ #define MSDC_INT_DMA_BDCSERR(0x1 << 17)/* W1C */ #define MSDC_INT_DMA_GPDCSERR (0x1 << 18)/* W1C */ #define MSDC_INT_DMA_PROTECT(0x1 << 19)/* W1C */ +#define MSDC_INT_CMDQ (0x1 << 28)/* W1C */ /* MSDC_INTEN mask */ #define MSDC_INTEN_MMCIRQ (0x1 << 0) /* RW */ @@ -182,6 +185,7 @@ /* SDC_CFG mask */ #define SDC_CFG_SDIOINTWKUP (0x1 << 0) /* RW */ #define SDC_CFG_INSWKUP (0x1 << 1) /* RW */ +#define SDC_CFG_WRDTOC (0x1fff << 2) /* RW */ #define SDC_CFG_BUSWIDTH(0x3 << 16)/* RW */ #define SDC_CFG_SDIO(0x1 << 19)/* RW */ #define SDC_CFG_SDIOIDE (0x1 << 20)/* RW */ @@ -230,6 +234,7 @@ #define MSDC_PATCH_BIT_DECRCTMO (0x1 << 30) /* RW */ #define MSDC_PATCH_BIT1_CMDTA (0x7 << 3)/* RW */ +#define MSDC_PB1_BUSY_CHECK_SEL (0x1 << 7)/* RW */ #define MSDC_PATCH_BIT1_STOP_DLY (0xf << 8)/* RW */ #define MSDC_PATCH_BIT2_CFGRESP (0x1 << 15) /* RW */ @@ -431,9 +436,11 @@ struct msdc_host { /* cmd response sample selection for HS400 */ bool hs400_mode;/* current eMMC will run at hs400 mode */ bool internal_cd; /* Use internal card-detect logic */ + bool cqhci; /* support eMMC hw cmdq */ struct msdc_save_para save_para; /* used when gate HCLK */ struct msdc_tune_para def_tune_para; /* default tune setting */ struct msdc_tune_para saved_tune_para; /* tune result of CMD21/CMD19 */ + struct cqhci_host *cq_host; }; static const struct mtk_mmc_compatible mt8135_compat = { @@ -764,6 +771,15 @@ static void msdc_set_timeout(struct msdc_host *host, u64 ns, u64 clks) (u32)(timeout > 255 ? 255 : timeout)); } +static void msdc_set_busy_timeout(struct msdc_host *host, u64 ns, u64 clks) +{ + u64 timeout; + + timeout = msdc_timeout_cal(host, ns, clks); + sdr_set_field(host->base + SDC_CFG, SDC_CFG_WRDTOC, + (u32)(timeout > 8191 ? 8191 : timeout)); +} + static void msdc_gate_clock(struct msdc_host *host) { clk_disable_unprepare(host->src_clk_cg); @@ -1480,6 +1496,36 @@ static void msdc_enable_sdio_irq(struct mmc_host *mmc, int enb) pm_runtime_put_noidle(host->dev); } +#if IS_ENABLED(CONFIG_MMC_CQHCI) +static irqreturn_t msdc_cmdq_irq(struct msdc_host *host, u32 intsts) +{ + int cmd_err = 0, dat_err = 0; + + if (intsts & MSDC_INT_RSPCRCERR) { + cmd_err = -EILSEQ; + dev_err(host->dev, "%s: CMD CRC ERR", __func__); + } else if (intsts & MSDC_INT_CMDTMO) { + cmd_err = -ETIMEDOUT; + dev_err(host->dev, "%s: CMD TIMEOUT ERR", __func__); + } + + if (intsts & MSDC_INT_DATCRCERR) { + dat_err = -EILSEQ; + dev_err(host->dev, "%s: DATA CRC ERR", __func__); + } else if (intsts & MSDC_INT_DATTMO) { + dat_err = -ETIMEDOUT; + dev_err(host->dev, "%s: DATA TIMEOUT ERR", __func__); + } + + if (cmd_err || dat_err) { + dev_err(host->dev, "cmd_err = %d, dat_err =%d, intsts = 0x%x", + cmd_err, dat_err, intsts); + } + + return cqhci_irq(host->mmc, 0, cmd_err, dat_err); +} +#endif + static irqreturn_t msdc_irq(int irq, void *dev_id) { struct msdc_host *host = (struct msdc_host *) dev_id; @@ -1516,6 +1562,16 @@ static irqreturn_t msdc_irq(int irq, void *dev_id) if (!(events & (event_mask & ~MSDC_INT_SDIOIRQ))) break; +#if IS_ENAB
[PATCH v6 4/4] dt-bindings: mmc: mediatek: Add document for mt6779
Add compatible node for mt6779 mmc and HW cmdq selection node "mediatek,cqhci". Signed-off-by: Chun-Hung Wu --- Documentation/devicetree/bindings/mmc/mtk-sd.txt | 4 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.txt b/Documentation/devicetree/bindings/mmc/mtk-sd.txt index 8a532f4..d4d20b9 100644 --- a/Documentation/devicetree/bindings/mmc/mtk-sd.txt +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.txt @@ -12,6 +12,7 @@ Required properties: "mediatek,mt8173-mmc": for mmc host ip compatible with mt8173 "mediatek,mt8183-mmc": for mmc host ip compatible with mt8183 "mediatek,mt8516-mmc": for mmc host ip compatible with mt8516 + "mediatek,mt6779-mmc": for mmc host ip compatible with mt6779 "mediatek,mt2701-mmc": for mmc host ip compatible with mt2701 "mediatek,mt2712-mmc": for mmc host ip compatible with mt2712 "mediatek,mt7622-mmc": for MT7622 SoC @@ -49,6 +50,9 @@ Optional properties: error caused by stop clock(fifo full) Valid range = [0:0x7]. if not present, default value is 0. applied to compatible "mediatek,mt2701-mmc". +- mediatek,cqhci: HW cmdq selection + If present, hw command queue is enabled. + If not present, hw command queue is disabled. Examples: mmc0: mmc@1123 { -- 1.9.1
[PATCH v6 1/4] mmc: mediatek: add MT6779 MMC driver support
MT6779 add cqhci support, so need to add new code to support it. Signed-off-by: Chun-Hung Wu --- drivers/mmc/host/mtk-sd.c | 13 + 1 file changed, 13 insertions(+) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index b221c02..8ada675 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -538,6 +538,18 @@ struct msdc_host { .use_internal_cd = true, }; +static const struct mtk_mmc_compatible mt6779_compat = { + .clk_div_bits = 12, + .hs400_tune = false, + .pad_tune_reg = MSDC_PAD_TUNE0, + .async_fifo = true, + .data_tune = true, + .busy_check = true, + .stop_clk_fix = true, + .enhance_rx = true, + .support_64g = true, +}; + static const struct of_device_id msdc_of_ids[] = { { .compatible = "mediatek,mt8135-mmc", .data = &mt8135_compat}, { .compatible = "mediatek,mt8173-mmc", .data = &mt8173_compat}, @@ -547,6 +559,7 @@ struct msdc_host { { .compatible = "mediatek,mt7622-mmc", .data = &mt7622_compat}, { .compatible = "mediatek,mt8516-mmc", .data = &mt8516_compat}, { .compatible = "mediatek,mt7620-mmc", .data = &mt7620_compat}, + { .compatible = "mediatek,mt6779-mmc", .data = &mt6779_compat}, {} }; MODULE_DEVICE_TABLE(of, msdc_of_ids); -- 1.9.1