root/drivers/usb/dwc3/dwc3-of-simple.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dwc3_of_simple_probe
  2. dwc3_of_simple_remove
  3. dwc3_of_simple_runtime_suspend
  4. dwc3_of_simple_runtime_resume
  5. dwc3_of_simple_suspend
  6. dwc3_of_simple_resume

   1 // SPDX-License-Identifier: GPL-2.0
   2 /**
   3  * dwc3-of-simple.c - OF glue layer for simple integrations
   4  *
   5  * Copyright (c) 2015 Texas Instruments Incorporated - http://www.ti.com
   6  *
   7  * Author: Felipe Balbi <balbi@ti.com>
   8  *
   9  * This is a combination of the old dwc3-qcom.c by Ivan T. Ivanov
  10  * <iivanov@mm-sol.com> and the original patch adding support for Xilinx' SoC
  11  * by Subbaraya Sundeep Bhatta <subbaraya.sundeep.bhatta@xilinx.com>
  12  */
  13 
  14 #include <linux/module.h>
  15 #include <linux/kernel.h>
  16 #include <linux/slab.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/dma-mapping.h>
  19 #include <linux/clk.h>
  20 #include <linux/of.h>
  21 #include <linux/of_platform.h>
  22 #include <linux/pm_runtime.h>
  23 #include <linux/reset.h>
  24 
  25 struct dwc3_of_simple {
  26         struct device           *dev;
  27         struct clk_bulk_data    *clks;
  28         int                     num_clocks;
  29         struct reset_control    *resets;
  30         bool                    pulse_resets;
  31         bool                    need_reset;
  32 };
  33 
  34 static int dwc3_of_simple_probe(struct platform_device *pdev)
  35 {
  36         struct dwc3_of_simple   *simple;
  37         struct device           *dev = &pdev->dev;
  38         struct device_node      *np = dev->of_node;
  39 
  40         int                     ret;
  41         bool                    shared_resets = false;
  42 
  43         simple = devm_kzalloc(dev, sizeof(*simple), GFP_KERNEL);
  44         if (!simple)
  45                 return -ENOMEM;
  46 
  47         platform_set_drvdata(pdev, simple);
  48         simple->dev = dev;
  49 
  50         /*
  51          * Some controllers need to toggle the usb3-otg reset before trying to
  52          * initialize the PHY, otherwise the PHY times out.
  53          */
  54         if (of_device_is_compatible(np, "rockchip,rk3399-dwc3"))
  55                 simple->need_reset = true;
  56 
  57         if (of_device_is_compatible(np, "amlogic,meson-axg-dwc3") ||
  58             of_device_is_compatible(np, "amlogic,meson-gxl-dwc3")) {
  59                 shared_resets = true;
  60                 simple->pulse_resets = true;
  61         }
  62 
  63         simple->resets = of_reset_control_array_get(np, shared_resets, true,
  64                                                     true);
  65         if (IS_ERR(simple->resets)) {
  66                 ret = PTR_ERR(simple->resets);
  67                 dev_err(dev, "failed to get device resets, err=%d\n", ret);
  68                 return ret;
  69         }
  70 
  71         if (simple->pulse_resets) {
  72                 ret = reset_control_reset(simple->resets);
  73                 if (ret)
  74                         goto err_resetc_put;
  75         } else {
  76                 ret = reset_control_deassert(simple->resets);
  77                 if (ret)
  78                         goto err_resetc_put;
  79         }
  80 
  81         ret = clk_bulk_get_all(simple->dev, &simple->clks);
  82         if (ret < 0)
  83                 goto err_resetc_assert;
  84 
  85         simple->num_clocks = ret;
  86         ret = clk_bulk_prepare_enable(simple->num_clocks, simple->clks);
  87         if (ret)
  88                 goto err_resetc_assert;
  89 
  90         ret = of_platform_populate(np, NULL, NULL, dev);
  91         if (ret)
  92                 goto err_clk_put;
  93 
  94         pm_runtime_set_active(dev);
  95         pm_runtime_enable(dev);
  96         pm_runtime_get_sync(dev);
  97 
  98         return 0;
  99 
 100 err_clk_put:
 101         clk_bulk_disable_unprepare(simple->num_clocks, simple->clks);
 102         clk_bulk_put_all(simple->num_clocks, simple->clks);
 103 
 104 err_resetc_assert:
 105         if (!simple->pulse_resets)
 106                 reset_control_assert(simple->resets);
 107 
 108 err_resetc_put:
 109         reset_control_put(simple->resets);
 110         return ret;
 111 }
 112 
 113 static int dwc3_of_simple_remove(struct platform_device *pdev)
 114 {
 115         struct dwc3_of_simple   *simple = platform_get_drvdata(pdev);
 116         struct device           *dev = &pdev->dev;
 117 
 118         of_platform_depopulate(dev);
 119 
 120         clk_bulk_disable_unprepare(simple->num_clocks, simple->clks);
 121         clk_bulk_put_all(simple->num_clocks, simple->clks);
 122         simple->num_clocks = 0;
 123 
 124         if (!simple->pulse_resets)
 125                 reset_control_assert(simple->resets);
 126 
 127         reset_control_put(simple->resets);
 128 
 129         pm_runtime_disable(dev);
 130         pm_runtime_put_noidle(dev);
 131         pm_runtime_set_suspended(dev);
 132 
 133         return 0;
 134 }
 135 
 136 static int __maybe_unused dwc3_of_simple_runtime_suspend(struct device *dev)
 137 {
 138         struct dwc3_of_simple   *simple = dev_get_drvdata(dev);
 139 
 140         clk_bulk_disable(simple->num_clocks, simple->clks);
 141 
 142         return 0;
 143 }
 144 
 145 static int __maybe_unused dwc3_of_simple_runtime_resume(struct device *dev)
 146 {
 147         struct dwc3_of_simple   *simple = dev_get_drvdata(dev);
 148 
 149         return clk_bulk_enable(simple->num_clocks, simple->clks);
 150 }
 151 
 152 static int __maybe_unused dwc3_of_simple_suspend(struct device *dev)
 153 {
 154         struct dwc3_of_simple *simple = dev_get_drvdata(dev);
 155 
 156         if (simple->need_reset)
 157                 reset_control_assert(simple->resets);
 158 
 159         return 0;
 160 }
 161 
 162 static int __maybe_unused dwc3_of_simple_resume(struct device *dev)
 163 {
 164         struct dwc3_of_simple *simple = dev_get_drvdata(dev);
 165 
 166         if (simple->need_reset)
 167                 reset_control_deassert(simple->resets);
 168 
 169         return 0;
 170 }
 171 
 172 static const struct dev_pm_ops dwc3_of_simple_dev_pm_ops = {
 173         SET_SYSTEM_SLEEP_PM_OPS(dwc3_of_simple_suspend, dwc3_of_simple_resume)
 174         SET_RUNTIME_PM_OPS(dwc3_of_simple_runtime_suspend,
 175                         dwc3_of_simple_runtime_resume, NULL)
 176 };
 177 
 178 static const struct of_device_id of_dwc3_simple_match[] = {
 179         { .compatible = "rockchip,rk3399-dwc3" },
 180         { .compatible = "xlnx,zynqmp-dwc3" },
 181         { .compatible = "cavium,octeon-7130-usb-uctl" },
 182         { .compatible = "sprd,sc9860-dwc3" },
 183         { .compatible = "amlogic,meson-axg-dwc3" },
 184         { .compatible = "amlogic,meson-gxl-dwc3" },
 185         { .compatible = "allwinner,sun50i-h6-dwc3" },
 186         { /* Sentinel */ }
 187 };
 188 MODULE_DEVICE_TABLE(of, of_dwc3_simple_match);
 189 
 190 static struct platform_driver dwc3_of_simple_driver = {
 191         .probe          = dwc3_of_simple_probe,
 192         .remove         = dwc3_of_simple_remove,
 193         .driver         = {
 194                 .name   = "dwc3-of-simple",
 195                 .of_match_table = of_dwc3_simple_match,
 196                 .pm     = &dwc3_of_simple_dev_pm_ops,
 197         },
 198 };
 199 
 200 module_platform_driver(dwc3_of_simple_driver);
 201 MODULE_LICENSE("GPL v2");
 202 MODULE_DESCRIPTION("DesignWare USB3 OF Simple Glue Layer");
 203 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");

/* [<][>][^][v][top][bottom][index][help] */