lkml.org 
[lkml]   [2015]   [Jun]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 4/4] scsi: ufs: probe and init of variant driver from the platform device
    Date
    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.

    Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>

    ---
    .../devicetree/bindings/ufs/ufshcd-pltfrm.txt | 8 +++++
    drivers/scsi/ufs/ufs-qcom.c | 40 ++++++++++++++++++++++
    drivers/scsi/ufs/ufshcd-pltfrm.c | 33 +++++++++++-------
    3 files changed, 68 insertions(+), 13 deletions(-)

    diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
    index 5357919..e2f3058 100644
    --- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
    +++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
    @@ -55,3 +55,11 @@ Example:
    clock-names = "core_clk", "ref_clk", "iface_clk";
    freq-table-hz = <100000000 200000000>, <0 0>, <0 0>;
    };
    +
    +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.
    diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
    index 6671a8e..ad5ffa8 100644
    --- a/drivers/scsi/ufs/ufs-qcom.c
    +++ b/drivers/scsi/ufs/ufs-qcom.c
    @@ -1018,4 +1018,44 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
    };
    EXPORT_SYMBOL(ufs_hba_qcom_vops);

    +/**
    + * ufs_qcom_probe - probe routine of the driver
    + * @pdev: pointer to Platform device handle
    + *
    + * Always return 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 return 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);
    +
    MODULE_LICENSE("GPL v2");
    diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
    index 7db9564..7bf2f44 100644
    --- a/drivers/scsi/ufs/ufshcd-pltfrm.c
    +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
    @@ -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)
    {
    @@ -300,6 +289,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);
    @@ -321,7 +313,22 @@ 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__);
    +
    + ufs_variant_node = of_get_next_available_child(node, NULL);
    +
    + if (!ufs_variant_node) {
    + dev_dbg(&pdev->dev, "failed to find ufs_variant_node child\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) {
    --
    1.8.5.2
    --
    QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation


    \
     
     \ /
      Last update: 2015-06-03 12:01    [W:2.725 / U:0.080 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site