Skip to content

Commit 9f21683

Browse files
mszyprowFelipe Balbi
authored andcommitted
usb: dwc3: exynos: Rework clock handling and prepare for new variants
Add per-variant list of clocks and manage them all together in the single array. This is a preparation for adding new variants of Exynos SoCs. No functional changes for existing Exynos SoCs. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
1 parent 1e041b6 commit 9f21683

File tree

1 file changed

+80
-48
lines changed

1 file changed

+80
-48
lines changed

drivers/usb/dwc3/dwc3-exynos.c

Lines changed: 80 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,21 @@
1717
#include <linux/of_platform.h>
1818
#include <linux/regulator/consumer.h>
1919

20+
#define DWC3_EXYNOS_MAX_CLOCKS 4
21+
22+
struct dwc3_exynos_driverdata {
23+
const char *clk_names[DWC3_EXYNOS_MAX_CLOCKS];
24+
int num_clks;
25+
int suspend_clk_idx;
26+
};
27+
2028
struct dwc3_exynos {
2129
struct device *dev;
2230

23-
struct clk *clk;
24-
struct clk *susp_clk;
25-
struct clk *axius_clk;
31+
const char **clk_names;
32+
struct clk *clks[DWC3_EXYNOS_MAX_CLOCKS];
33+
int num_clks;
34+
int suspend_clk_idx;
2635

2736
struct regulator *vdd33;
2837
struct regulator *vdd10;
@@ -42,47 +51,42 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
4251
struct dwc3_exynos *exynos;
4352
struct device *dev = &pdev->dev;
4453
struct device_node *node = dev->of_node;
45-
46-
int ret;
54+
const struct dwc3_exynos_driverdata *driver_data;
55+
int i, ret;
4756

4857
exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);
4958
if (!exynos)
5059
return -ENOMEM;
5160

52-
platform_set_drvdata(pdev, exynos);
61+
driver_data = of_device_get_match_data(dev);
62+
exynos->dev = dev;
63+
exynos->num_clks = driver_data->num_clks;
64+
exynos->clk_names = (const char **)driver_data->clk_names;
65+
exynos->suspend_clk_idx = driver_data->suspend_clk_idx;
5366

54-
exynos->dev = dev;
67+
platform_set_drvdata(pdev, exynos);
5568

56-
exynos->clk = devm_clk_get(dev, "usbdrd30");
57-
if (IS_ERR(exynos->clk)) {
58-
dev_err(dev, "couldn't get clock\n");
59-
return -EINVAL;
69+
for (i = 0; i < exynos->num_clks; i++) {
70+
exynos->clks[i] = devm_clk_get(dev, exynos->clk_names[i]);
71+
if (IS_ERR(exynos->clks[i])) {
72+
dev_err(dev, "failed to get clock: %s\n",
73+
exynos->clk_names[i]);
74+
return PTR_ERR(exynos->clks[i]);
75+
}
6076
}
61-
ret = clk_prepare_enable(exynos->clk);
62-
if (ret)
63-
return ret;
6477

65-
exynos->susp_clk = devm_clk_get(dev, "usbdrd30_susp_clk");
66-
if (IS_ERR(exynos->susp_clk))
67-
exynos->susp_clk = NULL;
68-
ret = clk_prepare_enable(exynos->susp_clk);
69-
if (ret)
70-
goto susp_clk_err;
71-
72-
if (of_device_is_compatible(node, "samsung,exynos7-dwusb3")) {
73-
exynos->axius_clk = devm_clk_get(dev, "usbdrd30_axius_clk");
74-
if (IS_ERR(exynos->axius_clk)) {
75-
dev_err(dev, "no AXI UpScaler clk specified\n");
76-
ret = -ENODEV;
77-
goto axius_clk_err;
78+
for (i = 0; i < exynos->num_clks; i++) {
79+
ret = clk_prepare_enable(exynos->clks[i]);
80+
if (ret) {
81+
while (--i > 0)
82+
clk_disable_unprepare(exynos->clks[i]);
83+
return ret;
7884
}
79-
ret = clk_prepare_enable(exynos->axius_clk);
80-
if (ret)
81-
goto axius_clk_err;
82-
} else {
83-
exynos->axius_clk = NULL;
8485
}
8586

87+
if (exynos->suspend_clk_idx >= 0)
88+
clk_prepare_enable(exynos->clks[exynos->suspend_clk_idx]);
89+
8690
exynos->vdd33 = devm_regulator_get(dev, "vdd33");
8791
if (IS_ERR(exynos->vdd33)) {
8892
ret = PTR_ERR(exynos->vdd33);
@@ -124,44 +128,66 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
124128
vdd10_err:
125129
regulator_disable(exynos->vdd33);
126130
vdd33_err:
127-
clk_disable_unprepare(exynos->axius_clk);
128-
axius_clk_err:
129-
clk_disable_unprepare(exynos->susp_clk);
130-
susp_clk_err:
131-
clk_disable_unprepare(exynos->clk);
131+
for (i = exynos->num_clks - 1; i >= 0; i--)
132+
clk_disable_unprepare(exynos->clks[i]);
133+
134+
if (exynos->suspend_clk_idx >= 0)
135+
clk_disable_unprepare(exynos->clks[exynos->suspend_clk_idx]);
136+
132137
return ret;
133138
}
134139

135140
static int dwc3_exynos_remove(struct platform_device *pdev)
136141
{
137142
struct dwc3_exynos *exynos = platform_get_drvdata(pdev);
143+
int i;
138144

139145
device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child);
140146

141-
clk_disable_unprepare(exynos->axius_clk);
142-
clk_disable_unprepare(exynos->susp_clk);
143-
clk_disable_unprepare(exynos->clk);
147+
for (i = exynos->num_clks - 1; i >= 0; i--)
148+
clk_disable_unprepare(exynos->clks[i]);
149+
150+
if (exynos->suspend_clk_idx >= 0)
151+
clk_disable_unprepare(exynos->clks[exynos->suspend_clk_idx]);
144152

145153
regulator_disable(exynos->vdd33);
146154
regulator_disable(exynos->vdd10);
147155

148156
return 0;
149157
}
150158

159+
static const struct dwc3_exynos_driverdata exynos5250_drvdata = {
160+
.clk_names = { "usbdrd30" },
161+
.num_clks = 1,
162+
.suspend_clk_idx = -1,
163+
};
164+
165+
static const struct dwc3_exynos_driverdata exynos7_drvdata = {
166+
.clk_names = { "usbdrd30", "usbdrd30_susp_clk", "usbdrd30_axius_clk" },
167+
.num_clks = 3,
168+
.suspend_clk_idx = 1,
169+
};
170+
151171
static const struct of_device_id exynos_dwc3_match[] = {
152-
{ .compatible = "samsung,exynos5250-dwusb3" },
153-
{ .compatible = "samsung,exynos7-dwusb3" },
154-
{},
172+
{
173+
.compatible = "samsung,exynos5250-dwusb3",
174+
.data = &exynos5250_drvdata,
175+
}, {
176+
.compatible = "samsung,exynos7-dwusb3",
177+
.data = &exynos7_drvdata,
178+
}, {
179+
}
155180
};
156181
MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
157182

158183
#ifdef CONFIG_PM_SLEEP
159184
static int dwc3_exynos_suspend(struct device *dev)
160185
{
161186
struct dwc3_exynos *exynos = dev_get_drvdata(dev);
187+
int i;
162188

163-
clk_disable(exynos->axius_clk);
164-
clk_disable(exynos->clk);
189+
for (i = exynos->num_clks - 1; i >= 0; i--)
190+
clk_disable_unprepare(exynos->clks[i]);
165191

166192
regulator_disable(exynos->vdd33);
167193
regulator_disable(exynos->vdd10);
@@ -172,7 +198,7 @@ static int dwc3_exynos_suspend(struct device *dev)
172198
static int dwc3_exynos_resume(struct device *dev)
173199
{
174200
struct dwc3_exynos *exynos = dev_get_drvdata(dev);
175-
int ret;
201+
int i, ret;
176202

177203
ret = regulator_enable(exynos->vdd33);
178204
if (ret) {
@@ -185,8 +211,14 @@ static int dwc3_exynos_resume(struct device *dev)
185211
return ret;
186212
}
187213

188-
clk_enable(exynos->clk);
189-
clk_enable(exynos->axius_clk);
214+
for (i = 0; i < exynos->num_clks; i++) {
215+
ret = clk_prepare_enable(exynos->clks[i]);
216+
if (ret) {
217+
while (--i > 0)
218+
clk_disable_unprepare(exynos->clks[i]);
219+
return ret;
220+
}
221+
}
190222

191223
return 0;
192224
}

0 commit comments

Comments
 (0)