Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dff8939c authored by Yaniv Gardi's avatar Yaniv Gardi
Browse files

scsi: ufs: separate dependency between UFS_QCOM and UFSHCD_PLATFORM



This change disconnects the dependency between the SCSI_UFSHCD_PLATFORM
and SCSI_UFS_QCOM.

It does so by adding the following changes:
1. Introducing SCSI_UFS_QCOM as a platform device. Its probe
   function registers a set of vops to its driver_data.
2. Adding an optional device tree sub-node, under SCSI_UFSHCD_PLATFORM.
   Now, the probe function of SCSI_UFSHCD_PLATFORM invokes the probe
   function of its sub-node (if it exists), by calling
   of_platform_populate(). It ensures that vops are set, and ready to
   be used, by the time the UFSHCD driver starts its initialization
   procedure.

Change-Id: Iaa80d2f6e3fd6f6526911064b3c39605aca96ccc
Signed-off-by: default avatarYaniv Gardi <ygardi@codeaurora.org>
parent b7eacff0
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -76,8 +76,8 @@ Example:
		spm-level = <5>;
	};

==== MSM UFS platform driver properties =====
* For UFS host controller in MSM platform following clocks are required -
==== UFS QCOM platform driver properties =====
* For UFS host controller in QCOM platform following clocks are required -
    Controller clock source -
        "core_clk_src", max-clock-frequency-hz = 200MHz
	"core_clk_unipro_src" - Some controller versions require separate core clock for UniPro.
@@ -177,3 +177,11 @@ Example:
					"HS_RB_G1_L2", "HS_RB_G2_L2", "HS_RB_G3_L2",
					"MAX";
	};

This is an example to a variant sub-node of ufshc:
ufs_variant {
	compatible = "qcom,ufs_variant";
};

This sub-node holds various specific information that is not defined in the
standard and that may differ between platforms.
+1 −0
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ lantiq Lantiq Semiconductor
lenovo	Lenovo Group Ltd.
invn	InvenSense Inc.
isl	Intersil
jedec	Jedec Solid State Technology Association
karo	Ka-Ro electronics GmbH
kionix	Kionix Inc.
lattice	Lattice Semiconductor.
+5 −1
Original line number Diff line number Diff line
@@ -1219,7 +1219,7 @@
	};

	ufs1: ufshc@624000 {
		compatible = "qcom,ufshc";
		compatible = "jedec,ufs-1.1";
		reg = <0x624000 0x2500>;
		interrupts = <0 265 0>;
		phys = <&ufsphy1>;
@@ -1304,6 +1304,10 @@
		qcom,cpu-dma-latency-us = <301>;

		status = "disabled";

		ufs_variant {
			compatible = "qcom,ufs_variant";
		};
	};

	pcie0: qcom,pcie@00600000 {
+40 −0
Original line number Diff line number Diff line
@@ -1783,6 +1783,46 @@ static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
	ufs_qcom_ice_print_regs(host);
}

/**
 * ufs_qcom_probe - probe routine of the driver
 * @pdev: pointer to platform device handle
 *
 * Always returns 0
 */
static int ufs_qcom_probe(struct platform_device *pdev)
{
	dev_set_drvdata(&pdev->dev, (void *)&ufs_hba_qcom_vops);
	return 0;
}

/**
 * ufs_qcom_remove - set driver_data of the device to NULL
 * @pdev: pointer to platform device handle
 *
 * Always returns 0
 */
static int ufs_qcom_remove(struct platform_device *pdev)
{
	dev_set_drvdata(&pdev->dev, NULL);
	return 0;
}

static const struct of_device_id ufs_qcom_of_match[] = {
	{ .compatible = "qcom,ufs_variant"},
	{},
};

static struct platform_driver ufs_qcom_pltform = {
	.probe	= ufs_qcom_probe,
	.remove	= ufs_qcom_remove,
	.driver	= {
		.name	= "ufs_qcom",
		.owner	= THIS_MODULE,
		.of_match_table = of_match_ptr(ufs_qcom_of_match),
	},
};
module_platform_driver(ufs_qcom_pltform);

/**
 * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
 *
+22 −14
Original line number Diff line number Diff line
@@ -36,22 +36,11 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/of_platform.h>

#include "ufshcd.h"

static const struct of_device_id ufs_of_match[];
static struct ufs_hba_variant_ops *get_variant_ops(struct device *dev)
{
	if (dev->of_node) {
		const struct of_device_id *match;

		match = of_match_node(ufs_of_match, dev->of_node);
		if (match)
			return (struct ufs_hba_variant_ops *)match->data;
	}

	return NULL;
}

static int ufshcd_parse_clock_info(struct ufs_hba *hba)
{
@@ -350,6 +339,9 @@ static int ufshcd_pltfrm_probe(struct platform_device *pdev)
	struct resource *mem_res;
	int irq, err;
	struct device *dev = &pdev->dev;
	struct device_node *node = pdev->dev.of_node;
	struct device_node *ufs_variant_node;
	struct platform_device *ufs_variant_pdev;

	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	mmio_base = devm_ioremap_resource(dev, mem_res);
@@ -371,7 +363,24 @@ static int ufshcd_pltfrm_probe(struct platform_device *pdev)
		goto out;
	}

	hba->vops = get_variant_ops(&pdev->dev);
	err = of_platform_populate(node, NULL, NULL, &pdev->dev);
	if (err) {
		dev_err(&pdev->dev,
			"%s: of_platform_populate() failed\n", __func__);
	} else {
		ufs_variant_node = of_get_next_available_child(node, NULL);

		if (!ufs_variant_node) {
			dev_dbg(&pdev->dev, "no ufs_variant_node found\n");
		} else {
			ufs_variant_pdev =
				of_find_device_by_node(ufs_variant_node);

			if (ufs_variant_pdev)
				hba->vops = (struct ufs_hba_variant_ops *)
				     dev_get_drvdata(&ufs_variant_pdev->dev);
		}
	}

	err = ufshcd_parse_clock_info(hba);
	if (err) {
@@ -428,7 +437,6 @@ static int ufshcd_pltfrm_remove(struct platform_device *pdev)

static const struct of_device_id ufs_of_match[] = {
	{ .compatible = "jedec,ufs-1.1"},
	{ .compatible = "qcom,ufshc", .data = (void *)&ufs_hba_qcom_vops, },
	{},
};