* [PATCH 0/5] Add intial support to DW MMC host on ZTE SoC @ 2016-10-24 9:11 Jun Nie 2016-10-24 9:11 ` [PATCH 1/5] mmc: dt-bindings: add ZTE MMC bindings Jun Nie ` (4 more replies) 0 siblings, 5 replies; 13+ messages in thread From: Jun Nie @ 2016-10-24 9:11 UTC (permalink / raw) To: shawn.guo, xie.baoyou Cc: ulf.hansson, jh80.chung, jason.liu, linux-mmc, Jun Nie Add intial support to DW MMC host on ZTE SoC. It include platform specific wrapper driver and workarounds for fifo quirk. Patches are prepared based on latest dw mmc runtime change: https://github.com/jh80chung/dw-mmc.git for-ulf Jun Nie (5): mmc: dt-bindings: add ZTE MMC bindings mmc: zx: Initial support for ZX mmc controller Documentation: synopsys-dw-mshc: add binding for fifo quirks mmc: dw: Add fifo address override property mmc: dw: Add fifo watermark quirk .../devicetree/bindings/mmc/synopsys-dw-mshc.txt | 13 ++ .../devicetree/bindings/mmc/zx-dw-mshc.txt | 34 +++ drivers/mmc/host/Kconfig | 9 + drivers/mmc/host/Makefile | 1 + drivers/mmc/host/dw_mmc-zx.c | 230 +++++++++++++++++++++ drivers/mmc/host/dw_mmc-zx.h | 23 +++ drivers/mmc/host/dw_mmc.c | 17 +- include/linux/mmc/dw_mmc.h | 3 + 8 files changed, 328 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/mmc/zx-dw-mshc.txt create mode 100644 drivers/mmc/host/dw_mmc-zx.c create mode 100644 drivers/mmc/host/dw_mmc-zx.h -- 1.9.1 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/5] mmc: dt-bindings: add ZTE MMC bindings 2016-10-24 9:11 [PATCH 0/5] Add intial support to DW MMC host on ZTE SoC Jun Nie @ 2016-10-24 9:11 ` Jun Nie 2016-10-24 9:11 ` [PATCH 2/5] mmc: zx: Initial support for ZX mmc controller Jun Nie ` (3 subsequent siblings) 4 siblings, 0 replies; 13+ messages in thread From: Jun Nie @ 2016-10-24 9:11 UTC (permalink / raw) To: shawn.guo, xie.baoyou Cc: ulf.hansson, jh80.chung, jason.liu, linux-mmc, Jun Nie Document the device-tree binding of ZTE MMC host Signed-off-by: Jun Nie <jun.nie@linaro.org> --- .../devicetree/bindings/mmc/zx-dw-mshc.txt | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 Documentation/devicetree/bindings/mmc/zx-dw-mshc.txt diff --git a/Documentation/devicetree/bindings/mmc/zx-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/zx-dw-mshc.txt new file mode 100644 index 0000000..8ad506e --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/zx-dw-mshc.txt @@ -0,0 +1,34 @@ +* ZTE specific extensions to the Synopsys Designware Mobile Storage + Host Controller + +The Synopsys designware mobile storage host controller is used to interface +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents +differences between the core Synopsys dw mshc controller properties described +by synopsys-dw-mshc.txt and the properties used by the ZTE specific +extensions to the Synopsys Designware Mobile Storage Host Controller. + +Required Properties: + +* compatible: should be + - "zx,dw-mshc": for ZX SoCs + +Example: + + mmc1: mmc@1110000 { + compatible = "zte,dw-mshc"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x01110000 0x1000>; + interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>; + fifo-depth = <32>; + fifo-addr-override = <0x200>; + bus-width = <4>; + clock-frequency = <50000000>; + clocks = <&topcrm SD0_AHB>, <&topcrm SD0_WCLK>; + clock-names = "biu", "ciu"; + num-slots = <1>; + max-frequency = <50000000>; + cap-sdio-irq; + cap-sd-highspeed; + status = "disabled"; + }; -- 1.9.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/5] mmc: zx: Initial support for ZX mmc controller 2016-10-24 9:11 [PATCH 0/5] Add intial support to DW MMC host on ZTE SoC Jun Nie 2016-10-24 9:11 ` [PATCH 1/5] mmc: dt-bindings: add ZTE MMC bindings Jun Nie @ 2016-10-24 9:11 ` Jun Nie 2016-10-24 12:29 ` Shawn Lin 2016-10-24 9:11 ` [PATCH 3/5] Documentation: synopsys-dw-mshc: add binding for fifo quirks Jun Nie ` (2 subsequent siblings) 4 siblings, 1 reply; 13+ messages in thread From: Jun Nie @ 2016-10-24 9:11 UTC (permalink / raw) To: shawn.guo, xie.baoyou Cc: ulf.hansson, jh80.chung, jason.liu, linux-mmc, Jun Nie This platform driver adds initial support for the DW host controller found on ZTE SoCs. It has been tested on ZX296718 EVB board currently. More support on timing tuning will be added when hardware is available. Signed-off-by: Jun Nie <jun.nie@linaro.org> --- drivers/mmc/host/Kconfig | 9 ++ drivers/mmc/host/Makefile | 1 + drivers/mmc/host/dw_mmc-zx.c | 230 +++++++++++++++++++++++++++++++++++++++++++ drivers/mmc/host/dw_mmc-zx.h | 23 +++++ 4 files changed, 263 insertions(+) create mode 100644 drivers/mmc/host/dw_mmc-zx.c create mode 100644 drivers/mmc/host/dw_mmc-zx.h diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 5274f50..2b3202c 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -662,6 +662,15 @@ config MMC_DW_ROCKCHIP Synopsys DesignWare Memory Card Interface driver. Select this option for platforms based on RK3066, RK3188 and RK3288 SoC's. +config MMC_DW_ZX + tristate "ZTE specific extensions for Synopsys DW Memory Card Interface" + depends on MMC_DW + select MMC_DW_PLTFM + help + This selects support for ZTE SoC specific extensions to the + Synopsys DesignWare Memory Card Interface driver. Select this option + for platforms based on ZX296718 SoC's. + config MMC_SH_MMCIF tristate "SuperH Internal MMCIF support" depends on HAS_DMA diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index e2bdaaf..9766143 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o obj-$(CONFIG_MMC_DW_K3) += dw_mmc-k3.o obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o obj-$(CONFIG_MMC_DW_ROCKCHIP) += dw_mmc-rockchip.o +obj-$(CONFIG_MMC_DW_ZX) += dw_mmc-zx.o obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o obj-$(CONFIG_MMC_VUB300) += vub300.o diff --git a/drivers/mmc/host/dw_mmc-zx.c b/drivers/mmc/host/dw_mmc-zx.c new file mode 100644 index 0000000..d0e4ef2 --- /dev/null +++ b/drivers/mmc/host/dw_mmc-zx.c @@ -0,0 +1,230 @@ +/* + * ZX Specific Extensions for Synopsys DW Multimedia Card Interface driver + * + * Copyright (C) 2016, Linaro Ltd. + * Copyright (C) 2016, ZTE Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/mfd/syscon.h> +#include <linux/mmc/dw_mmc.h> +#include <linux/mmc/host.h> +#include <linux/mmc/mmc.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/slab.h> + +#include "dw_mmc.h" +#include "dw_mmc-pltfm.h" +#include "dw_mmc-zx.h" + +#define ZX_DLL_LOCKED BIT(2) + +struct dw_mci_zx_priv_data { + struct regmap *sysc_base; +}; + +static int dw_mci_zx_emmc_set_delay(struct dw_mci *host, unsigned int delay, + unsigned int clk_flag) +{ + struct dw_mci_zx_priv_data *priv = host->priv; + struct regmap *sysc_base = priv->sysc_base; + unsigned int clksel; + unsigned int loop = 1000; + int ret; + + ret = regmap_write(sysc_base, LB_AON_EMMC_CFG_REG0, + PARA_DLL_START_POINT(4) | PARA_DLL_LOCK_NUM(4)); + if (ret) + return ret; + + ret = regmap_read(sysc_base, LB_AON_EMMC_CFG_REG1, &clksel); + if (ret) + return ret; + + if (clk_flag) { + clksel &= ~(CLK_SAMP_DELAY(0x7F)); + clksel |= (delay << 8); + } else { + clksel &= ~(READ_DQS_DELAY(0x7F)); + clksel |= delay; + } + + regmap_write(sysc_base, LB_AON_EMMC_CFG_REG1, clksel); + regmap_write(sysc_base, LB_AON_EMMC_CFG_REG0, + PARA_DLL_START_POINT(4) | PARA_DLL_LOCK_NUM(4) | + DLL_REG_SET); + + do { + ret = regmap_read(sysc_base, LB_AON_EMMC_CFG_REG2, &clksel); + if (ret) + return ret; + + } while (--loop && !(clksel & ZX_DLL_LOCKED)); + + if (!loop) { + dev_err(host->dev, "Error: %s dll lock fail\n", __func__); + return -EIO; + } + + return 0; +} + +static int dw_mci_zx_emmc_execute_tuning(struct dw_mci_slot *slot, u32 opcode) +{ + struct dw_mci *host = slot->host; + struct mmc_host *mmc = slot->mmc; + int len, start = 0, end = 0, delay, best = 0; + int ret = 0; + + for (delay = 1 ; delay < 128; delay++) { + ret = dw_mci_zx_emmc_set_delay(host, delay, 1); + if (ret) + return ret; + + if (mmc_send_tuning(mmc, opcode, NULL)) { + if (start >= 0) { + end = delay - 1; + /* check and update longest good range */ + if ((end - start) > len) { + best = (start + end) >> 1; + len = end - start; + } + } + start = -1; + end = 0; + continue; + } + if (start < 0) + start = delay; + } + + if (start >= 0) { + end = delay - 1; + if ((end - start) > len) { + best = (start + end) >> 1; + len = end - start; + } + } + if (best < 0) + return -EIO; + + dev_info(host->dev, "%s best range: start %d end %d\n", __func__, + start, end); + dw_mci_zx_emmc_set_delay(host, best, 1); + return 0; +} + +static int dw_mci_zx_prepare_hs400_tuning(struct dw_mci *host, + struct mmc_ios *ios) +{ + int ret; + + /* config phase shift 90 */ + ret = dw_mci_zx_emmc_set_delay(host, 32, 0); + if (ret < 0) + return -EIO; + + return 0; +} + +static int dw_mci_zx_execute_tuning(struct dw_mci_slot *slot, u32 opcode) +{ + struct dw_mci *host = slot->host; + + if (host->verid == 0x290a) /* emmc */ + return dw_mci_zx_emmc_execute_tuning(slot, opcode); + + return 0; +} + +static int dw_mci_zx_parse_dt(struct dw_mci *host) +{ + struct device_node *np = host->dev->of_node; + struct device_node *node; + struct dw_mci_zx_priv_data *priv; + struct regmap *sysc_base; + int ret; + + node = of_parse_phandle(np, "zte,aon-syscon", 0); + if (node) { + sysc_base = syscon_node_to_regmap(node); + of_node_put(node); + + if (IS_ERR(sysc_base)) { + ret = PTR_ERR(sysc_base); + if (ret != -EPROBE_DEFER) + dev_err(host->dev, "Can't get syscon: %d\n", + ret); + return ret; + } + } + + priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + priv->sysc_base = sysc_base; + host->priv = priv; + + return 0; +} + +static unsigned long zx_dwmmc_caps[3] = { + MMC_CAP_HW_RESET, + 0, + 0, +}; + +static const struct dw_mci_drv_data zx_drv_data = { + .caps = zx_dwmmc_caps, + .execute_tuning = dw_mci_zx_execute_tuning, + .prepare_hs400_tuning = dw_mci_zx_prepare_hs400_tuning, + .parse_dt = dw_mci_zx_parse_dt, +}; + +static const struct of_device_id dw_mci_zx_match[] = { + { .compatible = "zte,dw-mshc", .data = &zx_drv_data}, +}; +MODULE_DEVICE_TABLE(of, dw_mci_zx_match); + +static int dw_mci_zx_probe(struct platform_device *pdev) +{ + const struct dw_mci_drv_data *drv_data; + const struct of_device_id *match; + + match = of_match_node(dw_mci_zx_match, pdev->dev.of_node); + drv_data = match->data; + + return dw_mci_pltfm_register(pdev, drv_data); +} + +static const struct dev_pm_ops dw_mci_zx_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(dw_mci_runtime_suspend, + dw_mci_runtime_resume, + NULL) +}; + +static struct platform_driver dw_mci_zx_pltfm_driver = { + .probe = dw_mci_zx_probe, + .remove = dw_mci_pltfm_remove, + .driver = { + .name = "dwmmc_zx", + .of_match_table = dw_mci_zx_match, + .pm = &dw_mci_zx_dev_pm_ops, + }, +}; + +module_platform_driver(dw_mci_zx_pltfm_driver); + +MODULE_DESCRIPTION("ZTE emmc/sd driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mmc/host/dw_mmc-zx.h b/drivers/mmc/host/dw_mmc-zx.h new file mode 100644 index 0000000..b1aac52 --- /dev/null +++ b/drivers/mmc/host/dw_mmc-zx.h @@ -0,0 +1,23 @@ +#ifndef _DW_MMC_ZX_H_ +#define _DW_MMC_ZX_H_ + +/* dll reg offset*/ +#define LB_AON_EMMC_CFG_REG0 0x1B0 +#define LB_AON_EMMC_CFG_REG1 0x1B4 +#define LB_AON_EMMC_CFG_REG2 0x1B8 + +/* LB_AON_EMMC_CFG_REG0 register defines */ +#define PARA_DLL_START_POINT(x) (((x) & 0xFF) << 0) +#define DLL_REG_SET BIT(8) +#define PARA_DLL_LOCK_NUM(x) (((x) & 7) << 16) +#define PARA_PHASE_DET_SEL(x) (((x) & 7) << 20) +#define PARA_DLL_BYPASS_MODE BIT(23) +#define PARA_HALF_CLK_MODE BIT(24) + +/* LB_AON_EMMC_CFG_REG1 register defines */ +#define READ_DQS_DELAY(x) (((x) & 0x7F) << 0) +#define READ_DQS_BYPASS_MODE BIT(7) +#define CLK_SAMP_DELAY(x) (((x) & 0x7F) << 8) +#define CLK_SAMP_BYPASS_MODE BIT(15) + +#endif /* _DW_MMC_ZX_H_ */ -- 1.9.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 2/5] mmc: zx: Initial support for ZX mmc controller 2016-10-24 9:11 ` [PATCH 2/5] mmc: zx: Initial support for ZX mmc controller Jun Nie @ 2016-10-24 12:29 ` Shawn Lin 2016-10-25 8:29 ` Jun Nie 0 siblings, 1 reply; 13+ messages in thread From: Shawn Lin @ 2016-10-24 12:29 UTC (permalink / raw) To: Jun Nie, shawn.guo, xie.baoyou Cc: shawn.lin, ulf.hansson, jh80.chung, jason.liu, linux-mmc 在 2016/10/24 17:11, Jun Nie 写道: > This platform driver adds initial support for the DW host controller > found on ZTE SoCs. > > It has been tested on ZX296718 EVB board currently. More support on > timing tuning will be added when hardware is available. > > Signed-off-by: Jun Nie <jun.nie@linaro.org> > --- > drivers/mmc/host/Kconfig | 9 ++ > drivers/mmc/host/Makefile | 1 + > drivers/mmc/host/dw_mmc-zx.c | 230 +++++++++++++++++++++++++++++++++++++++++++ > drivers/mmc/host/dw_mmc-zx.h | 23 +++++ > 4 files changed, 263 insertions(+) > create mode 100644 drivers/mmc/host/dw_mmc-zx.c > create mode 100644 drivers/mmc/host/dw_mmc-zx.h > > diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig > index 5274f50..2b3202c 100644 > --- a/drivers/mmc/host/Kconfig > +++ b/drivers/mmc/host/Kconfig > @@ -662,6 +662,15 @@ config MMC_DW_ROCKCHIP > Synopsys DesignWare Memory Card Interface driver. Select this option > for platforms based on RK3066, RK3188 and RK3288 SoC's. > > +config MMC_DW_ZX > + tristate "ZTE specific extensions for Synopsys DW Memory Card Interface" > + depends on MMC_DW > + select MMC_DW_PLTFM > + help > + This selects support for ZTE SoC specific extensions to the > + Synopsys DesignWare Memory Card Interface driver. Select this option > + for platforms based on ZX296718 SoC's. > + > config MMC_SH_MMCIF > tristate "SuperH Internal MMCIF support" > depends on HAS_DMA > diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile > index e2bdaaf..9766143 100644 > --- a/drivers/mmc/host/Makefile > +++ b/drivers/mmc/host/Makefile > @@ -48,6 +48,7 @@ obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o > obj-$(CONFIG_MMC_DW_K3) += dw_mmc-k3.o > obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o > obj-$(CONFIG_MMC_DW_ROCKCHIP) += dw_mmc-rockchip.o > +obj-$(CONFIG_MMC_DW_ZX) += dw_mmc-zx.o > obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o > obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o > obj-$(CONFIG_MMC_VUB300) += vub300.o > diff --git a/drivers/mmc/host/dw_mmc-zx.c b/drivers/mmc/host/dw_mmc-zx.c > new file mode 100644 > index 0000000..d0e4ef2 > --- /dev/null > +++ b/drivers/mmc/host/dw_mmc-zx.c > @@ -0,0 +1,230 @@ > +/* > + * ZX Specific Extensions for Synopsys DW Multimedia Card Interface driver > + * > + * Copyright (C) 2016, Linaro Ltd. > + * Copyright (C) 2016, ZTE Corp. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + */ > + > +#include <linux/platform_device.h> > +#include <linux/clk.h> > +#include <linux/mfd/syscon.h> > +#include <linux/mmc/dw_mmc.h> > +#include <linux/mmc/host.h> > +#include <linux/mmc/mmc.h> > +#include <linux/module.h> > +#include <linux/of.h> #include <linux/platform_device.h> to keep alphabetical order > +#include <linux/pm_runtime.h> > +#include <linux/regmap.h> > +#include <linux/slab.h> > + > +#include "dw_mmc.h" > +#include "dw_mmc-pltfm.h" > +#include "dw_mmc-zx.h" > + > +#define ZX_DLL_LOCKED BIT(2) > + > +struct dw_mci_zx_priv_data { > + struct regmap *sysc_base; > +}; > + > +static int dw_mci_zx_emmc_set_delay(struct dw_mci *host, unsigned int delay, > + unsigned int clk_flag) I don't know if this is expected/legit way to control the delay/phase by adding code here. It looks more general to me that we should use clk_{set,get}_phase API. > +{ > + struct dw_mci_zx_priv_data *priv = host->priv; > + struct regmap *sysc_base = priv->sysc_base; > + unsigned int clksel; > + unsigned int loop = 1000; > + int ret; > + > + ret = regmap_write(sysc_base, LB_AON_EMMC_CFG_REG0, > + PARA_DLL_START_POINT(4) | PARA_DLL_LOCK_NUM(4)); > + if (ret) > + return ret; > + > + ret = regmap_read(sysc_base, LB_AON_EMMC_CFG_REG1, &clksel); > + if (ret) > + return ret; > + > + if (clk_flag) { > + clksel &= ~(CLK_SAMP_DELAY(0x7F)); > + clksel |= (delay << 8); > + } else { > + clksel &= ~(READ_DQS_DELAY(0x7F)); > + clksel |= delay; > + } > + > + regmap_write(sysc_base, LB_AON_EMMC_CFG_REG1, clksel); > + regmap_write(sysc_base, LB_AON_EMMC_CFG_REG0, > + PARA_DLL_START_POINT(4) | PARA_DLL_LOCK_NUM(4) | > + DLL_REG_SET); > + > + do { > + ret = regmap_read(sysc_base, LB_AON_EMMC_CFG_REG2, &clksel); > + if (ret) > + return ret; > + > + } while (--loop && !(clksel & ZX_DLL_LOCKED)); > + > + if (!loop) { > + dev_err(host->dev, "Error: %s dll lock fail\n", __func__); > + return -EIO; > + } > + > + return 0; > +} > + > +static int dw_mci_zx_emmc_execute_tuning(struct dw_mci_slot *slot, u32 opcode) > +{ > + struct dw_mci *host = slot->host; > + struct mmc_host *mmc = slot->mmc; > + int len, start = 0, end = 0, delay, best = 0; > + int ret = 0; > + > + for (delay = 1 ; delay < 128; delay++) { > + ret = dw_mci_zx_emmc_set_delay(host, delay, 1); > + if (ret) > + return ret; > + > + if (mmc_send_tuning(mmc, opcode, NULL)) { > + if (start >= 0) { > + end = delay - 1; > + /* check and update longest good range */ > + if ((end - start) > len) { > + best = (start + end) >> 1; > + len = end - start; > + } > + } > + start = -1; > + end = 0; > + continue; > + } > + if (start < 0) > + start = delay; > + } > + > + if (start >= 0) { > + end = delay - 1; > + if ((end - start) > len) { > + best = (start + end) >> 1; > + len = end - start; > + } > + } > + if (best < 0) > + return -EIO; > + > + dev_info(host->dev, "%s best range: start %d end %d\n", __func__, > + start, end); > + dw_mci_zx_emmc_set_delay(host, best, 1); > + return 0; > +} > + > +static int dw_mci_zx_prepare_hs400_tuning(struct dw_mci *host, > + struct mmc_ios *ios) > +{ > + int ret; > + > + /* config phase shift 90 */ > + ret = dw_mci_zx_emmc_set_delay(host, 32, 0); > + if (ret < 0) > + return -EIO; > + > + return 0; > +} > + > +static int dw_mci_zx_execute_tuning(struct dw_mci_slot *slot, u32 opcode) > +{ > + struct dw_mci *host = slot->host; > + > + if (host->verid == 0x290a) /* emmc */ > + return dw_mci_zx_emmc_execute_tuning(slot, opcode); > + > + return 0; > +} > + > +static int dw_mci_zx_parse_dt(struct dw_mci *host) > +{ > + struct device_node *np = host->dev->of_node; > + struct device_node *node; > + struct dw_mci_zx_priv_data *priv; > + struct regmap *sysc_base; > + int ret; > + > + node = of_parse_phandle(np, "zte,aon-syscon", 0); > + if (node) { > + sysc_base = syscon_node_to_regmap(node); > + of_node_put(node); > + > + if (IS_ERR(sysc_base)) { > + ret = PTR_ERR(sysc_base); > + if (ret != -EPROBE_DEFER) > + dev_err(host->dev, "Can't get syscon: %d\n", > + ret); > + return ret; > + } > + } > + > + priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; > + priv->sysc_base = sysc_base; > + host->priv = priv; > + > + return 0; > +} > + > +static unsigned long zx_dwmmc_caps[3] = { > + MMC_CAP_HW_RESET, > + 0, > + 0, > +}; > + just a thought, maybe you could add the cap-mmc-hw-reset for your emmc node on the DT as 1) you could save some bits here 2) Moreover, it's related to the board design since it isn't guaranteed that the hw_rest pin won't be used for other purpose.. > +static const struct dw_mci_drv_data zx_drv_data = { > + .caps = zx_dwmmc_caps, > + .execute_tuning = dw_mci_zx_execute_tuning, > + .prepare_hs400_tuning = dw_mci_zx_prepare_hs400_tuning, > + .parse_dt = dw_mci_zx_parse_dt, > +}; > + > +static const struct of_device_id dw_mci_zx_match[] = { > + { .compatible = "zte,dw-mshc", .data = &zx_drv_data}, > +}; > +MODULE_DEVICE_TABLE(of, dw_mci_zx_match); > + > +static int dw_mci_zx_probe(struct platform_device *pdev) > +{ > + const struct dw_mci_drv_data *drv_data; > + const struct of_device_id *match; > + > + match = of_match_node(dw_mci_zx_match, pdev->dev.of_node); > + drv_data = match->data; > + > + return dw_mci_pltfm_register(pdev, drv_data); > +} > + > +static const struct dev_pm_ops dw_mci_zx_dev_pm_ops = { > + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, > + pm_runtime_force_resume) > + SET_RUNTIME_PM_OPS(dw_mci_runtime_suspend, > + dw_mci_runtime_resume, > + NULL) > +}; > + > +static struct platform_driver dw_mci_zx_pltfm_driver = { > + .probe = dw_mci_zx_probe, > + .remove = dw_mci_pltfm_remove, > + .driver = { > + .name = "dwmmc_zx", > + .of_match_table = dw_mci_zx_match, > + .pm = &dw_mci_zx_dev_pm_ops, > + }, > +}; > + > +module_platform_driver(dw_mci_zx_pltfm_driver); > + > +MODULE_DESCRIPTION("ZTE emmc/sd driver"); > +MODULE_LICENSE("GPL v2"); > diff --git a/drivers/mmc/host/dw_mmc-zx.h b/drivers/mmc/host/dw_mmc-zx.h > new file mode 100644 > index 0000000..b1aac52 > --- /dev/null > +++ b/drivers/mmc/host/dw_mmc-zx.h > @@ -0,0 +1,23 @@ > +#ifndef _DW_MMC_ZX_H_ > +#define _DW_MMC_ZX_H_ > + > +/* dll reg offset*/ > +#define LB_AON_EMMC_CFG_REG0 0x1B0 > +#define LB_AON_EMMC_CFG_REG1 0x1B4 > +#define LB_AON_EMMC_CFG_REG2 0x1B8 > + > +/* LB_AON_EMMC_CFG_REG0 register defines */ > +#define PARA_DLL_START_POINT(x) (((x) & 0xFF) << 0) > +#define DLL_REG_SET BIT(8) > +#define PARA_DLL_LOCK_NUM(x) (((x) & 7) << 16) > +#define PARA_PHASE_DET_SEL(x) (((x) & 7) << 20) > +#define PARA_DLL_BYPASS_MODE BIT(23) > +#define PARA_HALF_CLK_MODE BIT(24) > + > +/* LB_AON_EMMC_CFG_REG1 register defines */ > +#define READ_DQS_DELAY(x) (((x) & 0x7F) << 0) > +#define READ_DQS_BYPASS_MODE BIT(7) > +#define CLK_SAMP_DELAY(x) (((x) & 0x7F) << 8) > +#define CLK_SAMP_BYPASS_MODE BIT(15) > + > +#endif /* _DW_MMC_ZX_H_ */ > -- Best Regards Shawn Lin ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/5] mmc: zx: Initial support for ZX mmc controller 2016-10-24 12:29 ` Shawn Lin @ 2016-10-25 8:29 ` Jun Nie 0 siblings, 0 replies; 13+ messages in thread From: Jun Nie @ 2016-10-25 8:29 UTC (permalink / raw) To: Shawn Lin Cc: Shawn Guo, xie.baoyou, Ulf Hansson, Jaehoon Chung, Jason Liu, linux-mmc 2016-10-24 20:29 GMT+08:00 Shawn Lin <shawn.lin@rock-chips.com>: > 在 2016/10/24 17:11, Jun Nie 写道: >> >> This platform driver adds initial support for the DW host controller >> found on ZTE SoCs. >> >> It has been tested on ZX296718 EVB board currently. More support on >> timing tuning will be added when hardware is available. >> >> Signed-off-by: Jun Nie <jun.nie@linaro.org> >> --- >> drivers/mmc/host/Kconfig | 9 ++ >> drivers/mmc/host/Makefile | 1 + >> drivers/mmc/host/dw_mmc-zx.c | 230 >> +++++++++++++++++++++++++++++++++++++++++++ >> drivers/mmc/host/dw_mmc-zx.h | 23 +++++ >> 4 files changed, 263 insertions(+) >> create mode 100644 drivers/mmc/host/dw_mmc-zx.c >> create mode 100644 drivers/mmc/host/dw_mmc-zx.h >> >> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig >> index 5274f50..2b3202c 100644 >> --- a/drivers/mmc/host/Kconfig >> +++ b/drivers/mmc/host/Kconfig >> @@ -662,6 +662,15 @@ config MMC_DW_ROCKCHIP >> Synopsys DesignWare Memory Card Interface driver. Select this >> option >> for platforms based on RK3066, RK3188 and RK3288 SoC's. >> >> +config MMC_DW_ZX >> + tristate "ZTE specific extensions for Synopsys DW Memory Card >> Interface" >> + depends on MMC_DW >> + select MMC_DW_PLTFM >> + help >> + This selects support for ZTE SoC specific extensions to the >> + Synopsys DesignWare Memory Card Interface driver. Select this >> option >> + for platforms based on ZX296718 SoC's. >> + >> config MMC_SH_MMCIF >> tristate "SuperH Internal MMCIF support" >> depends on HAS_DMA >> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile >> index e2bdaaf..9766143 100644 >> --- a/drivers/mmc/host/Makefile >> +++ b/drivers/mmc/host/Makefile >> @@ -48,6 +48,7 @@ obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o >> obj-$(CONFIG_MMC_DW_K3) += dw_mmc-k3.o >> obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o >> obj-$(CONFIG_MMC_DW_ROCKCHIP) += dw_mmc-rockchip.o >> +obj-$(CONFIG_MMC_DW_ZX) += dw_mmc-zx.o >> obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o >> obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o >> obj-$(CONFIG_MMC_VUB300) += vub300.o >> diff --git a/drivers/mmc/host/dw_mmc-zx.c b/drivers/mmc/host/dw_mmc-zx.c >> new file mode 100644 >> index 0000000..d0e4ef2 >> --- /dev/null >> +++ b/drivers/mmc/host/dw_mmc-zx.c >> @@ -0,0 +1,230 @@ >> +/* >> + * ZX Specific Extensions for Synopsys DW Multimedia Card Interface >> driver >> + * >> + * Copyright (C) 2016, Linaro Ltd. >> + * Copyright (C) 2016, ZTE Corp. >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License as published by >> + * the Free Software Foundation; either version 2 of the License, or >> + * (at your option) any later version. >> + */ >> + >> +#include <linux/platform_device.h> >> +#include <linux/clk.h> >> +#include <linux/mfd/syscon.h> >> +#include <linux/mmc/dw_mmc.h> >> +#include <linux/mmc/host.h> >> +#include <linux/mmc/mmc.h> >> +#include <linux/module.h> >> +#include <linux/of.h> > > > #include <linux/platform_device.h> > to keep alphabetical order Will do. > >> +#include <linux/pm_runtime.h> >> +#include <linux/regmap.h> >> +#include <linux/slab.h> >> + >> +#include "dw_mmc.h" >> +#include "dw_mmc-pltfm.h" >> +#include "dw_mmc-zx.h" >> + >> +#define ZX_DLL_LOCKED BIT(2) >> + >> +struct dw_mci_zx_priv_data { >> + struct regmap *sysc_base; >> +}; >> + >> +static int dw_mci_zx_emmc_set_delay(struct dw_mci *host, unsigned int >> delay, >> + unsigned int clk_flag) > > > I don't know if this is expected/legit way to control the delay/phase > by adding code here. It looks more general to me that we should use > clk_{set,get}_phase API. The phase control register reside in a system controller, not a standard clock controller. The register control data sampling phase and bypass mode etc, but no clk rate/mux. So it will take more code and ugly logic to expose a clk_* API based on such register. > > >> +{ >> + struct dw_mci_zx_priv_data *priv = host->priv; >> + struct regmap *sysc_base = priv->sysc_base; >> + unsigned int clksel; >> + unsigned int loop = 1000; >> + int ret; >> + >> + ret = regmap_write(sysc_base, LB_AON_EMMC_CFG_REG0, >> + PARA_DLL_START_POINT(4) | >> PARA_DLL_LOCK_NUM(4)); >> + if (ret) >> + return ret; >> + >> + ret = regmap_read(sysc_base, LB_AON_EMMC_CFG_REG1, &clksel); >> + if (ret) >> + return ret; >> + >> + if (clk_flag) { >> + clksel &= ~(CLK_SAMP_DELAY(0x7F)); >> + clksel |= (delay << 8); >> + } else { >> + clksel &= ~(READ_DQS_DELAY(0x7F)); >> + clksel |= delay; >> + } >> + >> + regmap_write(sysc_base, LB_AON_EMMC_CFG_REG1, clksel); >> + regmap_write(sysc_base, LB_AON_EMMC_CFG_REG0, >> + PARA_DLL_START_POINT(4) | PARA_DLL_LOCK_NUM(4) | >> + DLL_REG_SET); >> + >> + do { >> + ret = regmap_read(sysc_base, LB_AON_EMMC_CFG_REG2, >> &clksel); >> + if (ret) >> + return ret; >> + >> + } while (--loop && !(clksel & ZX_DLL_LOCKED)); >> + >> + if (!loop) { >> + dev_err(host->dev, "Error: %s dll lock fail\n", __func__); >> + return -EIO; >> + } >> + >> + return 0; >> +} >> + >> +static int dw_mci_zx_emmc_execute_tuning(struct dw_mci_slot *slot, u32 >> opcode) >> +{ >> + struct dw_mci *host = slot->host; >> + struct mmc_host *mmc = slot->mmc; >> + int len, start = 0, end = 0, delay, best = 0; >> + int ret = 0; >> + >> + for (delay = 1 ; delay < 128; delay++) { >> + ret = dw_mci_zx_emmc_set_delay(host, delay, 1); >> + if (ret) >> + return ret; >> + >> + if (mmc_send_tuning(mmc, opcode, NULL)) { >> + if (start >= 0) { >> + end = delay - 1; >> + /* check and update longest good range */ >> + if ((end - start) > len) { >> + best = (start + end) >> 1; >> + len = end - start; >> + } >> + } >> + start = -1; >> + end = 0; >> + continue; >> + } >> + if (start < 0) >> + start = delay; >> + } >> + >> + if (start >= 0) { >> + end = delay - 1; >> + if ((end - start) > len) { >> + best = (start + end) >> 1; >> + len = end - start; >> + } >> + } >> + if (best < 0) >> + return -EIO; >> + >> + dev_info(host->dev, "%s best range: start %d end %d\n", __func__, >> + start, end); >> + dw_mci_zx_emmc_set_delay(host, best, 1); >> + return 0; >> +} >> + >> +static int dw_mci_zx_prepare_hs400_tuning(struct dw_mci *host, >> + struct mmc_ios *ios) >> +{ >> + int ret; >> + >> + /* config phase shift 90 */ >> + ret = dw_mci_zx_emmc_set_delay(host, 32, 0); >> + if (ret < 0) >> + return -EIO; >> + >> + return 0; >> +} >> + >> +static int dw_mci_zx_execute_tuning(struct dw_mci_slot *slot, u32 opcode) >> +{ >> + struct dw_mci *host = slot->host; >> + >> + if (host->verid == 0x290a) /* emmc */ >> + return dw_mci_zx_emmc_execute_tuning(slot, opcode); >> + >> + return 0; >> +} >> + >> +static int dw_mci_zx_parse_dt(struct dw_mci *host) >> +{ >> + struct device_node *np = host->dev->of_node; >> + struct device_node *node; >> + struct dw_mci_zx_priv_data *priv; >> + struct regmap *sysc_base; >> + int ret; >> + >> + node = of_parse_phandle(np, "zte,aon-syscon", 0); >> + if (node) { >> + sysc_base = syscon_node_to_regmap(node); >> + of_node_put(node); >> + >> + if (IS_ERR(sysc_base)) { >> + ret = PTR_ERR(sysc_base); >> + if (ret != -EPROBE_DEFER) >> + dev_err(host->dev, "Can't get syscon: >> %d\n", >> + ret); >> + return ret; >> + } >> + } >> + >> + priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); >> + if (!priv) >> + return -ENOMEM; >> + priv->sysc_base = sysc_base; >> + host->priv = priv; >> + >> + return 0; >> +} >> + >> +static unsigned long zx_dwmmc_caps[3] = { >> + MMC_CAP_HW_RESET, >> + 0, >> + 0, >> +}; >> + > > > just a thought, maybe you could add the cap-mmc-hw-reset for your > emmc node on the DT as > > 1) you could save some bits here > 2) Moreover, it's related to the board design since it isn't > guaranteed that the hw_rest pin won't be used for other purpose.. > You are right. > >> +static const struct dw_mci_drv_data zx_drv_data = { >> + .caps = zx_dwmmc_caps, >> + .execute_tuning = dw_mci_zx_execute_tuning, >> + .prepare_hs400_tuning = dw_mci_zx_prepare_hs400_tuning, >> + .parse_dt = dw_mci_zx_parse_dt, >> +}; >> + >> +static const struct of_device_id dw_mci_zx_match[] = { >> + { .compatible = "zte,dw-mshc", .data = &zx_drv_data}, >> +}; >> +MODULE_DEVICE_TABLE(of, dw_mci_zx_match); >> + >> +static int dw_mci_zx_probe(struct platform_device *pdev) >> +{ >> + const struct dw_mci_drv_data *drv_data; >> + const struct of_device_id *match; >> + >> + match = of_match_node(dw_mci_zx_match, pdev->dev.of_node); >> + drv_data = match->data; >> + >> + return dw_mci_pltfm_register(pdev, drv_data); >> +} >> + >> +static const struct dev_pm_ops dw_mci_zx_dev_pm_ops = { >> + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, >> + pm_runtime_force_resume) >> + SET_RUNTIME_PM_OPS(dw_mci_runtime_suspend, >> + dw_mci_runtime_resume, >> + NULL) >> +}; >> + >> +static struct platform_driver dw_mci_zx_pltfm_driver = { >> + .probe = dw_mci_zx_probe, >> + .remove = dw_mci_pltfm_remove, >> + .driver = { >> + .name = "dwmmc_zx", >> + .of_match_table = dw_mci_zx_match, >> + .pm = &dw_mci_zx_dev_pm_ops, >> + }, >> +}; >> + >> +module_platform_driver(dw_mci_zx_pltfm_driver); >> + >> +MODULE_DESCRIPTION("ZTE emmc/sd driver"); >> +MODULE_LICENSE("GPL v2"); >> diff --git a/drivers/mmc/host/dw_mmc-zx.h b/drivers/mmc/host/dw_mmc-zx.h >> new file mode 100644 >> index 0000000..b1aac52 >> --- /dev/null >> +++ b/drivers/mmc/host/dw_mmc-zx.h >> @@ -0,0 +1,23 @@ >> +#ifndef _DW_MMC_ZX_H_ >> +#define _DW_MMC_ZX_H_ >> + >> +/* dll reg offset*/ >> +#define LB_AON_EMMC_CFG_REG0 0x1B0 >> +#define LB_AON_EMMC_CFG_REG1 0x1B4 >> +#define LB_AON_EMMC_CFG_REG2 0x1B8 >> + >> +/* LB_AON_EMMC_CFG_REG0 register defines */ >> +#define PARA_DLL_START_POINT(x) (((x) & 0xFF) << 0) >> +#define DLL_REG_SET BIT(8) >> +#define PARA_DLL_LOCK_NUM(x) (((x) & 7) << 16) >> +#define PARA_PHASE_DET_SEL(x) (((x) & 7) << 20) >> +#define PARA_DLL_BYPASS_MODE BIT(23) >> +#define PARA_HALF_CLK_MODE BIT(24) >> + >> +/* LB_AON_EMMC_CFG_REG1 register defines */ >> +#define READ_DQS_DELAY(x) (((x) & 0x7F) << 0) >> +#define READ_DQS_BYPASS_MODE BIT(7) >> +#define CLK_SAMP_DELAY(x) (((x) & 0x7F) << 8) >> +#define CLK_SAMP_BYPASS_MODE BIT(15) >> + >> +#endif /* _DW_MMC_ZX_H_ */ >> > > > -- > Best Regards > Shawn Lin > ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 3/5] Documentation: synopsys-dw-mshc: add binding for fifo quirks 2016-10-24 9:11 [PATCH 0/5] Add intial support to DW MMC host on ZTE SoC Jun Nie 2016-10-24 9:11 ` [PATCH 1/5] mmc: dt-bindings: add ZTE MMC bindings Jun Nie 2016-10-24 9:11 ` [PATCH 2/5] mmc: zx: Initial support for ZX mmc controller Jun Nie @ 2016-10-24 9:11 ` Jun Nie 2016-10-24 12:19 ` Shawn Lin 2016-10-24 9:11 ` [PATCH 4/5] mmc: dw: Add fifo address override property Jun Nie 2016-10-24 9:11 ` [PATCH 5/5] mmc: dw: Add fifo watermark quirk Jun Nie 4 siblings, 1 reply; 13+ messages in thread From: Jun Nie @ 2016-10-24 9:11 UTC (permalink / raw) To: shawn.guo, xie.baoyou Cc: ulf.hansson, jh80.chung, jason.liu, linux-mmc, Jun Nie Add fifo-addr-override property and fifo-watermark-quirk property to synopsys-dw-mshc bindings. It is intended to provide workarounds to support more SoCs that break current assumption. See Documentation/devicetree/bindings/reset/reset.txt for details. Signed-off-by: Jun Nie <jun.nie@linaro.org> --- Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt index 4e00e85..eb64921 100644 --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt @@ -76,6 +76,17 @@ Optional properties: * broken-cd: as documented in mmc core bindings. +* fifo-addr-override: Override fifo address with value provided by DT. The FIFO + reg offset of version 0x210A break current assumption that 0x100 (version < 0x240A) + and 0x200(version >= 0x240A) in some implementation. So this property serves as + workaround. + +* fifo-watermark-quirk: Data done irq is expected if data length is less than + watermark in PIO mode. But fifo watermark is requested to be aligned with data + length in some SoC so that TX/RX irq can be generated with data done irq. Add the + watermark quirk to mark this requirement and force fifo watermark setting + accordingly. + * vmmc-supply: The phandle to the regulator to use for vmmc. If this is specified we'll defer probe until we can find this regulator. @@ -103,6 +114,8 @@ board specific portions as listed below. interrupts = <0 75 0>; #address-cells = <1>; #size-cells = <0>; + fifo-addr-override = <0x200>; + fifo-watermark-quirk; }; [board specific internal DMA resources] -- 1.9.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 3/5] Documentation: synopsys-dw-mshc: add binding for fifo quirks 2016-10-24 9:11 ` [PATCH 3/5] Documentation: synopsys-dw-mshc: add binding for fifo quirks Jun Nie @ 2016-10-24 12:19 ` Shawn Lin 2016-10-25 2:16 ` Jaehoon Chung 0 siblings, 1 reply; 13+ messages in thread From: Shawn Lin @ 2016-10-24 12:19 UTC (permalink / raw) To: Jun Nie, shawn.guo, xie.baoyou Cc: shawn.lin, ulf.hansson, jh80.chung, jason.liu, linux-mmc On 2016/10/24 17:11, Jun Nie wrote: > Add fifo-addr-override property and fifo-watermark-quirk property to > synopsys-dw-mshc bindings. It is intended to provide workarounds to > support more SoCs that break current assumption. > > See Documentation/devicetree/bindings/reset/reset.txt for details. > > Signed-off-by: Jun Nie <jun.nie@linaro.org> > --- > Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt | 13 +++++++++++++ > 1 file changed, 13 insertions(+) > > diff --git a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt > index 4e00e85..eb64921 100644 > --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt > +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt > @@ -76,6 +76,17 @@ Optional properties: > > * broken-cd: as documented in mmc core bindings. > > +* fifo-addr-override: Override fifo address with value provided by DT. The FIFO > + reg offset of version 0x210A break current assumption that 0x100 (version < 0x240A) > + and 0x200(version >= 0x240A) in some implementation. So this property serves as > + workaround. Can we hardcode this to the code by checking the host version? > + > +* fifo-watermark-quirk: Data done irq is expected if data length is less than > + watermark in PIO mode. But fifo watermark is requested to be aligned with data > + length in some SoC so that TX/RX irq can be generated with data done irq. Add the > + watermark quirk to mark this requirement and force fifo watermark setting > + accordingly. I would like to know if this limitation is *really* related to some Socs or the version of 210A dw_mmc? > + > * vmmc-supply: The phandle to the regulator to use for vmmc. If this is > specified we'll defer probe until we can find this regulator. > > @@ -103,6 +114,8 @@ board specific portions as listed below. > interrupts = <0 75 0>; > #address-cells = <1>; > #size-cells = <0>; > + fifo-addr-override = <0x200>; > + fifo-watermark-quirk; > }; > > [board specific internal DMA resources] > -- Best Regards Shawn Lin ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/5] Documentation: synopsys-dw-mshc: add binding for fifo quirks 2016-10-24 12:19 ` Shawn Lin @ 2016-10-25 2:16 ` Jaehoon Chung 2016-10-25 4:17 ` Shawn Lin 0 siblings, 1 reply; 13+ messages in thread From: Jaehoon Chung @ 2016-10-25 2:16 UTC (permalink / raw) To: Shawn Lin, Jun Nie, shawn.guo, xie.baoyou Cc: ulf.hansson, jason.liu, linux-mmc On 10/24/2016 09:19 PM, Shawn Lin wrote: > On 2016/10/24 17:11, Jun Nie wrote: >> Add fifo-addr-override property and fifo-watermark-quirk property to >> synopsys-dw-mshc bindings. It is intended to provide workarounds to >> support more SoCs that break current assumption. >> >> See Documentation/devicetree/bindings/reset/reset.txt for details. >> >> Signed-off-by: Jun Nie <jun.nie@linaro.org> >> --- >> Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt | 13 +++++++++++++ >> 1 file changed, 13 insertions(+) >> >> diff --git a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt >> index 4e00e85..eb64921 100644 >> --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt >> +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt >> @@ -76,6 +76,17 @@ Optional properties: >> >> * broken-cd: as documented in mmc core bindings. >> >> +* fifo-addr-override: Override fifo address with value provided by DT. The FIFO >> + reg offset of version 0x210A break current assumption that 0x100 (version < 0x240A) >> + and 0x200(version >= 0x240A) in some implementation. So this property serves as >> + workaround. > > Can we hardcode this to the code by checking the host version? I think it should be not workaround..According to TRM, Address is equal or greater than 0x100. It means address can be 0x200, right? If you needs to overwrite the DATA register offset for your target, just can add the property for this. > >> + >> +* fifo-watermark-quirk: Data done irq is expected if data length is less than >> + watermark in PIO mode. But fifo watermark is requested to be aligned with data >> + length in some SoC so that TX/RX irq can be generated with data done irq. Add the >> + watermark quirk to mark this requirement and force fifo watermark setting >> + accordingly. > > I would like to know if this limitation is *really* related to some > Socs or the version of 210A dw_mmc? > > >> + >> * vmmc-supply: The phandle to the regulator to use for vmmc. If this is >> specified we'll defer probe until we can find this regulator. >> >> @@ -103,6 +114,8 @@ board specific portions as listed below. >> interrupts = <0 75 0>; >> #address-cells = <1>; >> #size-cells = <0>; >> + fifo-addr-override = <0x200>; >> + fifo-watermark-quirk; >> }; >> >> [board specific internal DMA resources] >> > > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/5] Documentation: synopsys-dw-mshc: add binding for fifo quirks 2016-10-25 2:16 ` Jaehoon Chung @ 2016-10-25 4:17 ` Shawn Lin 2016-10-25 8:09 ` Jaehoon Chung 0 siblings, 1 reply; 13+ messages in thread From: Shawn Lin @ 2016-10-25 4:17 UTC (permalink / raw) To: Jaehoon Chung, Jun Nie, shawn.guo, xie.baoyou Cc: shawn.lin, ulf.hansson, jason.liu, linux-mmc On 2016/10/25 10:16, Jaehoon Chung wrote: > On 10/24/2016 09:19 PM, Shawn Lin wrote: >> On 2016/10/24 17:11, Jun Nie wrote: >>> Add fifo-addr-override property and fifo-watermark-quirk property to >>> synopsys-dw-mshc bindings. It is intended to provide workarounds to >>> support more SoCs that break current assumption. >>> >>> See Documentation/devicetree/bindings/reset/reset.txt for details. >>> >>> Signed-off-by: Jun Nie <jun.nie@linaro.org> >>> --- >>> Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt | 13 +++++++++++++ >>> 1 file changed, 13 insertions(+) >>> >>> diff --git a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt >>> index 4e00e85..eb64921 100644 >>> --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt >>> +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt >>> @@ -76,6 +76,17 @@ Optional properties: >>> >>> * broken-cd: as documented in mmc core bindings. >>> >>> +* fifo-addr-override: Override fifo address with value provided by DT. The FIFO >>> + reg offset of version 0x210A break current assumption that 0x100 (version < 0x240A) >>> + and 0x200(version >= 0x240A) in some implementation. So this property serves as >>> + workaround. >> >> Can we hardcode this to the code by checking the host version? > > I think it should be not workaround..According to TRM, Address is equal or greater than 0x100. > It means address can be 0x200, right? > If you needs to overwrite the DATA register offset for your target, just can add the property for this. > I can't follow yours here as I don't have 210A TRM. Do you mean the TRM for 210A say: "Address is equal or greater than 0x100" ? >> >>> + >>> +* fifo-watermark-quirk: Data done irq is expected if data length is less than >>> + watermark in PIO mode. But fifo watermark is requested to be aligned with data >>> + length in some SoC so that TX/RX irq can be generated with data done irq. Add the >>> + watermark quirk to mark this requirement and force fifo watermark setting >>> + accordingly. >> >> I would like to know if this limitation is *really* related to some >> Socs or the version of 210A dw_mmc? >> >> >>> + >>> * vmmc-supply: The phandle to the regulator to use for vmmc. If this is >>> specified we'll defer probe until we can find this regulator. >>> >>> @@ -103,6 +114,8 @@ board specific portions as listed below. >>> interrupts = <0 75 0>; >>> #address-cells = <1>; >>> #size-cells = <0>; >>> + fifo-addr-override = <0x200>; >>> + fifo-watermark-quirk; >>> }; >>> >>> [board specific internal DMA resources] >>> >> >> > > > > -- Best Regards Shawn Lin ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/5] Documentation: synopsys-dw-mshc: add binding for fifo quirks 2016-10-25 4:17 ` Shawn Lin @ 2016-10-25 8:09 ` Jaehoon Chung 2016-10-25 8:33 ` Jun Nie 0 siblings, 1 reply; 13+ messages in thread From: Jaehoon Chung @ 2016-10-25 8:09 UTC (permalink / raw) To: Shawn Lin, Jun Nie, shawn.guo, xie.baoyou Cc: ulf.hansson, jason.liu, linux-mmc On 10/25/2016 01:17 PM, Shawn Lin wrote: > On 2016/10/25 10:16, Jaehoon Chung wrote: >> On 10/24/2016 09:19 PM, Shawn Lin wrote: >>> On 2016/10/24 17:11, Jun Nie wrote: >>>> Add fifo-addr-override property and fifo-watermark-quirk property to >>>> synopsys-dw-mshc bindings. It is intended to provide workarounds to >>>> support more SoCs that break current assumption. >>>> >>>> See Documentation/devicetree/bindings/reset/reset.txt for details. >>>> >>>> Signed-off-by: Jun Nie <jun.nie@linaro.org> >>>> --- >>>> Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt | 13 +++++++++++++ >>>> 1 file changed, 13 insertions(+) >>>> >>>> diff --git a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt >>>> index 4e00e85..eb64921 100644 >>>> --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt >>>> +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt >>>> @@ -76,6 +76,17 @@ Optional properties: >>>> >>>> * broken-cd: as documented in mmc core bindings. >>>> >>>> +* fifo-addr-override: Override fifo address with value provided by DT. The FIFO >>>> + reg offset of version 0x210A break current assumption that 0x100 (version < 0x240A) >>>> + and 0x200(version >= 0x240A) in some implementation. So this property serves as >>>> + workaround. >>> >>> Can we hardcode this to the code by checking the host version? >> >> I think it should be not workaround..According to TRM, Address is equal or greater than 0x100. >> It means address can be 0x200, right? >> If you needs to overwrite the DATA register offset for your target, just can add the property for this. >> > > I can't follow yours here as I don't have 210A TRM. Do you mean the TRM > for 210A say: "Address is equal or greater than 0x100" ? Upper version than IP 2.40a is used the offset 0x100 as other purpose. For preventing to use wrong register. we put to check host->verid. Yes, can set the address to any value 0x100 or greater. If some soc needs to use 0x200, why not? But it's not true that FIFO reg offset of version 2.10a break. I have checked 2.10a TRM..It's DATA offset >= 0x100. Best Regards, Jaehoon Chung > >>> >>>> + >>>> +* fifo-watermark-quirk: Data done irq is expected if data length is less than >>>> + watermark in PIO mode. But fifo watermark is requested to be aligned with data >>>> + length in some SoC so that TX/RX irq can be generated with data done irq. Add the >>>> + watermark quirk to mark this requirement and force fifo watermark setting >>>> + accordingly. >>> >>> I would like to know if this limitation is *really* related to some >>> Socs or the version of 210A dw_mmc? >>> >>> >>>> + >>>> * vmmc-supply: The phandle to the regulator to use for vmmc. If this is >>>> specified we'll defer probe until we can find this regulator. >>>> >>>> @@ -103,6 +114,8 @@ board specific portions as listed below. >>>> interrupts = <0 75 0>; >>>> #address-cells = <1>; >>>> #size-cells = <0>; >>>> + fifo-addr-override = <0x200>; >>>> + fifo-watermark-quirk; >>>> }; >>>> >>>> [board specific internal DMA resources] >>>> >>> >>> >> >> >> >> > > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/5] Documentation: synopsys-dw-mshc: add binding for fifo quirks 2016-10-25 8:09 ` Jaehoon Chung @ 2016-10-25 8:33 ` Jun Nie 0 siblings, 0 replies; 13+ messages in thread From: Jun Nie @ 2016-10-25 8:33 UTC (permalink / raw) To: Jaehoon Chung Cc: Shawn Lin, Shawn Guo, xie.baoyou, Ulf Hansson, Jason Liu, linux-mmc 2016-10-25 16:09 GMT+08:00 Jaehoon Chung <jh80.chung@samsung.com>: > On 10/25/2016 01:17 PM, Shawn Lin wrote: >> On 2016/10/25 10:16, Jaehoon Chung wrote: >>> On 10/24/2016 09:19 PM, Shawn Lin wrote: >>>> On 2016/10/24 17:11, Jun Nie wrote: >>>>> Add fifo-addr-override property and fifo-watermark-quirk property to >>>>> synopsys-dw-mshc bindings. It is intended to provide workarounds to >>>>> support more SoCs that break current assumption. >>>>> >>>>> See Documentation/devicetree/bindings/reset/reset.txt for details. >>>>> >>>>> Signed-off-by: Jun Nie <jun.nie@linaro.org> >>>>> --- >>>>> Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt | 13 +++++++++++++ >>>>> 1 file changed, 13 insertions(+) >>>>> >>>>> diff --git a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt >>>>> index 4e00e85..eb64921 100644 >>>>> --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt >>>>> +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt >>>>> @@ -76,6 +76,17 @@ Optional properties: >>>>> >>>>> * broken-cd: as documented in mmc core bindings. >>>>> >>>>> +* fifo-addr-override: Override fifo address with value provided by DT. The FIFO >>>>> + reg offset of version 0x210A break current assumption that 0x100 (version < 0x240A) >>>>> + and 0x200(version >= 0x240A) in some implementation. So this property serves as >>>>> + workaround. >>>> >>>> Can we hardcode this to the code by checking the host version? >>> >>> I think it should be not workaround..According to TRM, Address is equal or greater than 0x100. >>> It means address can be 0x200, right? >>> If you needs to overwrite the DATA register offset for your target, just can add the property for this. >>> >> >> I can't follow yours here as I don't have 210A TRM. Do you mean the TRM >> for 210A say: "Address is equal or greater than 0x100" ? > > Upper version than IP 2.40a is used the offset 0x100 as other purpose. > For preventing to use wrong register. we put to check host->verid. > > Yes, can set the address to any value 0x100 or greater. > If some soc needs to use 0x200, why not? > > But it's not true that FIFO reg offset of version 2.10a break. > I have checked 2.10a TRM..It's DATA offset >= 0x100. > > Best Regards, > Jaehoon Chung OK, will change property name to "fifo-addr" to set fifo reg address via property in next version. I do not have 2.10a TRM and had assumed current code is following the TRM. Jun > >> >>>> >>>>> + >>>>> +* fifo-watermark-quirk: Data done irq is expected if data length is less than >>>>> + watermark in PIO mode. But fifo watermark is requested to be aligned with data >>>>> + length in some SoC so that TX/RX irq can be generated with data done irq. Add the >>>>> + watermark quirk to mark this requirement and force fifo watermark setting >>>>> + accordingly. >>>> >>>> I would like to know if this limitation is *really* related to some >>>> Socs or the version of 210A dw_mmc? >>>> >>>> >>>>> + >>>>> * vmmc-supply: The phandle to the regulator to use for vmmc. If this is >>>>> specified we'll defer probe until we can find this regulator. >>>>> >>>>> @@ -103,6 +114,8 @@ board specific portions as listed below. >>>>> interrupts = <0 75 0>; >>>>> #address-cells = <1>; >>>>> #size-cells = <0>; >>>>> + fifo-addr-override = <0x200>; >>>>> + fifo-watermark-quirk; >>>>> }; >>>>> >>>>> [board specific internal DMA resources] >>>>> >>>> >>>> >>> >>> >>> >>> >> >> > ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 4/5] mmc: dw: Add fifo address override property 2016-10-24 9:11 [PATCH 0/5] Add intial support to DW MMC host on ZTE SoC Jun Nie ` (2 preceding siblings ...) 2016-10-24 9:11 ` [PATCH 3/5] Documentation: synopsys-dw-mshc: add binding for fifo quirks Jun Nie @ 2016-10-24 9:11 ` Jun Nie 2016-10-24 9:11 ` [PATCH 5/5] mmc: dw: Add fifo watermark quirk Jun Nie 4 siblings, 0 replies; 13+ messages in thread From: Jun Nie @ 2016-10-24 9:11 UTC (permalink / raw) To: shawn.guo, xie.baoyou Cc: ulf.hansson, jh80.chung, jason.liu, linux-mmc, Jun Nie The FIFO address of version 0x210A conflict with assumption that 0x100(version < 0x240A) and 0x200(version >= 0x240A) in some dw mmc implementation. So this property serves as a workaround to set fifo address with value provided by DT node. Signed-off-by: Jun Nie <jun.nie@linaro.org> --- drivers/mmc/host/dw_mmc.c | 6 ++++++ include/linux/mmc/dw_mmc.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 1c9ee36..9dcd6da 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2955,6 +2955,9 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); + of_property_read_u32(np, "fifo-addr-override", + &host->fifo_addr_override); + if (!of_property_read_u32(np, "clock-frequency", &clock_frequency)) pdata->bus_hz = clock_frequency; @@ -3163,6 +3166,9 @@ int dw_mci_probe(struct dw_mci *host) else host->fifo_reg = host->regs + DATA_240A_OFFSET; + if (host->fifo_addr_override) + host->fifo_reg = host->regs + host->fifo_addr_override; + tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host); ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt, host->irq_flags, "dw-mci", host); diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index f5af2bd..4866ef5 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -107,6 +107,7 @@ struct dw_mci_dma_slave { * @ciu_clk: Pointer to card interface unit clock instance. * @slot: Slots sharing this MMC controller. * @fifo_depth: depth of FIFO. + * @fifo_addr_override: override fifo reg offset with this value. * @data_shift: log2 of FIFO item size. * @part_buf_start: Start index in part_buf. * @part_buf_count: Bytes of partial data in part_buf. @@ -154,6 +155,7 @@ struct dw_mci { spinlock_t irq_lock; void __iomem *regs; void __iomem *fifo_reg; + u32 fifo_addr_override; struct scatterlist *sg; struct sg_mapping_iter sg_miter; -- 1.9.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 5/5] mmc: dw: Add fifo watermark quirk 2016-10-24 9:11 [PATCH 0/5] Add intial support to DW MMC host on ZTE SoC Jun Nie ` (3 preceding siblings ...) 2016-10-24 9:11 ` [PATCH 4/5] mmc: dw: Add fifo address override property Jun Nie @ 2016-10-24 9:11 ` Jun Nie 4 siblings, 0 replies; 13+ messages in thread From: Jun Nie @ 2016-10-24 9:11 UTC (permalink / raw) To: shawn.guo, xie.baoyou Cc: ulf.hansson, jh80.chung, jason.liu, linux-mmc, Jun Nie Data done irq is expected if data length is less than watermark in PIO mode. But fifo watermark is requested to be aligned with data length in some SoC so that TX/RX irq can be generated with data done irq. Add the watermark quirk to mark this requirement and force fifo watermark setting accordingly. Signed-off-by: Jun Nie <jun.nie@linaro.org> --- drivers/mmc/host/dw_mmc.c | 11 +++++++++-- include/linux/mmc/dw_mmc.h | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 9dcd6da..d746c4a 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1111,11 +1111,15 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) mci_writel(host, CTRL, temp); /* - * Use the initial fifoth_val for PIO mode. + * Use the initial fifoth_val for PIO mode. If wm_quirk + * is set, we set watermark same as data size. * If next issued data may be transfered by DMA mode, * prev_blksz should be invalidated. */ - mci_writel(host, FIFOTH, host->fifoth_val); + if (host->wm_quirk) + dw_mci_adjust_fifoth(host, data); + else + mci_writel(host, FIFOTH, host->fifoth_val); host->prev_blksz = 0; } else { /* @@ -2958,6 +2962,9 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) of_property_read_u32(np, "fifo-addr-override", &host->fifo_addr_override); + if (of_get_property(np, "fifo-watermark-quirk", NULL)) + host->wm_quirk = true; + if (!of_property_read_u32(np, "clock-frequency", &clock_frequency)) pdata->bus_hz = clock_frequency; diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 4866ef5..e7cc584 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -156,6 +156,7 @@ struct dw_mci { void __iomem *regs; void __iomem *fifo_reg; u32 fifo_addr_override; + u32 wm_quirk; struct scatterlist *sg; struct sg_mapping_iter sg_miter; -- 1.9.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
end of thread, other threads:[~2016-10-25 8:33 UTC | newest] Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2016-10-24 9:11 [PATCH 0/5] Add intial support to DW MMC host on ZTE SoC Jun Nie 2016-10-24 9:11 ` [PATCH 1/5] mmc: dt-bindings: add ZTE MMC bindings Jun Nie 2016-10-24 9:11 ` [PATCH 2/5] mmc: zx: Initial support for ZX mmc controller Jun Nie 2016-10-24 12:29 ` Shawn Lin 2016-10-25 8:29 ` Jun Nie 2016-10-24 9:11 ` [PATCH 3/5] Documentation: synopsys-dw-mshc: add binding for fifo quirks Jun Nie 2016-10-24 12:19 ` Shawn Lin 2016-10-25 2:16 ` Jaehoon Chung 2016-10-25 4:17 ` Shawn Lin 2016-10-25 8:09 ` Jaehoon Chung 2016-10-25 8:33 ` Jun Nie 2016-10-24 9:11 ` [PATCH 4/5] mmc: dw: Add fifo address override property Jun Nie 2016-10-24 9:11 ` [PATCH 5/5] mmc: dw: Add fifo watermark quirk Jun Nie
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.