linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] Add Support for MMC/SD in TI's AM65x SOCs
@ 2018-10-04 11:14 Faiz Abbas
  2018-10-04 11:14 ` [PATCH 1/6] dt-bindings: phy: am654-mmc-phy: Document new phy bindings Faiz Abbas
                   ` (5 more replies)
  0 siblings, 6 replies; 18+ messages in thread
From: Faiz Abbas @ 2018-10-04 11:14 UTC (permalink / raw)
  To: linux-kernel, devicetree, linux-mmc
  Cc: kishon, faiz_abbas, ulf.hansson, robh+dt, catalin.marinas, adrian.hunter

The following patches add driver support for MMC/SD in TI's
AM65x SOCs. There are two controller instances. Both are compatible
with eMMC5.1 Host Controller Standard Specification and SD Host
Controller Standard Specification 4.10.

DT Support patches will be posted separately.

Faiz Abbas (6):
  dt-bindings: phy: am654-mmc-phy: Document new phy bindings
  phy: am654-mmc-phy: Add Support for MMC PHY on AM654 Devices
  dt-bindings: mmc: sdhci-of-arasan: Add new compatible for AM654 MMC
    PHY
  mmc: sdhci-of-arasan: Add a single data structure to incorporate pdata
    and soc_ctl_map
  mmc: sdhci-of-arasan: Add Support for AM654 MMC and PHY
  arm64: defconfig: Enable MMC PHY for AM65xx

 .../devicetree/bindings/mmc/arasan,sdhci.txt  |   1 +
 .../devicetree/bindings/phy/am654-mmc-phy.txt |  42 +++
 arch/arm64/configs/defconfig                  |   1 +
 drivers/mmc/host/sdhci-of-arasan.c            |  93 +++++-
 drivers/phy/ti/Kconfig                        |   7 +
 drivers/phy/ti/Makefile                       |   1 +
 drivers/phy/ti/phy-am654-mmc.c                | 291 ++++++++++++++++++
 7 files changed, 421 insertions(+), 15 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/phy/am654-mmc-phy.txt
 create mode 100644 drivers/phy/ti/phy-am654-mmc.c

-- 
2.18.0


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 1/6] dt-bindings: phy: am654-mmc-phy: Document new phy bindings
  2018-10-04 11:14 [PATCH 0/6] Add Support for MMC/SD in TI's AM65x SOCs Faiz Abbas
@ 2018-10-04 11:14 ` Faiz Abbas
  2018-10-05 15:58   ` Andrew F. Davis
  2018-10-08 11:29   ` Ulf Hansson
  2018-10-04 11:14 ` [PATCH 2/6] phy: am654-mmc-phy: Add Support for MMC PHY on AM654 Devices Faiz Abbas
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 18+ messages in thread
From: Faiz Abbas @ 2018-10-04 11:14 UTC (permalink / raw)
  To: linux-kernel, devicetree, linux-mmc
  Cc: kishon, faiz_abbas, ulf.hansson, robh+dt, catalin.marinas, adrian.hunter

Add information to document bindings for the MMC PHY
on TI's AM654 devices.

Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
---
 .../devicetree/bindings/phy/am654-mmc-phy.txt | 42 +++++++++++++++++++
 1 file changed, 42 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/am654-mmc-phy.txt

diff --git a/Documentation/devicetree/bindings/phy/am654-mmc-phy.txt b/Documentation/devicetree/bindings/phy/am654-mmc-phy.txt
new file mode 100644
index 000000000000..766921612758
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/am654-mmc-phy.txt
@@ -0,0 +1,42 @@
+TI AM654 MMC PHY
+-------------------
+
+Required properties:
+ - compatible: ti,am654-emmc-phy
+ - #phy-cells: must be 0
+ - reg: PHY registers address offset and size
+ - clocks: must be phandle of the clock provider which is the host
+	   controller
+ - clock-names: must be "mmcclk"
+ - ti,otap-del-sel: Output Tap Delay select.
+ - ti,trm-icp: DLL trim select.
+ - ti,driver-strength-ohm: driver strength in ohms.
+			   Valid values are 33, 40, 50, 66, and 100 ohms.
+
+Example:
+			mmc_phy1: mmc_phy@10100 {
+				compatible = "ti,am654-mmc-phy";
+				reg = <0x10100 0x34>;
+				clocks = <&sdhci1>;
+				clock-names = "mmcclk";
+				#phy-cells = <0>;
+				ti,otap-del-sel = <0x2>;
+				ti,trm-icp = <0x8>;
+				status = "disabled";
+			};
+
+Host controller node:
+
+			sdhci1: sdhci@0 {
+				compatible = "ti,am654-sdhci-5.1";
+				reg = <0x0 0x1000>;
+				power-domains = <&k3_pds 48>;
+				clocks = <&k3_clks 48 0>, <&k3_clks 48 1>;
+				clock-names = "clk_ahb", "clk_xin";
+				interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
+				clock-output-names = "mmc_cardclck";
+				#clock-cells = <0>;
+				phys=<&mmc_phy1>;
+				phy-names = "phy_arasan";
+				status = "disabled";
+			};
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 2/6] phy: am654-mmc-phy: Add Support for MMC PHY on AM654 Devices
  2018-10-04 11:14 [PATCH 0/6] Add Support for MMC/SD in TI's AM65x SOCs Faiz Abbas
  2018-10-04 11:14 ` [PATCH 1/6] dt-bindings: phy: am654-mmc-phy: Document new phy bindings Faiz Abbas
@ 2018-10-04 11:14 ` Faiz Abbas
  2018-10-08 11:32   ` Ulf Hansson
  2018-10-04 11:14 ` [PATCH 3/6] dt-bindings: mmc: sdhci-of-arasan: Add new compatible for AM654 MMC PHY Faiz Abbas
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 18+ messages in thread
From: Faiz Abbas @ 2018-10-04 11:14 UTC (permalink / raw)
  To: linux-kernel, devicetree, linux-mmc
  Cc: kishon, faiz_abbas, ulf.hansson, robh+dt, catalin.marinas, adrian.hunter

Add driver support for the MMC physical layer present
on TI's AM654 devices.

Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
---
 drivers/phy/ti/Kconfig         |   7 +
 drivers/phy/ti/Makefile        |   1 +
 drivers/phy/ti/phy-am654-mmc.c | 291 +++++++++++++++++++++++++++++++++
 3 files changed, 299 insertions(+)
 create mode 100644 drivers/phy/ti/phy-am654-mmc.c

diff --git a/drivers/phy/ti/Kconfig b/drivers/phy/ti/Kconfig
index 20503562666c..ea5fe4db01c8 100644
--- a/drivers/phy/ti/Kconfig
+++ b/drivers/phy/ti/Kconfig
@@ -76,3 +76,10 @@ config TWL4030_USB
 	  family chips (including the TWL5030 and TPS659x0 devices).
 	  This transceiver supports high and full speed devices plus,
 	  in host mode, low speed.
+
+config PHY_AM654_MMC
+	bool "TI AM654 MMC PHY Support"
+	select GENERIC_PHY
+	help
+	  This option enables support for the Physical layer for MMC host
+	  controllers present on TI AM654 SOCs.
diff --git a/drivers/phy/ti/Makefile b/drivers/phy/ti/Makefile
index 9f361756eaf2..5b2db2d164a5 100644
--- a/drivers/phy/ti/Makefile
+++ b/drivers/phy/ti/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_OMAP_USB2)			+= phy-omap-usb2.o
 obj-$(CONFIG_TI_PIPE3)			+= phy-ti-pipe3.o
 obj-$(CONFIG_PHY_TUSB1210)		+= phy-tusb1210.o
 obj-$(CONFIG_TWL4030_USB)		+= phy-twl4030-usb.o
+obj-$(CONFIG_PHY_AM654_MMC)		+= phy-am654-mmc.o
diff --git a/drivers/phy/ti/phy-am654-mmc.c b/drivers/phy/ti/phy-am654-mmc.c
new file mode 100644
index 000000000000..91255947fb67
--- /dev/null
+++ b/drivers/phy/ti/phy-am654-mmc.c
@@ -0,0 +1,291 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * phy-am654-mmc.c - MMC PHY driver for TI's AM654 SOCs
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/regmap.h>
+
+/* MMC PHY Registers */
+#define PHYCTRL_CTRL1_REG	0x00
+#define PHYCTRL_CTRL2_REG	0x04
+#define PHYCTRL_CTRL3_REG	0x08
+#define PHYCTRL_CTRL4_REG	0x0C
+#define PHYCTRL_CTRL5_REG	0x10
+#define PHYCTRL_CTRL6_REG	0x14
+#define PHYCTRL_STAT1_REG	0x30
+#define PHYCTRL_STAT2_REG	0x34
+
+#define IOMUX_ENABLE_SHIFT	31
+#define IOMUX_ENABLE_MASK	BIT(IOMUX_ENABLE_SHIFT)
+#define OTAPDLYENA_SHIFT	20
+#define OTAPDLYENA_MASK	BIT(OTAPDLYENA_SHIFT)
+#define OTAPDLYSEL_SHIFT	12
+#define OTAPDLYSEL_MASK	GENMASK(15, 12)
+#define STRBSEL_SHIFT		24
+#define STRBSEL_MASK		GENMASK(27, 24)
+#define SEL50_SHIFT		8
+#define SEL50_MASK		BIT(SEL50_SHIFT)
+#define SEL100_SHIFT		9
+#define SEL100_MASK		BIT(SEL100_SHIFT)
+#define DLL_TRIM_ICP_SHIFT	4
+#define DLL_TRIM_ICP_MASK	GENMASK(7, 4)
+#define DR_TY_SHIFT		20
+#define DR_TY_MASK		GENMASK(22, 20)
+#define ENDLL_SHIFT		1
+#define ENDLL_MASK		BIT(ENDLL_SHIFT)
+#define DLLRDY_SHIFT		0
+#define DLLRDY_MASK		BIT(DLLRDY_SHIFT)
+#define PDB_SHIFT		0
+#define PDB_MASK		BIT(PDB_SHIFT)
+#define CALDONE_SHIFT		1
+#define CALDONE_MASK		BIT(CALDONE_SHIFT)
+
+#define DRIVER_STRENGTH_50_OHM	0x0
+#define DRIVER_STRENGTH_33_OHM	0x1
+#define DRIVER_STRENGTH_66_OHM	0x2
+#define DRIVER_STRENGTH_100_OHM	0x3
+#define DRIVER_STRENGTH_40_OHM	0x4
+
+static struct regmap_config am654_mmc_phy_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.fast_io = true,
+};
+
+struct am654_mmc_phy {
+	struct regmap *reg_base;
+	struct clk *mmcclk;
+	int otap_del_sel;
+	int trm_icp;
+	int drv_strength;
+};
+
+static int am654_mmc_phy_init(struct phy *phy)
+{
+	struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy);
+	int ret;
+	u32 val;
+
+	/* Reset registers to default value */
+	regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL1_REG, 0x10000);
+	regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL4_REG, 0x0);
+	regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL5_REG, 0x0);
+
+	/* Calibrate IO lines */
+	regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
+			   PDB_MASK, PDB_MASK);
+	ret = regmap_read_poll_timeout(mmc_phy->reg_base, PHYCTRL_STAT1_REG,
+				       val, val & CALDONE_MASK, 1, 20);
+	if (ret)
+		return ret;
+
+	/* Enable pins by setting the IO mux to 0 */
+	regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
+			   IOMUX_ENABLE_MASK, 0);
+
+	mmc_phy->mmcclk = clk_get(&phy->dev, "mmcclk");
+	if (IS_ERR(mmc_phy->mmcclk)) {
+		dev_err(&phy->dev, "Error getting mmcclk");
+		return PTR_ERR(mmc_phy->mmcclk);
+	}
+
+	return 0;
+}
+
+static int am654_mmc_phy_exit(struct phy *phy)
+{
+	struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy);
+
+	clk_put(mmc_phy->mmcclk);
+
+	return 0;
+}
+
+static int am654_mmc_phy_power_on(struct phy *phy)
+{
+	struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy);
+	u32 mask, val;
+	int sel50, sel100;
+	int rate;
+
+	/* Setup DLL Output TAP delay */
+	mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
+	val = (1 << OTAPDLYENA_SHIFT) |
+	      (mmc_phy->otap_del_sel << OTAPDLYSEL_SHIFT);
+	regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL4_REG,
+			   mask, val);
+
+	rate = clk_get_rate(mmc_phy->mmcclk);
+	switch (rate) {
+	case 200000000:
+		sel50 = 0;
+		sel100 = 0;
+		break;
+	case 100000000:
+		sel50 = 0;
+		sel100 = 1;
+		break;
+	default:
+		sel50 = 1;
+		sel100 = 0;
+	}
+
+	/* Configure PHY DLL frequency */
+	mask = SEL50_MASK | SEL100_MASK;
+	val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT);
+	regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL5_REG,
+			   mask, val);
+
+	/* Configure DLL TRIM */
+	mask = DLL_TRIM_ICP_MASK;
+	val = mmc_phy->trm_icp << DLL_TRIM_ICP_SHIFT;
+
+	/* Configure DLL driver strength */
+	mask |= DR_TY_MASK;
+	val |= mmc_phy->drv_strength << DR_TY_SHIFT;
+	regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG, mask, val);
+
+	/* Enable DLL */
+	regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
+			   ENDLL_MASK, 0x1 << ENDLL_SHIFT);
+
+	/*
+	 * Poll for DLL ready. Use a one second timeout.
+	 * Works in all experiments done so far
+	 */
+	return regmap_read_poll_timeout(mmc_phy->reg_base, PHYCTRL_STAT1_REG,
+					val, val & DLLRDY_MASK, 1000, 1000000);
+
+}
+
+static int am654_mmc_phy_power_off(struct phy *phy)
+{
+	struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy);
+
+	/* Disable DLL */
+	regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
+			   ENDLL_MASK, 0);
+
+	/* Reset registers to default value except PDB */
+	regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
+		     0x10000 | PDB_MASK);
+	regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL4_REG, 0x0);
+	regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL5_REG, 0x0);
+
+	return 0;
+}
+
+static const struct phy_ops ops = {
+	.init		= am654_mmc_phy_init,
+	.exit		= am654_mmc_phy_exit,
+	.power_on	= am654_mmc_phy_power_on,
+	.power_off	= am654_mmc_phy_power_off,
+	.owner		= THIS_MODULE,
+};
+
+static int am654_mmc_phy_probe(struct platform_device *pdev)
+{
+	struct phy_provider *phy_provider;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct am654_mmc_phy *mmc_phy;
+	struct phy *generic_phy;
+	struct resource *res;
+	void __iomem *base;
+	struct regmap *map;
+	int drv_strength;
+	int err;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	map = devm_regmap_init_mmio(dev, base, &am654_mmc_phy_regmap_config);
+	if (IS_ERR(map)) {
+		dev_err(dev, "could not initialize regmap\n");
+		return PTR_ERR(map);
+	}
+
+	mmc_phy = devm_kzalloc(dev, sizeof(struct am654_mmc_phy), GFP_KERNEL);
+	if (!mmc_phy)
+		return -ENOMEM;
+
+	mmc_phy->reg_base = map;
+	err = of_property_read_u32(np, "ti,otap-del-sel",
+				   &mmc_phy->otap_del_sel);
+	if (err)
+		return err;
+
+	err = of_property_read_u32(np, "ti,trm-icp",
+				   &mmc_phy->trm_icp);
+	if (err)
+		return err;
+
+	err = of_property_read_u32(np, "ti,driver-strength-ohm", &drv_strength);
+	if (err)
+		return err;
+
+	switch (drv_strength) {
+	case 50:
+		mmc_phy->drv_strength = DRIVER_STRENGTH_50_OHM;
+		break;
+	case 33:
+		mmc_phy->drv_strength = DRIVER_STRENGTH_33_OHM;
+		break;
+	case 66:
+		mmc_phy->drv_strength = DRIVER_STRENGTH_66_OHM;
+		break;
+	case 100:
+		mmc_phy->drv_strength = DRIVER_STRENGTH_100_OHM;
+		break;
+	case 40:
+		mmc_phy->drv_strength = DRIVER_STRENGTH_40_OHM;
+		break;
+	default:
+		dev_err(dev, "Invalid driver strength\n");
+		return -EINVAL;
+	}
+
+	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, mmc_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 am654_mmc_phy_dt_ids[] = {
+	{ .compatible = "ti,am654-mmc-phy" },
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, am654_mmc_phy_dt_ids);
+
+static struct platform_driver am654_mmc_phy_driver = {
+	.probe		= am654_mmc_phy_probe,
+	.driver		= {
+		.name	= "am654-mmc-phy",
+		.of_match_table = am654_mmc_phy_dt_ids,
+	},
+};
+
+module_platform_driver(am654_mmc_phy_driver);
+
+MODULE_AUTHOR("Faiz Abbas <faiz_abbas@ti.com>");
+MODULE_DESCRIPTION("TI AM654 MMC PHY driver");
+MODULE_LICENSE("GPL v2");
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 3/6] dt-bindings: mmc: sdhci-of-arasan: Add new compatible for AM654 MMC PHY
  2018-10-04 11:14 [PATCH 0/6] Add Support for MMC/SD in TI's AM65x SOCs Faiz Abbas
  2018-10-04 11:14 ` [PATCH 1/6] dt-bindings: phy: am654-mmc-phy: Document new phy bindings Faiz Abbas
  2018-10-04 11:14 ` [PATCH 2/6] phy: am654-mmc-phy: Add Support for MMC PHY on AM654 Devices Faiz Abbas
@ 2018-10-04 11:14 ` Faiz Abbas
  2018-10-09  7:30   ` Ulf Hansson
  2018-10-04 11:14 ` [PATCH 4/6] mmc: sdhci-of-arasan: Add a single data structure to incorporate pdata and soc_ctl_map Faiz Abbas
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 18+ messages in thread
From: Faiz Abbas @ 2018-10-04 11:14 UTC (permalink / raw)
  To: linux-kernel, devicetree, linux-mmc
  Cc: kishon, faiz_abbas, ulf.hansson, robh+dt, catalin.marinas, adrian.hunter

Add a new compatible to use the host controller driver with the
MMC PHY on TI's AM654 SOCs

Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
---
 Documentation/devicetree/bindings/mmc/arasan,sdhci.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt b/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
index f6ddba31cb73..e2effe17f05e 100644
--- a/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
+++ b/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
@@ -15,6 +15,7 @@ Required Properties:
     - "arasan,sdhci-5.1": generic Arasan SDHCI 5.1 PHY
     - "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1": rk3399 eMMC PHY
       For this device it is strongly suggested to include arasan,soc-ctl-syscon.
+    - "ti,am654-sdhci-5.1", "arasan,sdhci-5.1": TI AM654 MMC PHY
   - reg: From mmc bindings: Register location and length.
   - clocks: From clock bindings: Handles to clock inputs.
   - clock-names: From clock bindings: Tuple including "clk_xin" and "clk_ahb"
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 4/6] mmc: sdhci-of-arasan: Add a single data structure to incorporate pdata and soc_ctl_map
  2018-10-04 11:14 [PATCH 0/6] Add Support for MMC/SD in TI's AM65x SOCs Faiz Abbas
                   ` (2 preceding siblings ...)
  2018-10-04 11:14 ` [PATCH 3/6] dt-bindings: mmc: sdhci-of-arasan: Add new compatible for AM654 MMC PHY Faiz Abbas
@ 2018-10-04 11:14 ` Faiz Abbas
  2018-10-09  7:30   ` Ulf Hansson
  2018-10-04 11:14 ` [PATCH 5/6] mmc: sdhci-of-arasan: Add Support for AM654 MMC and PHY Faiz Abbas
  2018-10-04 11:14 ` [PATCH 6/6] arm64: defconfig: Enable MMC PHY for AM65xx Faiz Abbas
  5 siblings, 1 reply; 18+ messages in thread
From: Faiz Abbas @ 2018-10-04 11:14 UTC (permalink / raw)
  To: linux-kernel, devicetree, linux-mmc
  Cc: kishon, faiz_abbas, ulf.hansson, robh+dt, catalin.marinas, adrian.hunter

Currently, the driver passes platform data as a global structure
and uses the .data of of_device_id to pass the soc_ctl_map. To
make the implementation more flexible add a single data structure
that incorporates both of the above and pass it in the .data of
of_device_id.

Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
---
 drivers/mmc/host/sdhci-of-arasan.c | 47 ++++++++++++++++++++----------
 1 file changed, 32 insertions(+), 15 deletions(-)

diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c
index b806b24a3e5f..c9e3e050ccc8 100644
--- a/drivers/mmc/host/sdhci-of-arasan.c
+++ b/drivers/mmc/host/sdhci-of-arasan.c
@@ -107,6 +107,11 @@ struct sdhci_arasan_data {
 #define SDHCI_ARASAN_QUIRK_CLOCK_UNSTABLE BIT(1)
 };
 
+struct sdhci_arasan_of_data {
+	const struct sdhci_arasan_soc_ctl_map *soc_ctl_map;
+	const struct sdhci_pltfm_data *pdata;
+};
+
 static const struct sdhci_arasan_soc_ctl_map rk3399_soc_ctl_map = {
 	.baseclkfreq = { .reg = 0xf000, .width = 8, .shift = 8 },
 	.clockmultiplier = { .reg = 0xf02c, .width = 8, .shift = 0},
@@ -307,6 +312,10 @@ static const struct sdhci_pltfm_data sdhci_arasan_pdata = {
 			SDHCI_QUIRK2_STOP_WITH_TC,
 };
 
+static struct sdhci_arasan_of_data sdhci_arasan_data = {
+	.pdata = &sdhci_arasan_pdata,
+};
+
 static u32 sdhci_arasan_cqhci_irq(struct sdhci_host *host, u32 intmask)
 {
 	int cmd_error = 0;
@@ -363,6 +372,11 @@ static const struct sdhci_pltfm_data sdhci_arasan_cqe_pdata = {
 			SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
 };
 
+static struct sdhci_arasan_of_data sdhci_arasan_rk3399_data = {
+	.soc_ctl_map = &rk3399_soc_ctl_map,
+	.pdata = &sdhci_arasan_cqe_pdata,
+};
+
 #ifdef CONFIG_PM_SLEEP
 /**
  * sdhci_arasan_suspend - Suspend method for the driver
@@ -462,14 +476,21 @@ static const struct of_device_id sdhci_arasan_of_match[] = {
 	/* SoC-specific compatible strings w/ soc_ctl_map */
 	{
 		.compatible = "rockchip,rk3399-sdhci-5.1",
-		.data = &rk3399_soc_ctl_map,
+		.data = &sdhci_arasan_rk3399_data,
 	},
-
 	/* Generic compatible below here */
-	{ .compatible = "arasan,sdhci-8.9a" },
-	{ .compatible = "arasan,sdhci-5.1" },
-	{ .compatible = "arasan,sdhci-4.9a" },
-
+	{
+		.compatible = "arasan,sdhci-8.9a",
+		.data = &sdhci_arasan_data,
+	},
+	{
+		.compatible = "arasan,sdhci-5.1",
+		.data = &sdhci_arasan_data,
+	},
+	{
+		.compatible = "arasan,sdhci-4.9a",
+		.data = &sdhci_arasan_data,
+	},
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sdhci_arasan_of_match);
@@ -707,14 +728,11 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
 	struct sdhci_pltfm_host *pltfm_host;
 	struct sdhci_arasan_data *sdhci_arasan;
 	struct device_node *np = pdev->dev.of_node;
-	const struct sdhci_pltfm_data *pdata;
-
-	if (of_device_is_compatible(pdev->dev.of_node, "arasan,sdhci-5.1"))
-		pdata = &sdhci_arasan_cqe_pdata;
-	else
-		pdata = &sdhci_arasan_pdata;
+	const struct sdhci_arasan_of_data *data;
 
-	host = sdhci_pltfm_init(pdev, pdata, sizeof(*sdhci_arasan));
+	match = of_match_node(sdhci_arasan_of_match, pdev->dev.of_node);
+	data = match->data;
+	host = sdhci_pltfm_init(pdev, data->pdata, sizeof(*sdhci_arasan));
 
 	if (IS_ERR(host))
 		return PTR_ERR(host);
@@ -723,8 +741,7 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
 	sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
 	sdhci_arasan->host = host;
 
-	match = of_match_node(sdhci_arasan_of_match, pdev->dev.of_node);
-	sdhci_arasan->soc_ctl_map = match->data;
+	sdhci_arasan->soc_ctl_map = data->soc_ctl_map;
 
 	node = of_parse_phandle(pdev->dev.of_node, "arasan,soc-ctl-syscon", 0);
 	if (node) {
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 5/6] mmc: sdhci-of-arasan: Add Support for AM654 MMC and PHY
  2018-10-04 11:14 [PATCH 0/6] Add Support for MMC/SD in TI's AM65x SOCs Faiz Abbas
                   ` (3 preceding siblings ...)
  2018-10-04 11:14 ` [PATCH 4/6] mmc: sdhci-of-arasan: Add a single data structure to incorporate pdata and soc_ctl_map Faiz Abbas
@ 2018-10-04 11:14 ` Faiz Abbas
  2018-10-09  7:30   ` Ulf Hansson
  2018-10-04 11:14 ` [PATCH 6/6] arm64: defconfig: Enable MMC PHY for AM65xx Faiz Abbas
  5 siblings, 1 reply; 18+ messages in thread
From: Faiz Abbas @ 2018-10-04 11:14 UTC (permalink / raw)
  To: linux-kernel, devicetree, linux-mmc
  Cc: kishon, faiz_abbas, ulf.hansson, robh+dt, catalin.marinas, adrian.hunter

The current arasan sdhci PHY configuration isn't compatible
with the PHY on TI's AM654 devices.

Therefore, add a new compatible, AM654 specific quirks
and a new AM654 specific set_clock function which
configures the PHY in a sane way.

Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
---
 drivers/mmc/host/sdhci-of-arasan.c | 46 ++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c
index c9e3e050ccc8..142c4b802f31 100644
--- a/drivers/mmc/host/sdhci-of-arasan.c
+++ b/drivers/mmc/host/sdhci-of-arasan.c
@@ -231,6 +231,25 @@ static void sdhci_arasan_set_clock(struct sdhci_host *host, unsigned int clock)
 	}
 }
 
+static void sdhci_arasan_am654_set_clock(struct sdhci_host *host,
+					 unsigned int clock)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
+
+	if (sdhci_arasan->is_phy_on) {
+		phy_power_off(sdhci_arasan->phy);
+		sdhci_arasan->is_phy_on = false;
+	}
+
+	sdhci_set_clock(host, clock);
+
+	if (clock > PHY_CLK_TOO_SLOW_HZ) {
+		phy_power_on(sdhci_arasan->phy);
+		sdhci_arasan->is_phy_on = true;
+	}
+}
+
 static void sdhci_arasan_hs400_enhanced_strobe(struct mmc_host *mmc,
 					struct mmc_ios *ios)
 {
@@ -316,6 +335,29 @@ static struct sdhci_arasan_of_data sdhci_arasan_data = {
 	.pdata = &sdhci_arasan_pdata,
 };
 
+static const struct sdhci_ops sdhci_arasan_am654_ops = {
+	.set_clock = sdhci_arasan_am654_set_clock,
+	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
+	.get_timeout_clock = sdhci_pltfm_clk_get_max_clock,
+	.set_bus_width = sdhci_set_bus_width,
+	.reset = sdhci_arasan_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
+};
+
+static const struct sdhci_pltfm_data sdhci_arasan_am654_pdata = {
+	.ops = &sdhci_arasan_am654_ops,
+	.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN  |
+		  SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
+		  SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
+	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
+		   SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN |
+		   SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400,
+};
+
+static const struct sdhci_arasan_of_data sdhci_arasan_am654_data = {
+	.pdata = &sdhci_arasan_am654_pdata,
+};
+
 static u32 sdhci_arasan_cqhci_irq(struct sdhci_host *host, u32 intmask)
 {
 	int cmd_error = 0;
@@ -478,6 +520,10 @@ static const struct of_device_id sdhci_arasan_of_match[] = {
 		.compatible = "rockchip,rk3399-sdhci-5.1",
 		.data = &sdhci_arasan_rk3399_data,
 	},
+	{
+		.compatible = "ti,am654-sdhci-5.1",
+		.data = &sdhci_arasan_am654_data,
+	},
 	/* Generic compatible below here */
 	{
 		.compatible = "arasan,sdhci-8.9a",
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 6/6] arm64: defconfig: Enable MMC PHY for AM65xx
  2018-10-04 11:14 [PATCH 0/6] Add Support for MMC/SD in TI's AM65x SOCs Faiz Abbas
                   ` (4 preceding siblings ...)
  2018-10-04 11:14 ` [PATCH 5/6] mmc: sdhci-of-arasan: Add Support for AM654 MMC and PHY Faiz Abbas
@ 2018-10-04 11:14 ` Faiz Abbas
  5 siblings, 0 replies; 18+ messages in thread
From: Faiz Abbas @ 2018-10-04 11:14 UTC (permalink / raw)
  To: linux-kernel, devicetree, linux-mmc
  Cc: kishon, faiz_abbas, ulf.hansson, robh+dt, catalin.marinas, adrian.hunter

Enable the MMC phy implemented in the AM65xx SOC.
This phy is required for the sdhci host controller
driving the MMC ports.

Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index a51967154caa..d897ec2ba390 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -659,6 +659,7 @@ CONFIG_PHY_ROCKCHIP_TYPEC=y
 CONFIG_PHY_TEGRA_XUSB=y
 CONFIG_PHY_UNIPHIER_USB3=y
 CONFIG_PHY_UNIPHIER_USB2=y
+CONFIG_PHY_AM654_MMC=y
 CONFIG_HISI_PMU=y
 CONFIG_QCOM_L2_PMU=y
 CONFIG_QCOM_L3_PMU=y
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/6] dt-bindings: phy: am654-mmc-phy: Document new phy bindings
  2018-10-04 11:14 ` [PATCH 1/6] dt-bindings: phy: am654-mmc-phy: Document new phy bindings Faiz Abbas
@ 2018-10-05 15:58   ` Andrew F. Davis
  2018-10-09  6:34     ` Faiz Abbas
  2018-10-08 11:29   ` Ulf Hansson
  1 sibling, 1 reply; 18+ messages in thread
From: Andrew F. Davis @ 2018-10-05 15:58 UTC (permalink / raw)
  To: Faiz Abbas, linux-kernel, devicetree, linux-mmc
  Cc: kishon, ulf.hansson, robh+dt, catalin.marinas, adrian.hunter

On 10/04/2018 06:14 AM, Faiz Abbas wrote:
> Add information to document bindings for the MMC PHY
> on TI's AM654 devices.
> 
> Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
> Signed-off-by: Sekhar Nori <nsekhar@ti.com>
> ---
>  .../devicetree/bindings/phy/am654-mmc-phy.txt | 42 +++++++++++++++++++
>  1 file changed, 42 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/phy/am654-mmc-phy.txt
> 
> diff --git a/Documentation/devicetree/bindings/phy/am654-mmc-phy.txt b/Documentation/devicetree/bindings/phy/am654-mmc-phy.txt
> new file mode 100644
> index 000000000000..766921612758
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/am654-mmc-phy.txt


Name ti,am654-mmc-phy.txt might be more consistent name.


> @@ -0,0 +1,42 @@
> +TI AM654 MMC PHY
> +-------------------
> +
> +Required properties:
> + - compatible: ti,am654-emmc-phy
> + - #phy-cells: must be 0
> + - reg: PHY registers address offset and size
> + - clocks: must be phandle of the clock provider which is the host
> +	   controller
> + - clock-names: must be "mmcclk"
> + - ti,otap-del-sel: Output Tap Delay select.
> + - ti,trm-icp: DLL trim select.
> + - ti,driver-strength-ohm: driver strength in ohms.
> +			   Valid values are 33, 40, 50, 66, and 100 ohms.
> +
> +Example:
> +			mmc_phy1: mmc_phy@10100 {
> +				compatible = "ti,am654-mmc-phy";
> +				reg = <0x10100 0x34>;
> +				clocks = <&sdhci1>;
> +				clock-names = "mmcclk";
> +				#phy-cells = <0>;
> +				ti,otap-del-sel = <0x2>;
> +				ti,trm-icp = <0x8>;
> +				status = "disabled";


No need for disabled in the example case. Also not sure the host
controller example below needs to be here, there are already examples
for that binding in mmc/arasan,sdhci.txt.

Andrew


> +			};
> +
> +Host controller node:
> +
> +			sdhci1: sdhci@0 {
> +				compatible = "ti,am654-sdhci-5.1";
> +				reg = <0x0 0x1000>;
> +				power-domains = <&k3_pds 48>;
> +				clocks = <&k3_clks 48 0>, <&k3_clks 48 1>;
> +				clock-names = "clk_ahb", "clk_xin";
> +				interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
> +				clock-output-names = "mmc_cardclck";
> +				#clock-cells = <0>;
> +				phys=<&mmc_phy1>;
> +				phy-names = "phy_arasan";
> +				status = "disabled";
> +			};
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/6] dt-bindings: phy: am654-mmc-phy: Document new phy bindings
  2018-10-04 11:14 ` [PATCH 1/6] dt-bindings: phy: am654-mmc-phy: Document new phy bindings Faiz Abbas
  2018-10-05 15:58   ` Andrew F. Davis
@ 2018-10-08 11:29   ` Ulf Hansson
  1 sibling, 0 replies; 18+ messages in thread
From: Ulf Hansson @ 2018-10-08 11:29 UTC (permalink / raw)
  To: Faiz Abbas
  Cc: Linux Kernel Mailing List, DTML, linux-mmc, Kishon, Rob Herring,
	Catalin Marinas, Adrian Hunter

[...]

> +Host controller node:
> +
> +                       sdhci1: sdhci@0 {
> +                               compatible = "ti,am654-sdhci-5.1";
> +                               reg = <0x0 0x1000>;
> +                               power-domains = <&k3_pds 48>;
> +                               clocks = <&k3_clks 48 0>, <&k3_clks 48 1>;
> +                               clock-names = "clk_ahb", "clk_xin";
> +                               interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
> +                               clock-output-names = "mmc_cardclck";

mmc_cardclk

> +                               #clock-cells = <0>;
> +                               phys=<&mmc_phy1>;
> +                               phy-names = "phy_arasan";
> +                               status = "disabled";
> +                       };
> --
> 2.18.0
>

Besides the nitpick and the comments from Andrew, this looks good to me.

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/6] phy: am654-mmc-phy: Add Support for MMC PHY on AM654 Devices
  2018-10-04 11:14 ` [PATCH 2/6] phy: am654-mmc-phy: Add Support for MMC PHY on AM654 Devices Faiz Abbas
@ 2018-10-08 11:32   ` Ulf Hansson
  2018-10-09  5:18     ` Kishon Vijay Abraham I
  0 siblings, 1 reply; 18+ messages in thread
From: Ulf Hansson @ 2018-10-08 11:32 UTC (permalink / raw)
  To: Faiz Abbas
  Cc: Linux Kernel Mailing List, DTML, linux-mmc, Kishon, Rob Herring,
	Catalin Marinas, Adrian Hunter

On 4 October 2018 at 13:14, Faiz Abbas <faiz_abbas@ti.com> wrote:
> Add driver support for the MMC physical layer present
> on TI's AM654 devices.
>
> Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
> Signed-off-by: Sekhar Nori <nsekhar@ti.com>

I assume Kishon would like to pick up this through his tree? If not,
please tell and I can do it, with his ack.

Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>

Kind regards
Uffe

> ---
>  drivers/phy/ti/Kconfig         |   7 +
>  drivers/phy/ti/Makefile        |   1 +
>  drivers/phy/ti/phy-am654-mmc.c | 291 +++++++++++++++++++++++++++++++++
>  3 files changed, 299 insertions(+)
>  create mode 100644 drivers/phy/ti/phy-am654-mmc.c
>
> diff --git a/drivers/phy/ti/Kconfig b/drivers/phy/ti/Kconfig
> index 20503562666c..ea5fe4db01c8 100644
> --- a/drivers/phy/ti/Kconfig
> +++ b/drivers/phy/ti/Kconfig
> @@ -76,3 +76,10 @@ config TWL4030_USB
>           family chips (including the TWL5030 and TPS659x0 devices).
>           This transceiver supports high and full speed devices plus,
>           in host mode, low speed.
> +
> +config PHY_AM654_MMC
> +       bool "TI AM654 MMC PHY Support"
> +       select GENERIC_PHY
> +       help
> +         This option enables support for the Physical layer for MMC host
> +         controllers present on TI AM654 SOCs.
> diff --git a/drivers/phy/ti/Makefile b/drivers/phy/ti/Makefile
> index 9f361756eaf2..5b2db2d164a5 100644
> --- a/drivers/phy/ti/Makefile
> +++ b/drivers/phy/ti/Makefile
> @@ -6,3 +6,4 @@ obj-$(CONFIG_OMAP_USB2)                 += phy-omap-usb2.o
>  obj-$(CONFIG_TI_PIPE3)                 += phy-ti-pipe3.o
>  obj-$(CONFIG_PHY_TUSB1210)             += phy-tusb1210.o
>  obj-$(CONFIG_TWL4030_USB)              += phy-twl4030-usb.o
> +obj-$(CONFIG_PHY_AM654_MMC)            += phy-am654-mmc.o
> diff --git a/drivers/phy/ti/phy-am654-mmc.c b/drivers/phy/ti/phy-am654-mmc.c
> new file mode 100644
> index 000000000000..91255947fb67
> --- /dev/null
> +++ b/drivers/phy/ti/phy-am654-mmc.c
> @@ -0,0 +1,291 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * phy-am654-mmc.c - MMC PHY driver for TI's AM654 SOCs
> + *
> + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com
> + *
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/printk.h>
> +#include <linux/regmap.h>
> +
> +/* MMC PHY Registers */
> +#define PHYCTRL_CTRL1_REG      0x00
> +#define PHYCTRL_CTRL2_REG      0x04
> +#define PHYCTRL_CTRL3_REG      0x08
> +#define PHYCTRL_CTRL4_REG      0x0C
> +#define PHYCTRL_CTRL5_REG      0x10
> +#define PHYCTRL_CTRL6_REG      0x14
> +#define PHYCTRL_STAT1_REG      0x30
> +#define PHYCTRL_STAT2_REG      0x34
> +
> +#define IOMUX_ENABLE_SHIFT     31
> +#define IOMUX_ENABLE_MASK      BIT(IOMUX_ENABLE_SHIFT)
> +#define OTAPDLYENA_SHIFT       20
> +#define OTAPDLYENA_MASK        BIT(OTAPDLYENA_SHIFT)
> +#define OTAPDLYSEL_SHIFT       12
> +#define OTAPDLYSEL_MASK        GENMASK(15, 12)
> +#define STRBSEL_SHIFT          24
> +#define STRBSEL_MASK           GENMASK(27, 24)
> +#define SEL50_SHIFT            8
> +#define SEL50_MASK             BIT(SEL50_SHIFT)
> +#define SEL100_SHIFT           9
> +#define SEL100_MASK            BIT(SEL100_SHIFT)
> +#define DLL_TRIM_ICP_SHIFT     4
> +#define DLL_TRIM_ICP_MASK      GENMASK(7, 4)
> +#define DR_TY_SHIFT            20
> +#define DR_TY_MASK             GENMASK(22, 20)
> +#define ENDLL_SHIFT            1
> +#define ENDLL_MASK             BIT(ENDLL_SHIFT)
> +#define DLLRDY_SHIFT           0
> +#define DLLRDY_MASK            BIT(DLLRDY_SHIFT)
> +#define PDB_SHIFT              0
> +#define PDB_MASK               BIT(PDB_SHIFT)
> +#define CALDONE_SHIFT          1
> +#define CALDONE_MASK           BIT(CALDONE_SHIFT)
> +
> +#define DRIVER_STRENGTH_50_OHM 0x0
> +#define DRIVER_STRENGTH_33_OHM 0x1
> +#define DRIVER_STRENGTH_66_OHM 0x2
> +#define DRIVER_STRENGTH_100_OHM        0x3
> +#define DRIVER_STRENGTH_40_OHM 0x4
> +
> +static struct regmap_config am654_mmc_phy_regmap_config = {
> +       .reg_bits = 32,
> +       .val_bits = 32,
> +       .reg_stride = 4,
> +       .fast_io = true,
> +};
> +
> +struct am654_mmc_phy {
> +       struct regmap *reg_base;
> +       struct clk *mmcclk;
> +       int otap_del_sel;
> +       int trm_icp;
> +       int drv_strength;
> +};
> +
> +static int am654_mmc_phy_init(struct phy *phy)
> +{
> +       struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy);
> +       int ret;
> +       u32 val;
> +
> +       /* Reset registers to default value */
> +       regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL1_REG, 0x10000);
> +       regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL4_REG, 0x0);
> +       regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL5_REG, 0x0);
> +
> +       /* Calibrate IO lines */
> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
> +                          PDB_MASK, PDB_MASK);
> +       ret = regmap_read_poll_timeout(mmc_phy->reg_base, PHYCTRL_STAT1_REG,
> +                                      val, val & CALDONE_MASK, 1, 20);
> +       if (ret)
> +               return ret;
> +
> +       /* Enable pins by setting the IO mux to 0 */
> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
> +                          IOMUX_ENABLE_MASK, 0);
> +
> +       mmc_phy->mmcclk = clk_get(&phy->dev, "mmcclk");
> +       if (IS_ERR(mmc_phy->mmcclk)) {
> +               dev_err(&phy->dev, "Error getting mmcclk");
> +               return PTR_ERR(mmc_phy->mmcclk);
> +       }
> +
> +       return 0;
> +}
> +
> +static int am654_mmc_phy_exit(struct phy *phy)
> +{
> +       struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy);
> +
> +       clk_put(mmc_phy->mmcclk);
> +
> +       return 0;
> +}
> +
> +static int am654_mmc_phy_power_on(struct phy *phy)
> +{
> +       struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy);
> +       u32 mask, val;
> +       int sel50, sel100;
> +       int rate;
> +
> +       /* Setup DLL Output TAP delay */
> +       mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
> +       val = (1 << OTAPDLYENA_SHIFT) |
> +             (mmc_phy->otap_del_sel << OTAPDLYSEL_SHIFT);
> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL4_REG,
> +                          mask, val);
> +
> +       rate = clk_get_rate(mmc_phy->mmcclk);
> +       switch (rate) {
> +       case 200000000:
> +               sel50 = 0;
> +               sel100 = 0;
> +               break;
> +       case 100000000:
> +               sel50 = 0;
> +               sel100 = 1;
> +               break;
> +       default:
> +               sel50 = 1;
> +               sel100 = 0;
> +       }
> +
> +       /* Configure PHY DLL frequency */
> +       mask = SEL50_MASK | SEL100_MASK;
> +       val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT);
> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL5_REG,
> +                          mask, val);
> +
> +       /* Configure DLL TRIM */
> +       mask = DLL_TRIM_ICP_MASK;
> +       val = mmc_phy->trm_icp << DLL_TRIM_ICP_SHIFT;
> +
> +       /* Configure DLL driver strength */
> +       mask |= DR_TY_MASK;
> +       val |= mmc_phy->drv_strength << DR_TY_SHIFT;
> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG, mask, val);
> +
> +       /* Enable DLL */
> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
> +                          ENDLL_MASK, 0x1 << ENDLL_SHIFT);
> +
> +       /*
> +        * Poll for DLL ready. Use a one second timeout.
> +        * Works in all experiments done so far
> +        */
> +       return regmap_read_poll_timeout(mmc_phy->reg_base, PHYCTRL_STAT1_REG,
> +                                       val, val & DLLRDY_MASK, 1000, 1000000);
> +
> +}
> +
> +static int am654_mmc_phy_power_off(struct phy *phy)
> +{
> +       struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy);
> +
> +       /* Disable DLL */
> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
> +                          ENDLL_MASK, 0);
> +
> +       /* Reset registers to default value except PDB */
> +       regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
> +                    0x10000 | PDB_MASK);
> +       regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL4_REG, 0x0);
> +       regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL5_REG, 0x0);
> +
> +       return 0;
> +}
> +
> +static const struct phy_ops ops = {
> +       .init           = am654_mmc_phy_init,
> +       .exit           = am654_mmc_phy_exit,
> +       .power_on       = am654_mmc_phy_power_on,
> +       .power_off      = am654_mmc_phy_power_off,
> +       .owner          = THIS_MODULE,
> +};
> +
> +static int am654_mmc_phy_probe(struct platform_device *pdev)
> +{
> +       struct phy_provider *phy_provider;
> +       struct device *dev = &pdev->dev;
> +       struct device_node *np = dev->of_node;
> +       struct am654_mmc_phy *mmc_phy;
> +       struct phy *generic_phy;
> +       struct resource *res;
> +       void __iomem *base;
> +       struct regmap *map;
> +       int drv_strength;
> +       int err;
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       base = devm_ioremap_resource(&pdev->dev, res);
> +       if (IS_ERR(base))
> +               return PTR_ERR(base);
> +
> +       map = devm_regmap_init_mmio(dev, base, &am654_mmc_phy_regmap_config);
> +       if (IS_ERR(map)) {
> +               dev_err(dev, "could not initialize regmap\n");
> +               return PTR_ERR(map);
> +       }
> +
> +       mmc_phy = devm_kzalloc(dev, sizeof(struct am654_mmc_phy), GFP_KERNEL);
> +       if (!mmc_phy)
> +               return -ENOMEM;
> +
> +       mmc_phy->reg_base = map;
> +       err = of_property_read_u32(np, "ti,otap-del-sel",
> +                                  &mmc_phy->otap_del_sel);
> +       if (err)
> +               return err;
> +
> +       err = of_property_read_u32(np, "ti,trm-icp",
> +                                  &mmc_phy->trm_icp);
> +       if (err)
> +               return err;
> +
> +       err = of_property_read_u32(np, "ti,driver-strength-ohm", &drv_strength);
> +       if (err)
> +               return err;
> +
> +       switch (drv_strength) {
> +       case 50:
> +               mmc_phy->drv_strength = DRIVER_STRENGTH_50_OHM;
> +               break;
> +       case 33:
> +               mmc_phy->drv_strength = DRIVER_STRENGTH_33_OHM;
> +               break;
> +       case 66:
> +               mmc_phy->drv_strength = DRIVER_STRENGTH_66_OHM;
> +               break;
> +       case 100:
> +               mmc_phy->drv_strength = DRIVER_STRENGTH_100_OHM;
> +               break;
> +       case 40:
> +               mmc_phy->drv_strength = DRIVER_STRENGTH_40_OHM;
> +               break;
> +       default:
> +               dev_err(dev, "Invalid driver strength\n");
> +               return -EINVAL;
> +       }
> +
> +       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, mmc_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 am654_mmc_phy_dt_ids[] = {
> +       { .compatible = "ti,am654-mmc-phy" },
> +       {}
> +};
> +
> +MODULE_DEVICE_TABLE(of, am654_mmc_phy_dt_ids);
> +
> +static struct platform_driver am654_mmc_phy_driver = {
> +       .probe          = am654_mmc_phy_probe,
> +       .driver         = {
> +               .name   = "am654-mmc-phy",
> +               .of_match_table = am654_mmc_phy_dt_ids,
> +       },
> +};
> +
> +module_platform_driver(am654_mmc_phy_driver);
> +
> +MODULE_AUTHOR("Faiz Abbas <faiz_abbas@ti.com>");
> +MODULE_DESCRIPTION("TI AM654 MMC PHY driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.18.0
>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/6] phy: am654-mmc-phy: Add Support for MMC PHY on AM654 Devices
  2018-10-08 11:32   ` Ulf Hansson
@ 2018-10-09  5:18     ` Kishon Vijay Abraham I
  2018-10-09  7:30       ` Ulf Hansson
  0 siblings, 1 reply; 18+ messages in thread
From: Kishon Vijay Abraham I @ 2018-10-09  5:18 UTC (permalink / raw)
  To: Ulf Hansson, Faiz Abbas
  Cc: Linux Kernel Mailing List, DTML, linux-mmc, Rob Herring,
	Catalin Marinas, Adrian Hunter

Hi Uffe,

On Monday 08 October 2018 05:02 PM, Ulf Hansson wrote:
> On 4 October 2018 at 13:14, Faiz Abbas <faiz_abbas@ti.com> wrote:
>> Add driver support for the MMC physical layer present
>> on TI's AM654 devices.
>>
>> Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
>> Signed-off-by: Sekhar Nori <nsekhar@ti.com>
> 
> I assume Kishon would like to pick up this through his tree? If not,
> please tell and I can do it, with his ack.

yes, I'll pick this in my tree.

> 
> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>

Thanks
Kishon

> 
> Kind regards
> Uffe
> 
>> ---
>>  drivers/phy/ti/Kconfig         |   7 +
>>  drivers/phy/ti/Makefile        |   1 +
>>  drivers/phy/ti/phy-am654-mmc.c | 291 +++++++++++++++++++++++++++++++++
>>  3 files changed, 299 insertions(+)
>>  create mode 100644 drivers/phy/ti/phy-am654-mmc.c
>>
>> diff --git a/drivers/phy/ti/Kconfig b/drivers/phy/ti/Kconfig
>> index 20503562666c..ea5fe4db01c8 100644
>> --- a/drivers/phy/ti/Kconfig
>> +++ b/drivers/phy/ti/Kconfig
>> @@ -76,3 +76,10 @@ config TWL4030_USB
>>           family chips (including the TWL5030 and TPS659x0 devices).
>>           This transceiver supports high and full speed devices plus,
>>           in host mode, low speed.
>> +
>> +config PHY_AM654_MMC
>> +       bool "TI AM654 MMC PHY Support"
>> +       select GENERIC_PHY
>> +       help
>> +         This option enables support for the Physical layer for MMC host
>> +         controllers present on TI AM654 SOCs.
>> diff --git a/drivers/phy/ti/Makefile b/drivers/phy/ti/Makefile
>> index 9f361756eaf2..5b2db2d164a5 100644
>> --- a/drivers/phy/ti/Makefile
>> +++ b/drivers/phy/ti/Makefile
>> @@ -6,3 +6,4 @@ obj-$(CONFIG_OMAP_USB2)                 += phy-omap-usb2.o
>>  obj-$(CONFIG_TI_PIPE3)                 += phy-ti-pipe3.o
>>  obj-$(CONFIG_PHY_TUSB1210)             += phy-tusb1210.o
>>  obj-$(CONFIG_TWL4030_USB)              += phy-twl4030-usb.o
>> +obj-$(CONFIG_PHY_AM654_MMC)            += phy-am654-mmc.o
>> diff --git a/drivers/phy/ti/phy-am654-mmc.c b/drivers/phy/ti/phy-am654-mmc.c
>> new file mode 100644
>> index 000000000000..91255947fb67
>> --- /dev/null
>> +++ b/drivers/phy/ti/phy-am654-mmc.c
>> @@ -0,0 +1,291 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * phy-am654-mmc.c - MMC PHY driver for TI's AM654 SOCs
>> + *
>> + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com
>> + *
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/phy/phy.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/printk.h>
>> +#include <linux/regmap.h>
>> +
>> +/* MMC PHY Registers */
>> +#define PHYCTRL_CTRL1_REG      0x00
>> +#define PHYCTRL_CTRL2_REG      0x04
>> +#define PHYCTRL_CTRL3_REG      0x08
>> +#define PHYCTRL_CTRL4_REG      0x0C
>> +#define PHYCTRL_CTRL5_REG      0x10
>> +#define PHYCTRL_CTRL6_REG      0x14
>> +#define PHYCTRL_STAT1_REG      0x30
>> +#define PHYCTRL_STAT2_REG      0x34
>> +
>> +#define IOMUX_ENABLE_SHIFT     31
>> +#define IOMUX_ENABLE_MASK      BIT(IOMUX_ENABLE_SHIFT)
>> +#define OTAPDLYENA_SHIFT       20
>> +#define OTAPDLYENA_MASK        BIT(OTAPDLYENA_SHIFT)
>> +#define OTAPDLYSEL_SHIFT       12
>> +#define OTAPDLYSEL_MASK        GENMASK(15, 12)
>> +#define STRBSEL_SHIFT          24
>> +#define STRBSEL_MASK           GENMASK(27, 24)
>> +#define SEL50_SHIFT            8
>> +#define SEL50_MASK             BIT(SEL50_SHIFT)
>> +#define SEL100_SHIFT           9
>> +#define SEL100_MASK            BIT(SEL100_SHIFT)
>> +#define DLL_TRIM_ICP_SHIFT     4
>> +#define DLL_TRIM_ICP_MASK      GENMASK(7, 4)
>> +#define DR_TY_SHIFT            20
>> +#define DR_TY_MASK             GENMASK(22, 20)
>> +#define ENDLL_SHIFT            1
>> +#define ENDLL_MASK             BIT(ENDLL_SHIFT)
>> +#define DLLRDY_SHIFT           0
>> +#define DLLRDY_MASK            BIT(DLLRDY_SHIFT)
>> +#define PDB_SHIFT              0
>> +#define PDB_MASK               BIT(PDB_SHIFT)
>> +#define CALDONE_SHIFT          1
>> +#define CALDONE_MASK           BIT(CALDONE_SHIFT)
>> +
>> +#define DRIVER_STRENGTH_50_OHM 0x0
>> +#define DRIVER_STRENGTH_33_OHM 0x1
>> +#define DRIVER_STRENGTH_66_OHM 0x2
>> +#define DRIVER_STRENGTH_100_OHM        0x3
>> +#define DRIVER_STRENGTH_40_OHM 0x4
>> +
>> +static struct regmap_config am654_mmc_phy_regmap_config = {
>> +       .reg_bits = 32,
>> +       .val_bits = 32,
>> +       .reg_stride = 4,
>> +       .fast_io = true,
>> +};
>> +
>> +struct am654_mmc_phy {
>> +       struct regmap *reg_base;
>> +       struct clk *mmcclk;
>> +       int otap_del_sel;
>> +       int trm_icp;
>> +       int drv_strength;
>> +};
>> +
>> +static int am654_mmc_phy_init(struct phy *phy)
>> +{
>> +       struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy);
>> +       int ret;
>> +       u32 val;
>> +
>> +       /* Reset registers to default value */
>> +       regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL1_REG, 0x10000);
>> +       regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL4_REG, 0x0);
>> +       regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL5_REG, 0x0);
>> +
>> +       /* Calibrate IO lines */
>> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
>> +                          PDB_MASK, PDB_MASK);
>> +       ret = regmap_read_poll_timeout(mmc_phy->reg_base, PHYCTRL_STAT1_REG,
>> +                                      val, val & CALDONE_MASK, 1, 20);
>> +       if (ret)
>> +               return ret;
>> +
>> +       /* Enable pins by setting the IO mux to 0 */
>> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
>> +                          IOMUX_ENABLE_MASK, 0);
>> +
>> +       mmc_phy->mmcclk = clk_get(&phy->dev, "mmcclk");
>> +       if (IS_ERR(mmc_phy->mmcclk)) {
>> +               dev_err(&phy->dev, "Error getting mmcclk");
>> +               return PTR_ERR(mmc_phy->mmcclk);
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int am654_mmc_phy_exit(struct phy *phy)
>> +{
>> +       struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy);
>> +
>> +       clk_put(mmc_phy->mmcclk);
>> +
>> +       return 0;
>> +}
>> +
>> +static int am654_mmc_phy_power_on(struct phy *phy)
>> +{
>> +       struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy);
>> +       u32 mask, val;
>> +       int sel50, sel100;
>> +       int rate;
>> +
>> +       /* Setup DLL Output TAP delay */
>> +       mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
>> +       val = (1 << OTAPDLYENA_SHIFT) |
>> +             (mmc_phy->otap_del_sel << OTAPDLYSEL_SHIFT);
>> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL4_REG,
>> +                          mask, val);
>> +
>> +       rate = clk_get_rate(mmc_phy->mmcclk);
>> +       switch (rate) {
>> +       case 200000000:
>> +               sel50 = 0;
>> +               sel100 = 0;
>> +               break;
>> +       case 100000000:
>> +               sel50 = 0;
>> +               sel100 = 1;
>> +               break;
>> +       default:
>> +               sel50 = 1;
>> +               sel100 = 0;
>> +       }
>> +
>> +       /* Configure PHY DLL frequency */
>> +       mask = SEL50_MASK | SEL100_MASK;
>> +       val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT);
>> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL5_REG,
>> +                          mask, val);
>> +
>> +       /* Configure DLL TRIM */
>> +       mask = DLL_TRIM_ICP_MASK;
>> +       val = mmc_phy->trm_icp << DLL_TRIM_ICP_SHIFT;
>> +
>> +       /* Configure DLL driver strength */
>> +       mask |= DR_TY_MASK;
>> +       val |= mmc_phy->drv_strength << DR_TY_SHIFT;
>> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG, mask, val);
>> +
>> +       /* Enable DLL */
>> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
>> +                          ENDLL_MASK, 0x1 << ENDLL_SHIFT);
>> +
>> +       /*
>> +        * Poll for DLL ready. Use a one second timeout.
>> +        * Works in all experiments done so far
>> +        */
>> +       return regmap_read_poll_timeout(mmc_phy->reg_base, PHYCTRL_STAT1_REG,
>> +                                       val, val & DLLRDY_MASK, 1000, 1000000);
>> +
>> +}
>> +
>> +static int am654_mmc_phy_power_off(struct phy *phy)
>> +{
>> +       struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy);
>> +
>> +       /* Disable DLL */
>> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
>> +                          ENDLL_MASK, 0);
>> +
>> +       /* Reset registers to default value except PDB */
>> +       regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
>> +                    0x10000 | PDB_MASK);
>> +       regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL4_REG, 0x0);
>> +       regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL5_REG, 0x0);
>> +
>> +       return 0;
>> +}
>> +
>> +static const struct phy_ops ops = {
>> +       .init           = am654_mmc_phy_init,
>> +       .exit           = am654_mmc_phy_exit,
>> +       .power_on       = am654_mmc_phy_power_on,
>> +       .power_off      = am654_mmc_phy_power_off,
>> +       .owner          = THIS_MODULE,
>> +};
>> +
>> +static int am654_mmc_phy_probe(struct platform_device *pdev)
>> +{
>> +       struct phy_provider *phy_provider;
>> +       struct device *dev = &pdev->dev;
>> +       struct device_node *np = dev->of_node;
>> +       struct am654_mmc_phy *mmc_phy;
>> +       struct phy *generic_phy;
>> +       struct resource *res;
>> +       void __iomem *base;
>> +       struct regmap *map;
>> +       int drv_strength;
>> +       int err;
>> +
>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +       base = devm_ioremap_resource(&pdev->dev, res);
>> +       if (IS_ERR(base))
>> +               return PTR_ERR(base);
>> +
>> +       map = devm_regmap_init_mmio(dev, base, &am654_mmc_phy_regmap_config);
>> +       if (IS_ERR(map)) {
>> +               dev_err(dev, "could not initialize regmap\n");
>> +               return PTR_ERR(map);
>> +       }
>> +
>> +       mmc_phy = devm_kzalloc(dev, sizeof(struct am654_mmc_phy), GFP_KERNEL);
>> +       if (!mmc_phy)
>> +               return -ENOMEM;
>> +
>> +       mmc_phy->reg_base = map;
>> +       err = of_property_read_u32(np, "ti,otap-del-sel",
>> +                                  &mmc_phy->otap_del_sel);
>> +       if (err)
>> +               return err;
>> +
>> +       err = of_property_read_u32(np, "ti,trm-icp",
>> +                                  &mmc_phy->trm_icp);
>> +       if (err)
>> +               return err;
>> +
>> +       err = of_property_read_u32(np, "ti,driver-strength-ohm", &drv_strength);
>> +       if (err)
>> +               return err;
>> +
>> +       switch (drv_strength) {
>> +       case 50:
>> +               mmc_phy->drv_strength = DRIVER_STRENGTH_50_OHM;
>> +               break;
>> +       case 33:
>> +               mmc_phy->drv_strength = DRIVER_STRENGTH_33_OHM;
>> +               break;
>> +       case 66:
>> +               mmc_phy->drv_strength = DRIVER_STRENGTH_66_OHM;
>> +               break;
>> +       case 100:
>> +               mmc_phy->drv_strength = DRIVER_STRENGTH_100_OHM;
>> +               break;
>> +       case 40:
>> +               mmc_phy->drv_strength = DRIVER_STRENGTH_40_OHM;
>> +               break;
>> +       default:
>> +               dev_err(dev, "Invalid driver strength\n");
>> +               return -EINVAL;
>> +       }
>> +
>> +       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, mmc_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 am654_mmc_phy_dt_ids[] = {
>> +       { .compatible = "ti,am654-mmc-phy" },
>> +       {}
>> +};
>> +
>> +MODULE_DEVICE_TABLE(of, am654_mmc_phy_dt_ids);
>> +
>> +static struct platform_driver am654_mmc_phy_driver = {
>> +       .probe          = am654_mmc_phy_probe,
>> +       .driver         = {
>> +               .name   = "am654-mmc-phy",
>> +               .of_match_table = am654_mmc_phy_dt_ids,
>> +       },
>> +};
>> +
>> +module_platform_driver(am654_mmc_phy_driver);
>> +
>> +MODULE_AUTHOR("Faiz Abbas <faiz_abbas@ti.com>");
>> +MODULE_DESCRIPTION("TI AM654 MMC PHY driver");
>> +MODULE_LICENSE("GPL v2");
>> --
>> 2.18.0
>>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/6] dt-bindings: phy: am654-mmc-phy: Document new phy bindings
  2018-10-05 15:58   ` Andrew F. Davis
@ 2018-10-09  6:34     ` Faiz Abbas
  0 siblings, 0 replies; 18+ messages in thread
From: Faiz Abbas @ 2018-10-09  6:34 UTC (permalink / raw)
  To: Andrew F. Davis, linux-kernel, devicetree, linux-mmc
  Cc: kishon, ulf.hansson, robh+dt, catalin.marinas, adrian.hunter

Hi Andrew,

On Friday 05 October 2018 09:28 PM, Andrew F. Davis wrote:
> On 10/04/2018 06:14 AM, Faiz Abbas wrote:
>> Add information to document bindings for the MMC PHY
>> on TI's AM654 devices.
>>
>> Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
>> Signed-off-by: Sekhar Nori <nsekhar@ti.com>
>> ---
>>  .../devicetree/bindings/phy/am654-mmc-phy.txt | 42 +++++++++++++++++++
>>  1 file changed, 42 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/phy/am654-mmc-phy.txt
>>
>> diff --git a/Documentation/devicetree/bindings/phy/am654-mmc-phy.txt b/Documentation/devicetree/bindings/phy/am654-mmc-phy.txt
>> new file mode 100644
>> index 000000000000..766921612758
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/phy/am654-mmc-phy.txt
> 
> 
> Name ti,am654-mmc-phy.txt might be more consistent name.

Ok.

> 
> 
>> @@ -0,0 +1,42 @@
>> +TI AM654 MMC PHY
>> +-------------------
>> +
>> +Required properties:
>> + - compatible: ti,am654-emmc-phy
>> + - #phy-cells: must be 0
>> + - reg: PHY registers address offset and size
>> + - clocks: must be phandle of the clock provider which is the host
>> +	   controller
>> + - clock-names: must be "mmcclk"
>> + - ti,otap-del-sel: Output Tap Delay select.
>> + - ti,trm-icp: DLL trim select.
>> + - ti,driver-strength-ohm: driver strength in ohms.
>> +			   Valid values are 33, 40, 50, 66, and 100 ohms.
>> +
>> +Example:
>> +			mmc_phy1: mmc_phy@10100 {
>> +				compatible = "ti,am654-mmc-phy";
>> +				reg = <0x10100 0x34>;
>> +				clocks = <&sdhci1>;
>> +				clock-names = "mmcclk";
>> +				#phy-cells = <0>;
>> +				ti,otap-del-sel = <0x2>;
>> +				ti,trm-icp = <0x8>;
>> +				status = "disabled";
> 
> 
> No need for disabled in the example case. 

Ok.

> Also not sure the host
> controller example below needs to be here, there are already examples
> for that binding in mmc/arasan,sdhci.txt.
> 

I had added it because it is a clock source in clocks=<&sdhci1> so it
should have #clock-cells and clock-output-names. I suppose I can just
reference it here.

Thanks,
Faiz

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 3/6] dt-bindings: mmc: sdhci-of-arasan: Add new compatible for AM654 MMC PHY
  2018-10-04 11:14 ` [PATCH 3/6] dt-bindings: mmc: sdhci-of-arasan: Add new compatible for AM654 MMC PHY Faiz Abbas
@ 2018-10-09  7:30   ` Ulf Hansson
  0 siblings, 0 replies; 18+ messages in thread
From: Ulf Hansson @ 2018-10-09  7:30 UTC (permalink / raw)
  To: Faiz Abbas
  Cc: Linux Kernel Mailing List, DTML, linux-mmc, Kishon, Rob Herring,
	Catalin Marinas, Adrian Hunter

On 4 October 2018 at 13:14, Faiz Abbas <faiz_abbas@ti.com> wrote:
> Add a new compatible to use the host controller driver with the
> MMC PHY on TI's AM654 SOCs
>
> Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
> Signed-off-by: Sekhar Nori <nsekhar@ti.com>

Applied for next, thanks!

Kind regards
Uffe

> ---
>  Documentation/devicetree/bindings/mmc/arasan,sdhci.txt | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt b/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
> index f6ddba31cb73..e2effe17f05e 100644
> --- a/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
> +++ b/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
> @@ -15,6 +15,7 @@ Required Properties:
>      - "arasan,sdhci-5.1": generic Arasan SDHCI 5.1 PHY
>      - "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1": rk3399 eMMC PHY
>        For this device it is strongly suggested to include arasan,soc-ctl-syscon.
> +    - "ti,am654-sdhci-5.1", "arasan,sdhci-5.1": TI AM654 MMC PHY
>    - reg: From mmc bindings: Register location and length.
>    - clocks: From clock bindings: Handles to clock inputs.
>    - clock-names: From clock bindings: Tuple including "clk_xin" and "clk_ahb"
> --
> 2.18.0
>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/6] mmc: sdhci-of-arasan: Add a single data structure to incorporate pdata and soc_ctl_map
  2018-10-04 11:14 ` [PATCH 4/6] mmc: sdhci-of-arasan: Add a single data structure to incorporate pdata and soc_ctl_map Faiz Abbas
@ 2018-10-09  7:30   ` Ulf Hansson
  0 siblings, 0 replies; 18+ messages in thread
From: Ulf Hansson @ 2018-10-09  7:30 UTC (permalink / raw)
  To: Faiz Abbas
  Cc: Linux Kernel Mailing List, DTML, linux-mmc, Kishon, Rob Herring,
	Catalin Marinas, Adrian Hunter

On 4 October 2018 at 13:14, Faiz Abbas <faiz_abbas@ti.com> wrote:
> Currently, the driver passes platform data as a global structure
> and uses the .data of of_device_id to pass the soc_ctl_map. To
> make the implementation more flexible add a single data structure
> that incorporates both of the above and pass it in the .data of
> of_device_id.
>
> Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
> Signed-off-by: Sekhar Nori <nsekhar@ti.com>

Applied for next, thanks!

Kind regards
Uffe

> ---
>  drivers/mmc/host/sdhci-of-arasan.c | 47 ++++++++++++++++++++----------
>  1 file changed, 32 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c
> index b806b24a3e5f..c9e3e050ccc8 100644
> --- a/drivers/mmc/host/sdhci-of-arasan.c
> +++ b/drivers/mmc/host/sdhci-of-arasan.c
> @@ -107,6 +107,11 @@ struct sdhci_arasan_data {
>  #define SDHCI_ARASAN_QUIRK_CLOCK_UNSTABLE BIT(1)
>  };
>
> +struct sdhci_arasan_of_data {
> +       const struct sdhci_arasan_soc_ctl_map *soc_ctl_map;
> +       const struct sdhci_pltfm_data *pdata;
> +};
> +
>  static const struct sdhci_arasan_soc_ctl_map rk3399_soc_ctl_map = {
>         .baseclkfreq = { .reg = 0xf000, .width = 8, .shift = 8 },
>         .clockmultiplier = { .reg = 0xf02c, .width = 8, .shift = 0},
> @@ -307,6 +312,10 @@ static const struct sdhci_pltfm_data sdhci_arasan_pdata = {
>                         SDHCI_QUIRK2_STOP_WITH_TC,
>  };
>
> +static struct sdhci_arasan_of_data sdhci_arasan_data = {
> +       .pdata = &sdhci_arasan_pdata,
> +};
> +
>  static u32 sdhci_arasan_cqhci_irq(struct sdhci_host *host, u32 intmask)
>  {
>         int cmd_error = 0;
> @@ -363,6 +372,11 @@ static const struct sdhci_pltfm_data sdhci_arasan_cqe_pdata = {
>                         SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
>  };
>
> +static struct sdhci_arasan_of_data sdhci_arasan_rk3399_data = {
> +       .soc_ctl_map = &rk3399_soc_ctl_map,
> +       .pdata = &sdhci_arasan_cqe_pdata,
> +};
> +
>  #ifdef CONFIG_PM_SLEEP
>  /**
>   * sdhci_arasan_suspend - Suspend method for the driver
> @@ -462,14 +476,21 @@ static const struct of_device_id sdhci_arasan_of_match[] = {
>         /* SoC-specific compatible strings w/ soc_ctl_map */
>         {
>                 .compatible = "rockchip,rk3399-sdhci-5.1",
> -               .data = &rk3399_soc_ctl_map,
> +               .data = &sdhci_arasan_rk3399_data,
>         },
> -
>         /* Generic compatible below here */
> -       { .compatible = "arasan,sdhci-8.9a" },
> -       { .compatible = "arasan,sdhci-5.1" },
> -       { .compatible = "arasan,sdhci-4.9a" },
> -
> +       {
> +               .compatible = "arasan,sdhci-8.9a",
> +               .data = &sdhci_arasan_data,
> +       },
> +       {
> +               .compatible = "arasan,sdhci-5.1",
> +               .data = &sdhci_arasan_data,
> +       },
> +       {
> +               .compatible = "arasan,sdhci-4.9a",
> +               .data = &sdhci_arasan_data,
> +       },
>         { /* sentinel */ }
>  };
>  MODULE_DEVICE_TABLE(of, sdhci_arasan_of_match);
> @@ -707,14 +728,11 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
>         struct sdhci_pltfm_host *pltfm_host;
>         struct sdhci_arasan_data *sdhci_arasan;
>         struct device_node *np = pdev->dev.of_node;
> -       const struct sdhci_pltfm_data *pdata;
> -
> -       if (of_device_is_compatible(pdev->dev.of_node, "arasan,sdhci-5.1"))
> -               pdata = &sdhci_arasan_cqe_pdata;
> -       else
> -               pdata = &sdhci_arasan_pdata;
> +       const struct sdhci_arasan_of_data *data;
>
> -       host = sdhci_pltfm_init(pdev, pdata, sizeof(*sdhci_arasan));
> +       match = of_match_node(sdhci_arasan_of_match, pdev->dev.of_node);
> +       data = match->data;
> +       host = sdhci_pltfm_init(pdev, data->pdata, sizeof(*sdhci_arasan));
>
>         if (IS_ERR(host))
>                 return PTR_ERR(host);
> @@ -723,8 +741,7 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
>         sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
>         sdhci_arasan->host = host;
>
> -       match = of_match_node(sdhci_arasan_of_match, pdev->dev.of_node);
> -       sdhci_arasan->soc_ctl_map = match->data;
> +       sdhci_arasan->soc_ctl_map = data->soc_ctl_map;
>
>         node = of_parse_phandle(pdev->dev.of_node, "arasan,soc-ctl-syscon", 0);
>         if (node) {
> --
> 2.18.0
>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/6] mmc: sdhci-of-arasan: Add Support for AM654 MMC and PHY
  2018-10-04 11:14 ` [PATCH 5/6] mmc: sdhci-of-arasan: Add Support for AM654 MMC and PHY Faiz Abbas
@ 2018-10-09  7:30   ` Ulf Hansson
  2018-10-09  7:35     ` Faiz Abbas
  0 siblings, 1 reply; 18+ messages in thread
From: Ulf Hansson @ 2018-10-09  7:30 UTC (permalink / raw)
  To: Faiz Abbas
  Cc: Linux Kernel Mailing List, DTML, linux-mmc, Kishon, Rob Herring,
	Catalin Marinas, Adrian Hunter

On 4 October 2018 at 13:14, Faiz Abbas <faiz_abbas@ti.com> wrote:
> The current arasan sdhci PHY configuration isn't compatible
> with the PHY on TI's AM654 devices.
>
> Therefore, add a new compatible, AM654 specific quirks
> and a new AM654 specific set_clock function which
> configures the PHY in a sane way.
>
> Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
> Signed-off-by: Sekhar Nori <nsekhar@ti.com>

Applied for next, thanks!

Kind regards
Uffe

> ---
>  drivers/mmc/host/sdhci-of-arasan.c | 46 ++++++++++++++++++++++++++++++
>  1 file changed, 46 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c
> index c9e3e050ccc8..142c4b802f31 100644
> --- a/drivers/mmc/host/sdhci-of-arasan.c
> +++ b/drivers/mmc/host/sdhci-of-arasan.c
> @@ -231,6 +231,25 @@ static void sdhci_arasan_set_clock(struct sdhci_host *host, unsigned int clock)
>         }
>  }
>
> +static void sdhci_arasan_am654_set_clock(struct sdhci_host *host,
> +                                        unsigned int clock)
> +{
> +       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +       struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
> +
> +       if (sdhci_arasan->is_phy_on) {
> +               phy_power_off(sdhci_arasan->phy);
> +               sdhci_arasan->is_phy_on = false;
> +       }
> +
> +       sdhci_set_clock(host, clock);
> +
> +       if (clock > PHY_CLK_TOO_SLOW_HZ) {
> +               phy_power_on(sdhci_arasan->phy);
> +               sdhci_arasan->is_phy_on = true;
> +       }
> +}
> +
>  static void sdhci_arasan_hs400_enhanced_strobe(struct mmc_host *mmc,
>                                         struct mmc_ios *ios)
>  {
> @@ -316,6 +335,29 @@ static struct sdhci_arasan_of_data sdhci_arasan_data = {
>         .pdata = &sdhci_arasan_pdata,
>  };
>
> +static const struct sdhci_ops sdhci_arasan_am654_ops = {
> +       .set_clock = sdhci_arasan_am654_set_clock,
> +       .get_max_clock = sdhci_pltfm_clk_get_max_clock,
> +       .get_timeout_clock = sdhci_pltfm_clk_get_max_clock,
> +       .set_bus_width = sdhci_set_bus_width,
> +       .reset = sdhci_arasan_reset,
> +       .set_uhs_signaling = sdhci_set_uhs_signaling,
> +};
> +
> +static const struct sdhci_pltfm_data sdhci_arasan_am654_pdata = {
> +       .ops = &sdhci_arasan_am654_ops,
> +       .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN  |
> +                 SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
> +                 SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
> +       .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
> +                  SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN |
> +                  SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400,
> +};
> +
> +static const struct sdhci_arasan_of_data sdhci_arasan_am654_data = {
> +       .pdata = &sdhci_arasan_am654_pdata,
> +};
> +
>  static u32 sdhci_arasan_cqhci_irq(struct sdhci_host *host, u32 intmask)
>  {
>         int cmd_error = 0;
> @@ -478,6 +520,10 @@ static const struct of_device_id sdhci_arasan_of_match[] = {
>                 .compatible = "rockchip,rk3399-sdhci-5.1",
>                 .data = &sdhci_arasan_rk3399_data,
>         },
> +       {
> +               .compatible = "ti,am654-sdhci-5.1",
> +               .data = &sdhci_arasan_am654_data,
> +       },
>         /* Generic compatible below here */
>         {
>                 .compatible = "arasan,sdhci-8.9a",
> --
> 2.18.0
>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/6] phy: am654-mmc-phy: Add Support for MMC PHY on AM654 Devices
  2018-10-09  5:18     ` Kishon Vijay Abraham I
@ 2018-10-09  7:30       ` Ulf Hansson
  0 siblings, 0 replies; 18+ messages in thread
From: Ulf Hansson @ 2018-10-09  7:30 UTC (permalink / raw)
  To: Kishon Vijay Abraham I
  Cc: Faiz Abbas, Linux Kernel Mailing List, DTML, linux-mmc,
	Rob Herring, Catalin Marinas, Adrian Hunter

On 9 October 2018 at 07:18, Kishon Vijay Abraham I <kishon@ti.com> wrote:
> Hi Uffe,
>
> On Monday 08 October 2018 05:02 PM, Ulf Hansson wrote:
>> On 4 October 2018 at 13:14, Faiz Abbas <faiz_abbas@ti.com> wrote:
>>> Add driver support for the MMC physical layer present
>>> on TI's AM654 devices.
>>>
>>> Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
>>> Signed-off-by: Sekhar Nori <nsekhar@ti.com>
>>
>> I assume Kishon would like to pick up this through his tree? If not,
>> please tell and I can do it, with his ack.
>
> yes, I'll pick this in my tree.
>

So I have picked patch3, 4 and 5. The rest I leave for you to pick up then.

Kind regards
Uffe

>>
>> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
>
> Thanks
> Kishon
>
>>
>> Kind regards
>> Uffe
>>
>>> ---
>>>  drivers/phy/ti/Kconfig         |   7 +
>>>  drivers/phy/ti/Makefile        |   1 +
>>>  drivers/phy/ti/phy-am654-mmc.c | 291 +++++++++++++++++++++++++++++++++
>>>  3 files changed, 299 insertions(+)
>>>  create mode 100644 drivers/phy/ti/phy-am654-mmc.c
>>>
>>> diff --git a/drivers/phy/ti/Kconfig b/drivers/phy/ti/Kconfig
>>> index 20503562666c..ea5fe4db01c8 100644
>>> --- a/drivers/phy/ti/Kconfig
>>> +++ b/drivers/phy/ti/Kconfig
>>> @@ -76,3 +76,10 @@ config TWL4030_USB
>>>           family chips (including the TWL5030 and TPS659x0 devices).
>>>           This transceiver supports high and full speed devices plus,
>>>           in host mode, low speed.
>>> +
>>> +config PHY_AM654_MMC
>>> +       bool "TI AM654 MMC PHY Support"
>>> +       select GENERIC_PHY
>>> +       help
>>> +         This option enables support for the Physical layer for MMC host
>>> +         controllers present on TI AM654 SOCs.
>>> diff --git a/drivers/phy/ti/Makefile b/drivers/phy/ti/Makefile
>>> index 9f361756eaf2..5b2db2d164a5 100644
>>> --- a/drivers/phy/ti/Makefile
>>> +++ b/drivers/phy/ti/Makefile
>>> @@ -6,3 +6,4 @@ obj-$(CONFIG_OMAP_USB2)                 += phy-omap-usb2.o
>>>  obj-$(CONFIG_TI_PIPE3)                 += phy-ti-pipe3.o
>>>  obj-$(CONFIG_PHY_TUSB1210)             += phy-tusb1210.o
>>>  obj-$(CONFIG_TWL4030_USB)              += phy-twl4030-usb.o
>>> +obj-$(CONFIG_PHY_AM654_MMC)            += phy-am654-mmc.o
>>> diff --git a/drivers/phy/ti/phy-am654-mmc.c b/drivers/phy/ti/phy-am654-mmc.c
>>> new file mode 100644
>>> index 000000000000..91255947fb67
>>> --- /dev/null
>>> +++ b/drivers/phy/ti/phy-am654-mmc.c
>>> @@ -0,0 +1,291 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +/*
>>> + * phy-am654-mmc.c - MMC PHY driver for TI's AM654 SOCs
>>> + *
>>> + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com
>>> + *
>>> + */
>>> +
>>> +#include <linux/clk.h>
>>> +#include <linux/module.h>
>>> +#include <linux/of.h>
>>> +#include <linux/phy/phy.h>
>>> +#include <linux/platform_device.h>
>>> +#include <linux/printk.h>
>>> +#include <linux/regmap.h>
>>> +
>>> +/* MMC PHY Registers */
>>> +#define PHYCTRL_CTRL1_REG      0x00
>>> +#define PHYCTRL_CTRL2_REG      0x04
>>> +#define PHYCTRL_CTRL3_REG      0x08
>>> +#define PHYCTRL_CTRL4_REG      0x0C
>>> +#define PHYCTRL_CTRL5_REG      0x10
>>> +#define PHYCTRL_CTRL6_REG      0x14
>>> +#define PHYCTRL_STAT1_REG      0x30
>>> +#define PHYCTRL_STAT2_REG      0x34
>>> +
>>> +#define IOMUX_ENABLE_SHIFT     31
>>> +#define IOMUX_ENABLE_MASK      BIT(IOMUX_ENABLE_SHIFT)
>>> +#define OTAPDLYENA_SHIFT       20
>>> +#define OTAPDLYENA_MASK        BIT(OTAPDLYENA_SHIFT)
>>> +#define OTAPDLYSEL_SHIFT       12
>>> +#define OTAPDLYSEL_MASK        GENMASK(15, 12)
>>> +#define STRBSEL_SHIFT          24
>>> +#define STRBSEL_MASK           GENMASK(27, 24)
>>> +#define SEL50_SHIFT            8
>>> +#define SEL50_MASK             BIT(SEL50_SHIFT)
>>> +#define SEL100_SHIFT           9
>>> +#define SEL100_MASK            BIT(SEL100_SHIFT)
>>> +#define DLL_TRIM_ICP_SHIFT     4
>>> +#define DLL_TRIM_ICP_MASK      GENMASK(7, 4)
>>> +#define DR_TY_SHIFT            20
>>> +#define DR_TY_MASK             GENMASK(22, 20)
>>> +#define ENDLL_SHIFT            1
>>> +#define ENDLL_MASK             BIT(ENDLL_SHIFT)
>>> +#define DLLRDY_SHIFT           0
>>> +#define DLLRDY_MASK            BIT(DLLRDY_SHIFT)
>>> +#define PDB_SHIFT              0
>>> +#define PDB_MASK               BIT(PDB_SHIFT)
>>> +#define CALDONE_SHIFT          1
>>> +#define CALDONE_MASK           BIT(CALDONE_SHIFT)
>>> +
>>> +#define DRIVER_STRENGTH_50_OHM 0x0
>>> +#define DRIVER_STRENGTH_33_OHM 0x1
>>> +#define DRIVER_STRENGTH_66_OHM 0x2
>>> +#define DRIVER_STRENGTH_100_OHM        0x3
>>> +#define DRIVER_STRENGTH_40_OHM 0x4
>>> +
>>> +static struct regmap_config am654_mmc_phy_regmap_config = {
>>> +       .reg_bits = 32,
>>> +       .val_bits = 32,
>>> +       .reg_stride = 4,
>>> +       .fast_io = true,
>>> +};
>>> +
>>> +struct am654_mmc_phy {
>>> +       struct regmap *reg_base;
>>> +       struct clk *mmcclk;
>>> +       int otap_del_sel;
>>> +       int trm_icp;
>>> +       int drv_strength;
>>> +};
>>> +
>>> +static int am654_mmc_phy_init(struct phy *phy)
>>> +{
>>> +       struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy);
>>> +       int ret;
>>> +       u32 val;
>>> +
>>> +       /* Reset registers to default value */
>>> +       regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL1_REG, 0x10000);
>>> +       regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL4_REG, 0x0);
>>> +       regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL5_REG, 0x0);
>>> +
>>> +       /* Calibrate IO lines */
>>> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
>>> +                          PDB_MASK, PDB_MASK);
>>> +       ret = regmap_read_poll_timeout(mmc_phy->reg_base, PHYCTRL_STAT1_REG,
>>> +                                      val, val & CALDONE_MASK, 1, 20);
>>> +       if (ret)
>>> +               return ret;
>>> +
>>> +       /* Enable pins by setting the IO mux to 0 */
>>> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
>>> +                          IOMUX_ENABLE_MASK, 0);
>>> +
>>> +       mmc_phy->mmcclk = clk_get(&phy->dev, "mmcclk");
>>> +       if (IS_ERR(mmc_phy->mmcclk)) {
>>> +               dev_err(&phy->dev, "Error getting mmcclk");
>>> +               return PTR_ERR(mmc_phy->mmcclk);
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int am654_mmc_phy_exit(struct phy *phy)
>>> +{
>>> +       struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy);
>>> +
>>> +       clk_put(mmc_phy->mmcclk);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int am654_mmc_phy_power_on(struct phy *phy)
>>> +{
>>> +       struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy);
>>> +       u32 mask, val;
>>> +       int sel50, sel100;
>>> +       int rate;
>>> +
>>> +       /* Setup DLL Output TAP delay */
>>> +       mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
>>> +       val = (1 << OTAPDLYENA_SHIFT) |
>>> +             (mmc_phy->otap_del_sel << OTAPDLYSEL_SHIFT);
>>> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL4_REG,
>>> +                          mask, val);
>>> +
>>> +       rate = clk_get_rate(mmc_phy->mmcclk);
>>> +       switch (rate) {
>>> +       case 200000000:
>>> +               sel50 = 0;
>>> +               sel100 = 0;
>>> +               break;
>>> +       case 100000000:
>>> +               sel50 = 0;
>>> +               sel100 = 1;
>>> +               break;
>>> +       default:
>>> +               sel50 = 1;
>>> +               sel100 = 0;
>>> +       }
>>> +
>>> +       /* Configure PHY DLL frequency */
>>> +       mask = SEL50_MASK | SEL100_MASK;
>>> +       val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT);
>>> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL5_REG,
>>> +                          mask, val);
>>> +
>>> +       /* Configure DLL TRIM */
>>> +       mask = DLL_TRIM_ICP_MASK;
>>> +       val = mmc_phy->trm_icp << DLL_TRIM_ICP_SHIFT;
>>> +
>>> +       /* Configure DLL driver strength */
>>> +       mask |= DR_TY_MASK;
>>> +       val |= mmc_phy->drv_strength << DR_TY_SHIFT;
>>> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG, mask, val);
>>> +
>>> +       /* Enable DLL */
>>> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
>>> +                          ENDLL_MASK, 0x1 << ENDLL_SHIFT);
>>> +
>>> +       /*
>>> +        * Poll for DLL ready. Use a one second timeout.
>>> +        * Works in all experiments done so far
>>> +        */
>>> +       return regmap_read_poll_timeout(mmc_phy->reg_base, PHYCTRL_STAT1_REG,
>>> +                                       val, val & DLLRDY_MASK, 1000, 1000000);
>>> +
>>> +}
>>> +
>>> +static int am654_mmc_phy_power_off(struct phy *phy)
>>> +{
>>> +       struct am654_mmc_phy *mmc_phy = phy_get_drvdata(phy);
>>> +
>>> +       /* Disable DLL */
>>> +       regmap_update_bits(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
>>> +                          ENDLL_MASK, 0);
>>> +
>>> +       /* Reset registers to default value except PDB */
>>> +       regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL1_REG,
>>> +                    0x10000 | PDB_MASK);
>>> +       regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL4_REG, 0x0);
>>> +       regmap_write(mmc_phy->reg_base, PHYCTRL_CTRL5_REG, 0x0);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static const struct phy_ops ops = {
>>> +       .init           = am654_mmc_phy_init,
>>> +       .exit           = am654_mmc_phy_exit,
>>> +       .power_on       = am654_mmc_phy_power_on,
>>> +       .power_off      = am654_mmc_phy_power_off,
>>> +       .owner          = THIS_MODULE,
>>> +};
>>> +
>>> +static int am654_mmc_phy_probe(struct platform_device *pdev)
>>> +{
>>> +       struct phy_provider *phy_provider;
>>> +       struct device *dev = &pdev->dev;
>>> +       struct device_node *np = dev->of_node;
>>> +       struct am654_mmc_phy *mmc_phy;
>>> +       struct phy *generic_phy;
>>> +       struct resource *res;
>>> +       void __iomem *base;
>>> +       struct regmap *map;
>>> +       int drv_strength;
>>> +       int err;
>>> +
>>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> +       base = devm_ioremap_resource(&pdev->dev, res);
>>> +       if (IS_ERR(base))
>>> +               return PTR_ERR(base);
>>> +
>>> +       map = devm_regmap_init_mmio(dev, base, &am654_mmc_phy_regmap_config);
>>> +       if (IS_ERR(map)) {
>>> +               dev_err(dev, "could not initialize regmap\n");
>>> +               return PTR_ERR(map);
>>> +       }
>>> +
>>> +       mmc_phy = devm_kzalloc(dev, sizeof(struct am654_mmc_phy), GFP_KERNEL);
>>> +       if (!mmc_phy)
>>> +               return -ENOMEM;
>>> +
>>> +       mmc_phy->reg_base = map;
>>> +       err = of_property_read_u32(np, "ti,otap-del-sel",
>>> +                                  &mmc_phy->otap_del_sel);
>>> +       if (err)
>>> +               return err;
>>> +
>>> +       err = of_property_read_u32(np, "ti,trm-icp",
>>> +                                  &mmc_phy->trm_icp);
>>> +       if (err)
>>> +               return err;
>>> +
>>> +       err = of_property_read_u32(np, "ti,driver-strength-ohm", &drv_strength);
>>> +       if (err)
>>> +               return err;
>>> +
>>> +       switch (drv_strength) {
>>> +       case 50:
>>> +               mmc_phy->drv_strength = DRIVER_STRENGTH_50_OHM;
>>> +               break;
>>> +       case 33:
>>> +               mmc_phy->drv_strength = DRIVER_STRENGTH_33_OHM;
>>> +               break;
>>> +       case 66:
>>> +               mmc_phy->drv_strength = DRIVER_STRENGTH_66_OHM;
>>> +               break;
>>> +       case 100:
>>> +               mmc_phy->drv_strength = DRIVER_STRENGTH_100_OHM;
>>> +               break;
>>> +       case 40:
>>> +               mmc_phy->drv_strength = DRIVER_STRENGTH_40_OHM;
>>> +               break;
>>> +       default:
>>> +               dev_err(dev, "Invalid driver strength\n");
>>> +               return -EINVAL;
>>> +       }
>>> +
>>> +       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, mmc_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 am654_mmc_phy_dt_ids[] = {
>>> +       { .compatible = "ti,am654-mmc-phy" },
>>> +       {}
>>> +};
>>> +
>>> +MODULE_DEVICE_TABLE(of, am654_mmc_phy_dt_ids);
>>> +
>>> +static struct platform_driver am654_mmc_phy_driver = {
>>> +       .probe          = am654_mmc_phy_probe,
>>> +       .driver         = {
>>> +               .name   = "am654-mmc-phy",
>>> +               .of_match_table = am654_mmc_phy_dt_ids,
>>> +       },
>>> +};
>>> +
>>> +module_platform_driver(am654_mmc_phy_driver);
>>> +
>>> +MODULE_AUTHOR("Faiz Abbas <faiz_abbas@ti.com>");
>>> +MODULE_DESCRIPTION("TI AM654 MMC PHY driver");
>>> +MODULE_LICENSE("GPL v2");
>>> --
>>> 2.18.0
>>>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/6] mmc: sdhci-of-arasan: Add Support for AM654 MMC and PHY
  2018-10-09  7:35     ` Faiz Abbas
@ 2018-10-09  7:35       ` Ulf Hansson
  0 siblings, 0 replies; 18+ messages in thread
From: Ulf Hansson @ 2018-10-09  7:35 UTC (permalink / raw)
  To: Faiz Abbas
  Cc: Linux Kernel Mailing List, DTML, linux-mmc, Kishon, Rob Herring,
	Catalin Marinas, Adrian Hunter

On 9 October 2018 at 09:35, Faiz Abbas <faiz_abbas@ti.com> wrote:
> Hi Uffe,
>
> On Tuesday 09 October 2018 01:00 PM, Ulf Hansson wrote:
>> On 4 October 2018 at 13:14, Faiz Abbas <faiz_abbas@ti.com> wrote:
>>> The current arasan sdhci PHY configuration isn't compatible
>>> with the PHY on TI's AM654 devices.
>>>
>>> Therefore, add a new compatible, AM654 specific quirks
>>> and a new AM654 specific set_clock function which
>>> configures the PHY in a sane way.
>>>
>>> Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
>>> Signed-off-by: Sekhar Nori <nsekhar@ti.com>
>>
>> Applied for next, thanks!
>>
>
> Do I need to repost these in the v2 ?

No. It's okay if you drop them from the series.

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/6] mmc: sdhci-of-arasan: Add Support for AM654 MMC and PHY
  2018-10-09  7:30   ` Ulf Hansson
@ 2018-10-09  7:35     ` Faiz Abbas
  2018-10-09  7:35       ` Ulf Hansson
  0 siblings, 1 reply; 18+ messages in thread
From: Faiz Abbas @ 2018-10-09  7:35 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Linux Kernel Mailing List, DTML, linux-mmc, Kishon, Rob Herring,
	Catalin Marinas, Adrian Hunter

Hi Uffe,

On Tuesday 09 October 2018 01:00 PM, Ulf Hansson wrote:
> On 4 October 2018 at 13:14, Faiz Abbas <faiz_abbas@ti.com> wrote:
>> The current arasan sdhci PHY configuration isn't compatible
>> with the PHY on TI's AM654 devices.
>>
>> Therefore, add a new compatible, AM654 specific quirks
>> and a new AM654 specific set_clock function which
>> configures the PHY in a sane way.
>>
>> Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
>> Signed-off-by: Sekhar Nori <nsekhar@ti.com>
> 
> Applied for next, thanks!
> 

Do I need to repost these in the v2 ?

Thanks,
Faiz

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2018-10-09  7:35 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-04 11:14 [PATCH 0/6] Add Support for MMC/SD in TI's AM65x SOCs Faiz Abbas
2018-10-04 11:14 ` [PATCH 1/6] dt-bindings: phy: am654-mmc-phy: Document new phy bindings Faiz Abbas
2018-10-05 15:58   ` Andrew F. Davis
2018-10-09  6:34     ` Faiz Abbas
2018-10-08 11:29   ` Ulf Hansson
2018-10-04 11:14 ` [PATCH 2/6] phy: am654-mmc-phy: Add Support for MMC PHY on AM654 Devices Faiz Abbas
2018-10-08 11:32   ` Ulf Hansson
2018-10-09  5:18     ` Kishon Vijay Abraham I
2018-10-09  7:30       ` Ulf Hansson
2018-10-04 11:14 ` [PATCH 3/6] dt-bindings: mmc: sdhci-of-arasan: Add new compatible for AM654 MMC PHY Faiz Abbas
2018-10-09  7:30   ` Ulf Hansson
2018-10-04 11:14 ` [PATCH 4/6] mmc: sdhci-of-arasan: Add a single data structure to incorporate pdata and soc_ctl_map Faiz Abbas
2018-10-09  7:30   ` Ulf Hansson
2018-10-04 11:14 ` [PATCH 5/6] mmc: sdhci-of-arasan: Add Support for AM654 MMC and PHY Faiz Abbas
2018-10-09  7:30   ` Ulf Hansson
2018-10-09  7:35     ` Faiz Abbas
2018-10-09  7:35       ` Ulf Hansson
2018-10-04 11:14 ` [PATCH 6/6] arm64: defconfig: Enable MMC PHY for AM65xx Faiz Abbas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).