Subject: [PATCH 0/2] phy: intel: Add Keem Bay eMMC PHY support

Hi.

The first part is to document DT bindings for Keem Bay eMMC PHY.

The second is the driver file, loosely based on phy-rockchip-emmc.c
and phy-intel-emmc.c. The latter is not being reused as there are
quite a number of differences i.e. registers offset, supported clock
rates, bitfield to set.

The patch was tested with Keem Bay evaluation module board.

Thank you.

Best regards,
Zainie


Wan Ahmad Zainie (2):
dt-bindings: phy: intel: Add documentation for Keem Bay eMMC PHY
phy: intel: Add Keem Bay eMMC PHY support

.../bindings/phy/intel,keembay-emmc-phy.yaml | 57 +++++
drivers/phy/intel/Kconfig | 7 +
drivers/phy/intel/Makefile | 1 +
drivers/phy/intel/phy-keembay-emmc.c | 231 ++++++++++++++++++
4 files changed, 296 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/intel,keembay-emmc-phy.yaml
create mode 100644 drivers/phy/intel/phy-keembay-emmc.c

--
2.17.1


Subject: [PATCH 1/2] dt-bindings: phy: intel: Add documentation for Keem Bay eMMC PHY

Document Intel Keem Bay eMMC PHY DT bindings.

Signed-off-by: Wan Ahmad Zainie <[email protected]>
---
.../bindings/phy/intel,keembay-emmc-phy.yaml | 57 +++++++++++++++++++
1 file changed, 57 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/intel,keembay-emmc-phy.yaml

diff --git a/Documentation/devicetree/bindings/phy/intel,keembay-emmc-phy.yaml b/Documentation/devicetree/bindings/phy/intel,keembay-emmc-phy.yaml
new file mode 100644
index 000000000000..af1d62fc8323
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/intel,keembay-emmc-phy.yaml
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright 2020 Intel Corporation
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/phy/intel,keembay-emmc-phy.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Intel Keem Bay eMMC PHY
+
+maintainers:
+ - Wan Ahmad Zainie <[email protected]>
+
+properties:
+ compatible:
+ enum:
+ - intel,keembay-emmc-phy
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ items:
+ - const: emmcclk
+
+ intel,syscon:
+ $ref: '/schemas/types.yaml#/definitions/phandle'
+ description:
+ A phandle to a syscon device used to access core/phy configuration
+ registers.
+
+ "#phy-cells":
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - intel,syscon
+ - "#phy-cells"
+
+examples:
+ - |
+ mmc_phy_syscon: syscon@20290000 {
+ compatible = "simple-mfd", "syscon";
+ reg = <0x0 0x20290000 0x0 0x54>;
+ };
+
+ emmc_phy: mmc_phy@20290000 {
+ compatible = "intel,keembay-emmc-phy";
+ reg = <0x0 0x20290000 0x0 0x54>;
+ clocks = <&mmc>;
+ clock-names = "emmcclk";
+ intel,syscon = <&mmc_phy_syscon>;
+ #phy-cells = <0>;
+ };
--
2.17.1

Subject: [PATCH 2/2] phy: intel: Add Keem Bay eMMC PHY support

Add support for eMMC PHY on Intel Keem Bay SoC.

Signed-off-by: Wan Ahmad Zainie <[email protected]>
---
drivers/phy/intel/Kconfig | 7 +
drivers/phy/intel/Makefile | 1 +
drivers/phy/intel/phy-keembay-emmc.c | 231 +++++++++++++++++++++++++++
3 files changed, 239 insertions(+)
create mode 100644 drivers/phy/intel/phy-keembay-emmc.c

diff --git a/drivers/phy/intel/Kconfig b/drivers/phy/intel/Kconfig
index 4ea6a8897cd7..56dc4d817c5f 100644
--- a/drivers/phy/intel/Kconfig
+++ b/drivers/phy/intel/Kconfig
@@ -7,3 +7,10 @@ config PHY_INTEL_EMMC
select GENERIC_PHY
help
Enable this to support the Intel EMMC PHY
+
+config PHY_KEEMBAY_EMMC
+ tristate "Intel Keem Bay EMMC PHY Driver"
+ depends on OF
+ select GENERIC_PHY
+ help
+ Enable this to support the Keem Bay EMMC PHY.
diff --git a/drivers/phy/intel/Makefile b/drivers/phy/intel/Makefile
index 6b876a75599d..bdf769671198 100644
--- a/drivers/phy/intel/Makefile
+++ b/drivers/phy/intel/Makefile
@@ -1,2 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PHY_INTEL_EMMC) += phy-intel-emmc.o
+obj-$(CONFIG_PHY_KEEMBAY_EMMC) += phy-keembay-emmc.o
diff --git a/drivers/phy/intel/phy-keembay-emmc.c b/drivers/phy/intel/phy-keembay-emmc.c
new file mode 100644
index 000000000000..490c0f79dc8d
--- /dev/null
+++ b/drivers/phy/intel/phy-keembay-emmc.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Intel Keem Bay eMMC PHY driver
+ * Copyright (C) 2019 Intel Corporation
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* eMMC/SD/SDIO core/phy configuration registers */
+#define PHY_CFG_0 0x24
+#define SEL_DLY_TXCLK_MASK BIT(29)
+#define SEL_DLY_TXCLK_SHIFT 29
+#define OTAP_DLY_ENA_MASK BIT(27)
+#define OTAP_DLY_ENA_SHIFT 27
+#define OTAP_DLY_SEL_MASK GENMASK(26, 23)
+#define OTAP_DLY_SEL_SHIFT 23
+#define DLL_EN_MASK BIT(10)
+#define DLL_EN_SHIFT 10
+#define PWR_DOWN_MASK BIT(0)
+#define PWR_DOWN_SHIFT 0
+
+#define PHY_CFG_2 0x2c
+#define SEL_FREQ_MASK GENMASK(12, 10)
+#define SEL_FREQ_SHIFT 10
+
+#define PHY_STAT 0x40
+#define CAL_DONE BIT(6)
+#define DLL_RDY BIT(5)
+
+/* From ACS_eMMC51_16nFFC_RO1100_Userguide_v1p0.pdf p17 */
+#define FREQSEL_200M_170M 0x0
+#define FREQSEL_170M_140M 0x1
+#define FREQSEL_140M_110M 0x2
+#define FREQSEL_110M_80M 0x3
+#define FREQSEL_80M_50M 0x4
+
+struct keembay_emmc_phy {
+ struct regmap *reg_base;
+ struct clk *emmcclk;
+};
+
+static int keembay_emmc_phy_power(struct phy *phy, bool power_on)
+{
+ struct keembay_emmc_phy *kmb_phy = phy_get_drvdata(phy);
+ unsigned int freqsel = FREQSEL_200M_170M;
+ unsigned long rate;
+ u32 val;
+ int ret;
+
+ regmap_update_bits(kmb_phy->reg_base, PHY_CFG_0, PWR_DOWN_MASK,
+ (0x0 << PWR_DOWN_SHIFT) & PWR_DOWN_MASK);
+ regmap_update_bits(kmb_phy->reg_base, PHY_CFG_0, DLL_EN_MASK,
+ (0x0 << DLL_EN_SHIFT) & DLL_EN_MASK);
+
+ if (!power_on)
+ return 0;
+
+ rate = clk_get_rate(kmb_phy->emmcclk);
+
+ if (rate != 0) {
+ switch (rate) {
+ case 170000001 ... 200000000:
+ freqsel = FREQSEL_200M_170M;
+ break;
+ case 140000001 ... 170000000:
+ freqsel = FREQSEL_170M_140M;
+ break;
+ case 110000001 ... 140000000:
+ freqsel = FREQSEL_140M_110M;
+ break;
+ case 80000001 ... 110000000:
+ freqsel = FREQSEL_110M_80M;
+ break;
+ case 50000000 ... 80000000:
+ freqsel = FREQSEL_80M_50M;
+ break;
+ default:
+ break;
+ }
+
+ if ((rate < 50000000) || (rate > 200000000))
+ dev_warn(&phy->dev, "Unsupported rate: %lu\n", rate);
+ }
+
+ udelay(5);
+
+ regmap_update_bits(kmb_phy->reg_base, PHY_CFG_0, PWR_DOWN_MASK,
+ (0x1 << PWR_DOWN_SHIFT) & PWR_DOWN_MASK);
+
+ ret = regmap_read_poll_timeout(kmb_phy->reg_base, PHY_STAT,
+ val, (val & CAL_DONE),
+ 0, 50 * USEC_PER_MSEC);
+ if (ret) {
+ dev_err(&phy->dev, "caldone failed, ret=%d\n", ret);
+ return ret;
+ }
+
+ /* Set the frequency of the DLL operation */
+ regmap_update_bits(kmb_phy->reg_base, PHY_CFG_2, SEL_FREQ_MASK,
+ (freqsel << SEL_FREQ_SHIFT) & SEL_FREQ_MASK);
+
+ /* Enable DLL */
+ regmap_update_bits(kmb_phy->reg_base, PHY_CFG_0, DLL_EN_MASK,
+ (0x1 << DLL_EN_SHIFT) & DLL_EN_MASK);
+
+ if (rate == 0)
+ return 0;
+
+ ret = regmap_read_poll_timeout(kmb_phy->reg_base, PHY_STAT,
+ val, (val & DLL_RDY),
+ 0, 50 * USEC_PER_MSEC);
+ if (ret) {
+ dev_err(&phy->dev, "dllrdy failed, ret=%d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int keembay_emmc_phy_init(struct phy *phy)
+{
+ struct keembay_emmc_phy *kmb_phy = phy_get_drvdata(phy);
+
+ kmb_phy->emmcclk = clk_get(&phy->dev, "emmcclk");
+ if (IS_ERR(kmb_phy->emmcclk)) {
+ dev_dbg(&phy->dev, "Error getting emmcclk\n");
+ kmb_phy->emmcclk = NULL;
+ }
+
+ return 0;
+}
+
+static int keembay_emmc_phy_exit(struct phy *phy)
+{
+ struct keembay_emmc_phy *kmb_phy = phy_get_drvdata(phy);
+
+ clk_put(kmb_phy->emmcclk);
+
+ return 0;
+};
+
+static int keembay_emmc_phy_power_on(struct phy *phy)
+{
+ struct keembay_emmc_phy *kmb_phy = phy_get_drvdata(phy);
+
+ /* Select the Delay chain based txclk */
+ regmap_update_bits(kmb_phy->reg_base, PHY_CFG_0, SEL_DLY_TXCLK_MASK,
+ (0x1 << SEL_DLY_TXCLK_SHIFT) & SEL_DLY_TXCLK_MASK);
+
+ /* Output TAP Delay Enable */
+ regmap_update_bits(kmb_phy->reg_base, PHY_CFG_0, OTAP_DLY_ENA_MASK,
+ (0x1 << OTAP_DLY_ENA_SHIFT) & OTAP_DLY_ENA_MASK);
+
+ /* Output TAP Delay Select */
+ regmap_update_bits(kmb_phy->reg_base, PHY_CFG_0, OTAP_DLY_SEL_MASK,
+ (0x2 << OTAP_DLY_SEL_SHIFT) & OTAP_DLY_SEL_MASK);
+
+ return keembay_emmc_phy_power(phy, 1);
+}
+
+static int keembay_emmc_phy_power_off(struct phy *phy)
+{
+ return keembay_emmc_phy_power(phy, 0);
+}
+
+static const struct phy_ops ops = {
+ .init = keembay_emmc_phy_init,
+ .exit = keembay_emmc_phy_exit,
+ .power_on = keembay_emmc_phy_power_on,
+ .power_off = keembay_emmc_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int keembay_emmc_phy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct keembay_emmc_phy *kmb_phy;
+ struct phy *generic_phy;
+ struct phy_provider *phy_provider;
+
+ if (!dev->parent || !dev->parent->of_node)
+ return -ENODEV;
+
+ kmb_phy = devm_kzalloc(dev, sizeof(*kmb_phy), GFP_KERNEL);
+ if (!kmb_phy)
+ return -ENOMEM;
+
+ kmb_phy->reg_base = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "intel,syscon");
+ if (IS_ERR(kmb_phy->reg_base)) {
+ dev_err(dev, "failed to find syscon\n");
+ return PTR_ERR(kmb_phy->reg_base);
+ }
+
+ generic_phy = devm_phy_create(dev, dev->of_node, &ops);
+ if (IS_ERR(generic_phy)) {
+ dev_err(dev, "failed to create PHY\n");
+ return PTR_ERR(generic_phy);
+ }
+
+ phy_set_drvdata(generic_phy, kmb_phy);
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id keembay_emmc_phy_of_match[] = {
+ { .compatible = "intel,keembay-emmc-phy" },
+ {}
+};
+
+static struct platform_driver keembay_emmc_phy_driver = {
+ .probe = keembay_emmc_phy_probe,
+ .driver = {
+ .name = "keembay-emmc-phy",
+ .of_match_table = keembay_emmc_phy_of_match,
+ },
+};
+module_platform_driver(keembay_emmc_phy_driver);
+
+MODULE_AUTHOR("Wan Ahmad Zainie <[email protected]>");
+MODULE_DESCRIPTION("Keem Bay EMMC PHY driver");
+MODULE_LICENSE("GPL v2");
--
2.17.1

2020-03-20 06:01:24

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: Re: [PATCH 1/2] dt-bindings: phy: intel: Add documentation for Keem Bay eMMC PHY

Hi,

On 3/16/2020 4:07 PM, Wan Ahmad Zainie wrote:
> Document Intel Keem Bay eMMC PHY DT bindings.
>
> Signed-off-by: Wan Ahmad Zainie <[email protected]>

Need Rob's Ack on this patch.

Thanks
Kishon
> ---
> .../bindings/phy/intel,keembay-emmc-phy.yaml | 57 +++++++++++++++++++
> 1 file changed, 57 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/phy/intel,keembay-emmc-phy.yaml
>
> diff --git a/Documentation/devicetree/bindings/phy/intel,keembay-emmc-phy.yaml b/Documentation/devicetree/bindings/phy/intel,keembay-emmc-phy.yaml
> new file mode 100644
> index 000000000000..af1d62fc8323
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/intel,keembay-emmc-phy.yaml
> @@ -0,0 +1,57 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +# Copyright 2020 Intel Corporation
> +%YAML 1.2
> +---
> +$id: "http://devicetree.org/schemas/phy/intel,keembay-emmc-phy.yaml#"
> +$schema: "http://devicetree.org/meta-schemas/core.yaml#"
> +
> +title: Intel Keem Bay eMMC PHY
> +
> +maintainers:
> + - Wan Ahmad Zainie <[email protected]>
> +
> +properties:
> + compatible:
> + enum:
> + - intel,keembay-emmc-phy
> +
> + reg:
> + maxItems: 1
> +
> + clocks:
> + maxItems: 1
> +
> + clock-names:
> + items:
> + - const: emmcclk
> +
> + intel,syscon:
> + $ref: '/schemas/types.yaml#/definitions/phandle'
> + description:
> + A phandle to a syscon device used to access core/phy configuration
> + registers.
> +
> + "#phy-cells":
> + const: 0
> +
> +required:
> + - compatible
> + - reg
> + - intel,syscon
> + - "#phy-cells"
> +
> +examples:
> + - |
> + mmc_phy_syscon: syscon@20290000 {
> + compatible = "simple-mfd", "syscon";
> + reg = <0x0 0x20290000 0x0 0x54>;
> + };
> +
> + emmc_phy: mmc_phy@20290000 {
> + compatible = "intel,keembay-emmc-phy";
> + reg = <0x0 0x20290000 0x0 0x54>;
> + clocks = <&mmc>;
> + clock-names = "emmcclk";
> + intel,syscon = <&mmc_phy_syscon>;
> + #phy-cells = <0>;
> + };
>

2020-03-30 20:23:53

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH 1/2] dt-bindings: phy: intel: Add documentation for Keem Bay eMMC PHY

On Mon, Mar 16, 2020 at 06:37:25PM +0800, Wan Ahmad Zainie wrote:
> Document Intel Keem Bay eMMC PHY DT bindings.
>
> Signed-off-by: Wan Ahmad Zainie <[email protected]>
> ---
> .../bindings/phy/intel,keembay-emmc-phy.yaml | 57 +++++++++++++++++++
> 1 file changed, 57 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/phy/intel,keembay-emmc-phy.yaml
>
> diff --git a/Documentation/devicetree/bindings/phy/intel,keembay-emmc-phy.yaml b/Documentation/devicetree/bindings/phy/intel,keembay-emmc-phy.yaml
> new file mode 100644
> index 000000000000..af1d62fc8323
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/intel,keembay-emmc-phy.yaml
> @@ -0,0 +1,57 @@
> +# SPDX-License-Identifier: GPL-2.0-only

Dual license new bindings:

(GPL-2.0-only OR BSD-2-Clause)

> +# Copyright 2020 Intel Corporation
> +%YAML 1.2
> +---
> +$id: "http://devicetree.org/schemas/phy/intel,keembay-emmc-phy.yaml#"
> +$schema: "http://devicetree.org/meta-schemas/core.yaml#"
> +
> +title: Intel Keem Bay eMMC PHY
> +
> +maintainers:
> + - Wan Ahmad Zainie <[email protected]>
> +
> +properties:
> + compatible:
> + enum:
> + - intel,keembay-emmc-phy
> +
> + reg:
> + maxItems: 1
> +
> + clocks:
> + maxItems: 1
> +
> + clock-names:
> + items:
> + - const: emmcclk
> +
> + intel,syscon:
> + $ref: '/schemas/types.yaml#/definitions/phandle'

Make this binding a child of the syscon and get rid of this.

> + description:
> + A phandle to a syscon device used to access core/phy configuration
> + registers.
> +
> + "#phy-cells":
> + const: 0
> +
> +required:
> + - compatible
> + - reg
> + - intel,syscon
> + - "#phy-cells"
> +
> +examples:
> + - |
> + mmc_phy_syscon: syscon@20290000 {
> + compatible = "simple-mfd", "syscon";
> + reg = <0x0 0x20290000 0x0 0x54>;
> + };
> +
> + emmc_phy: mmc_phy@20290000 {

phy@...

> + compatible = "intel,keembay-emmc-phy";
> + reg = <0x0 0x20290000 0x0 0x54>;

Here you have overlapping register regions. Don't do that.

Given they are the same size, why do you need the syscon at all?

> + clocks = <&mmc>;
> + clock-names = "emmcclk";
> + intel,syscon = <&mmc_phy_syscon>;
> + #phy-cells = <0>;
> + };
> --
> 2.17.1
>

Subject: RE: [PATCH 1/2] dt-bindings: phy: intel: Add documentation for Keem Bay eMMC PHY



> -----Original Message-----
> From: Rob Herring <[email protected]>
> Sent: Tuesday, March 31, 2020 4:23 AM
> To: Wan Mohamad, Wan Ahmad Zainie
> <[email protected]>
> Cc: [email protected]; [email protected]; [email protected];
> [email protected]
> Subject: Re: [PATCH 1/2] dt-bindings: phy: intel: Add documentation for
> Keem Bay eMMC PHY
>
> On Mon, Mar 16, 2020 at 06:37:25PM +0800, Wan Ahmad Zainie wrote:
> > Document Intel Keem Bay eMMC PHY DT bindings.
> >
> > Signed-off-by: Wan Ahmad Zainie
> <[email protected]>
> > ---
> > .../bindings/phy/intel,keembay-emmc-phy.yaml | 57
> +++++++++++++++++++
> > 1 file changed, 57 insertions(+)
> > create mode 100644
> Documentation/devicetree/bindings/phy/intel,keembay-emmc-phy.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/phy/intel,keembay-
> emmc-phy.yaml b/Documentation/devicetree/bindings/phy/intel,keembay-
> emmc-phy.yaml
> > new file mode 100644
> > index 000000000000..af1d62fc8323
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/phy/intel,keembay-emmc-
> phy.yaml
> > @@ -0,0 +1,57 @@
> > +# SPDX-License-Identifier: GPL-2.0-only
>
> Dual license new bindings:
>
> (GPL-2.0-only OR BSD-2-Clause)

Will change in v2.

>
> > +# Copyright 2020 Intel Corporation
> > +%YAML 1.2
> > +---
> > +$id: "http://devicetree.org/schemas/phy/intel,keembay-emmc-
> phy.yaml#"
> > +$schema: "http://devicetree.org/meta-schemas/core.yaml#"
> > +
> > +title: Intel Keem Bay eMMC PHY
> > +
> > +maintainers:
> > + - Wan Ahmad Zainie <[email protected]>
> > +
> > +properties:
> > + compatible:
> > + enum:
> > + - intel,keembay-emmc-phy
> > +
> > + reg:
> > + maxItems: 1
> > +
> > + clocks:
> > + maxItems: 1
> > +
> > + clock-names:
> > + items:
> > + - const: emmcclk
> > +
> > + intel,syscon:
> > + $ref: '/schemas/types.yaml#/definitions/phandle'
>
> Make this binding a child of the syscon and get rid of this.
>
> > + description:
> > + A phandle to a syscon device used to access core/phy configuration
> > + registers.
> > +
> > + "#phy-cells":
> > + const: 0
> > +
> > +required:
> > + - compatible
> > + - reg
> > + - intel,syscon
> > + - "#phy-cells"
> > +
> > +examples:
> > + - |
> > + mmc_phy_syscon: syscon@20290000 {
> > + compatible = "simple-mfd", "syscon";
> > + reg = <0x0 0x20290000 0x0 0x54>;
> > + };
> > +
> > + emmc_phy: mmc_phy@20290000 {
>
> phy@...

Will change in v2.

>
> > + compatible = "intel,keembay-emmc-phy";
> > + reg = <0x0 0x20290000 0x0 0x54>;
>
> Here you have overlapping register regions. Don't do that.
>
> Given they are the same size, why do you need the syscon at all?

In v2, the driver will use regmap_mmio. With that, can remove
intel,syscon. I will send out once reviewed internally.

>
> > + clocks = <&mmc>;
> > + clock-names = "emmcclk";
> > + intel,syscon = <&mmc_phy_syscon>;
> > + #phy-cells = <0>;
> > + };
> > --
> > 2.17.1
> >