15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
226ef796fSLee Jones /*
316adc674SFelipe Balbi * dwc3-of-simple.c - OF glue layer for simple integrations
416adc674SFelipe Balbi *
510623b87SAlexander A. Klimov * Copyright (c) 2015 Texas Instruments Incorporated - https://www.ti.com
616adc674SFelipe Balbi *
716adc674SFelipe Balbi * Author: Felipe Balbi <balbi@ti.com>
816adc674SFelipe Balbi *
916adc674SFelipe Balbi * This is a combination of the old dwc3-qcom.c by Ivan T. Ivanov
1016adc674SFelipe Balbi * <iivanov@mm-sol.com> and the original patch adding support for Xilinx' SoC
1116adc674SFelipe Balbi * by Subbaraya Sundeep Bhatta <subbaraya.sundeep.bhatta@xilinx.com>
1216adc674SFelipe Balbi */
1316adc674SFelipe Balbi
1416adc674SFelipe Balbi #include <linux/module.h>
1516adc674SFelipe Balbi #include <linux/kernel.h>
1616adc674SFelipe Balbi #include <linux/slab.h>
1716adc674SFelipe Balbi #include <linux/platform_device.h>
1816adc674SFelipe Balbi #include <linux/dma-mapping.h>
1916adc674SFelipe Balbi #include <linux/clk.h>
2016adc674SFelipe Balbi #include <linux/of.h>
2116adc674SFelipe Balbi #include <linux/of_platform.h>
2216adc674SFelipe Balbi #include <linux/pm_runtime.h>
2306c47e62SVivek Gautam #include <linux/reset.h>
2416adc674SFelipe Balbi
2516adc674SFelipe Balbi struct dwc3_of_simple {
2616adc674SFelipe Balbi struct device *dev;
27c0c61471SRobin Murphy struct clk_bulk_data *clks;
2816adc674SFelipe Balbi int num_clocks;
2906c47e62SVivek Gautam struct reset_control *resets;
3076251db8SEnric Balletbo i Serra bool need_reset;
3116adc674SFelipe Balbi };
3216adc674SFelipe Balbi
dwc3_of_simple_probe(struct platform_device * pdev)3326c9cac4SFelipe Balbi static int dwc3_of_simple_probe(struct platform_device *pdev)
3426c9cac4SFelipe Balbi {
3526c9cac4SFelipe Balbi struct dwc3_of_simple *simple;
3626c9cac4SFelipe Balbi struct device *dev = &pdev->dev;
3726c9cac4SFelipe Balbi struct device_node *np = dev->of_node;
3826c9cac4SFelipe Balbi
3926c9cac4SFelipe Balbi int ret;
4026c9cac4SFelipe Balbi
4126c9cac4SFelipe Balbi simple = devm_kzalloc(dev, sizeof(*simple), GFP_KERNEL);
4226c9cac4SFelipe Balbi if (!simple)
4326c9cac4SFelipe Balbi return -ENOMEM;
4426c9cac4SFelipe Balbi
4526c9cac4SFelipe Balbi platform_set_drvdata(pdev, simple);
4626c9cac4SFelipe Balbi simple->dev = dev;
4726c9cac4SFelipe Balbi
4876251db8SEnric Balletbo i Serra /*
4976251db8SEnric Balletbo i Serra * Some controllers need to toggle the usb3-otg reset before trying to
5076251db8SEnric Balletbo i Serra * initialize the PHY, otherwise the PHY times out.
5176251db8SEnric Balletbo i Serra */
5276251db8SEnric Balletbo i Serra if (of_device_is_compatible(np, "rockchip,rk3399-dwc3"))
5376251db8SEnric Balletbo i Serra simple->need_reset = true;
5476251db8SEnric Balletbo i Serra
55f4cc91ddSMartin Blumenstingl simple->resets = of_reset_control_array_get(np, false, true,
56f31d5c24SThierry Reding true);
5706c47e62SVivek Gautam if (IS_ERR(simple->resets)) {
5806c47e62SVivek Gautam ret = PTR_ERR(simple->resets);
5906c47e62SVivek Gautam dev_err(dev, "failed to get device resets, err=%d\n", ret);
6006c47e62SVivek Gautam return ret;
6106c47e62SVivek Gautam }
6206c47e62SVivek Gautam
6306c47e62SVivek Gautam ret = reset_control_deassert(simple->resets);
6406c47e62SVivek Gautam if (ret)
6506c47e62SVivek Gautam goto err_resetc_put;
6606c47e62SVivek Gautam
67c0c61471SRobin Murphy ret = clk_bulk_get_all(simple->dev, &simple->clks);
68c0c61471SRobin Murphy if (ret < 0)
69c0c61471SRobin Murphy goto err_resetc_assert;
70c0c61471SRobin Murphy
71c0c61471SRobin Murphy simple->num_clocks = ret;
72c0c61471SRobin Murphy ret = clk_bulk_prepare_enable(simple->num_clocks, simple->clks);
7326c9cac4SFelipe Balbi if (ret)
7406c47e62SVivek Gautam goto err_resetc_assert;
7526c9cac4SFelipe Balbi
7616adc674SFelipe Balbi ret = of_platform_populate(np, NULL, NULL, dev);
77c0c61471SRobin Murphy if (ret)
78c0c61471SRobin Murphy goto err_clk_put;
7916adc674SFelipe Balbi
8016adc674SFelipe Balbi pm_runtime_set_active(dev);
8116adc674SFelipe Balbi pm_runtime_enable(dev);
8216adc674SFelipe Balbi pm_runtime_get_sync(dev);
8316adc674SFelipe Balbi
8416adc674SFelipe Balbi return 0;
8506c47e62SVivek Gautam
86c0c61471SRobin Murphy err_clk_put:
87c0c61471SRobin Murphy clk_bulk_disable_unprepare(simple->num_clocks, simple->clks);
88c0c61471SRobin Murphy clk_bulk_put_all(simple->num_clocks, simple->clks);
89c0c61471SRobin Murphy
9006c47e62SVivek Gautam err_resetc_assert:
9106c47e62SVivek Gautam reset_control_assert(simple->resets);
9206c47e62SVivek Gautam
9306c47e62SVivek Gautam err_resetc_put:
9406c47e62SVivek Gautam reset_control_put(simple->resets);
9506c47e62SVivek Gautam return ret;
9616adc674SFelipe Balbi }
9716adc674SFelipe Balbi
__dwc3_of_simple_teardown(struct dwc3_of_simple * simple)98726b4fbaSFelipe Balbi static void __dwc3_of_simple_teardown(struct dwc3_of_simple *simple)
9916adc674SFelipe Balbi {
100726b4fbaSFelipe Balbi of_platform_depopulate(simple->dev);
101d6d9c2a3SVivek Gautam
102c0c61471SRobin Murphy clk_bulk_disable_unprepare(simple->num_clocks, simple->clks);
103c0c61471SRobin Murphy clk_bulk_put_all(simple->num_clocks, simple->clks);
104bff52352SEnric Balletbo i Serra simple->num_clocks = 0;
10516adc674SFelipe Balbi
10606c47e62SVivek Gautam reset_control_assert(simple->resets);
107ff0a632fSMartin Blumenstingl
10806c47e62SVivek Gautam reset_control_put(simple->resets);
10906c47e62SVivek Gautam
110726b4fbaSFelipe Balbi pm_runtime_disable(simple->dev);
111726b4fbaSFelipe Balbi pm_runtime_put_noidle(simple->dev);
112726b4fbaSFelipe Balbi pm_runtime_set_suspended(simple->dev);
113726b4fbaSFelipe Balbi }
114726b4fbaSFelipe Balbi
dwc3_of_simple_remove(struct platform_device * pdev)115*86a2b452SUwe Kleine-König static void dwc3_of_simple_remove(struct platform_device *pdev)
116726b4fbaSFelipe Balbi {
117726b4fbaSFelipe Balbi struct dwc3_of_simple *simple = platform_get_drvdata(pdev);
118726b4fbaSFelipe Balbi
119726b4fbaSFelipe Balbi __dwc3_of_simple_teardown(simple);
12016adc674SFelipe Balbi }
12116adc674SFelipe Balbi
dwc3_of_simple_shutdown(struct platform_device * pdev)122726b4fbaSFelipe Balbi static void dwc3_of_simple_shutdown(struct platform_device *pdev)
123726b4fbaSFelipe Balbi {
124726b4fbaSFelipe Balbi struct dwc3_of_simple *simple = platform_get_drvdata(pdev);
125726b4fbaSFelipe Balbi
126726b4fbaSFelipe Balbi __dwc3_of_simple_teardown(simple);
127726b4fbaSFelipe Balbi }
128726b4fbaSFelipe Balbi
dwc3_of_simple_runtime_suspend(struct device * dev)12966174b69SArnd Bergmann static int __maybe_unused dwc3_of_simple_runtime_suspend(struct device *dev)
13016adc674SFelipe Balbi {
13116adc674SFelipe Balbi struct dwc3_of_simple *simple = dev_get_drvdata(dev);
13216adc674SFelipe Balbi
133c0c61471SRobin Murphy clk_bulk_disable(simple->num_clocks, simple->clks);
13416adc674SFelipe Balbi
13516adc674SFelipe Balbi return 0;
13616adc674SFelipe Balbi }
13716adc674SFelipe Balbi
dwc3_of_simple_runtime_resume(struct device * dev)13866174b69SArnd Bergmann static int __maybe_unused dwc3_of_simple_runtime_resume(struct device *dev)
13916adc674SFelipe Balbi {
14016adc674SFelipe Balbi struct dwc3_of_simple *simple = dev_get_drvdata(dev);
14116adc674SFelipe Balbi
142c0c61471SRobin Murphy return clk_bulk_enable(simple->num_clocks, simple->clks);
14316adc674SFelipe Balbi }
14476251db8SEnric Balletbo i Serra
dwc3_of_simple_suspend(struct device * dev)14566174b69SArnd Bergmann static int __maybe_unused dwc3_of_simple_suspend(struct device *dev)
14676251db8SEnric Balletbo i Serra {
14776251db8SEnric Balletbo i Serra struct dwc3_of_simple *simple = dev_get_drvdata(dev);
14876251db8SEnric Balletbo i Serra
14976251db8SEnric Balletbo i Serra if (simple->need_reset)
15076251db8SEnric Balletbo i Serra reset_control_assert(simple->resets);
15176251db8SEnric Balletbo i Serra
15276251db8SEnric Balletbo i Serra return 0;
15376251db8SEnric Balletbo i Serra }
15476251db8SEnric Balletbo i Serra
dwc3_of_simple_resume(struct device * dev)15566174b69SArnd Bergmann static int __maybe_unused dwc3_of_simple_resume(struct device *dev)
15676251db8SEnric Balletbo i Serra {
15776251db8SEnric Balletbo i Serra struct dwc3_of_simple *simple = dev_get_drvdata(dev);
15876251db8SEnric Balletbo i Serra
15976251db8SEnric Balletbo i Serra if (simple->need_reset)
16076251db8SEnric Balletbo i Serra reset_control_deassert(simple->resets);
16176251db8SEnric Balletbo i Serra
16276251db8SEnric Balletbo i Serra return 0;
16376251db8SEnric Balletbo i Serra }
16416adc674SFelipe Balbi
16516adc674SFelipe Balbi static const struct dev_pm_ops dwc3_of_simple_dev_pm_ops = {
16676251db8SEnric Balletbo i Serra SET_SYSTEM_SLEEP_PM_OPS(dwc3_of_simple_suspend, dwc3_of_simple_resume)
16716adc674SFelipe Balbi SET_RUNTIME_PM_OPS(dwc3_of_simple_runtime_suspend,
16816adc674SFelipe Balbi dwc3_of_simple_runtime_resume, NULL)
16916adc674SFelipe Balbi };
17016adc674SFelipe Balbi
17116adc674SFelipe Balbi static const struct of_device_id of_dwc3_simple_match[] = {
172f652191bSWilliam Wu { .compatible = "rockchip,rk3399-dwc3" },
173c3cdce45SBaolin Wang { .compatible = "sprd,sc9860-dwc3" },
174e362098fSIcenowy Zheng { .compatible = "allwinner,sun50i-h6-dwc3" },
175b68d9251SMauro Carvalho Chehab { .compatible = "hisilicon,hi3670-dwc3" },
176e2c53515SWan Ahmad Zainie { .compatible = "intel,keembay-dwc3" },
17716adc674SFelipe Balbi { /* Sentinel */ }
17816adc674SFelipe Balbi };
17916adc674SFelipe Balbi MODULE_DEVICE_TABLE(of, of_dwc3_simple_match);
18016adc674SFelipe Balbi
18116adc674SFelipe Balbi static struct platform_driver dwc3_of_simple_driver = {
18216adc674SFelipe Balbi .probe = dwc3_of_simple_probe,
183*86a2b452SUwe Kleine-König .remove_new = dwc3_of_simple_remove,
184726b4fbaSFelipe Balbi .shutdown = dwc3_of_simple_shutdown,
18516adc674SFelipe Balbi .driver = {
18616adc674SFelipe Balbi .name = "dwc3-of-simple",
18716adc674SFelipe Balbi .of_match_table = of_dwc3_simple_match,
188a0d8c4cfSMasahiro Yamada .pm = &dwc3_of_simple_dev_pm_ops,
18916adc674SFelipe Balbi },
19016adc674SFelipe Balbi };
19116adc674SFelipe Balbi
19216adc674SFelipe Balbi module_platform_driver(dwc3_of_simple_driver);
19316adc674SFelipe Balbi MODULE_LICENSE("GPL v2");
19416adc674SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 OF Simple Glue Layer");
19516adc674SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
196