xref: /openbmc/linux/drivers/usb/dwc3/dwc3-of-simple.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
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