xref: /linux/drivers/remoteproc/qcom_wcnss_iris.c (revision 0fdebc5ec2ca492d69df2d93a6a7abade4941aae)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Qualcomm Wireless Connectivity Subsystem Iris driver
4  *
5  * Copyright (C) 2016 Linaro Ltd
6  * Copyright (C) 2014 Sony Mobile Communications AB
7  * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
8  */
9 
10 #include <linux/clk.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/of_device.h>
14 #include <linux/platform_device.h>
15 #include <linux/regulator/consumer.h>
16 
17 #include "qcom_wcnss.h"
18 
19 struct qcom_iris {
20 	struct device dev;
21 
22 	struct clk *xo_clk;
23 
24 	struct regulator_bulk_data *vregs;
25 	size_t num_vregs;
26 };
27 
28 struct iris_data {
29 	const struct wcnss_vreg_info *vregs;
30 	size_t num_vregs;
31 
32 	bool use_48mhz_xo;
33 };
34 
35 static const struct iris_data wcn3620_data = {
36 	.vregs = (struct wcnss_vreg_info[]) {
37 		{ "vddxo",  1800000, 1800000, 10000 },
38 		{ "vddrfa", 1300000, 1300000, 100000 },
39 		{ "vddpa",  3300000, 3300000, 515000 },
40 		{ "vdddig", 1800000, 1800000, 10000 },
41 	},
42 	.num_vregs = 4,
43 	.use_48mhz_xo = false,
44 };
45 
46 static const struct iris_data wcn3660_data = {
47 	.vregs = (struct wcnss_vreg_info[]) {
48 		{ "vddxo",  1800000, 1800000, 10000 },
49 		{ "vddrfa", 1300000, 1300000, 100000 },
50 		{ "vddpa",  2900000, 3000000, 515000 },
51 		{ "vdddig", 1200000, 1225000, 10000 },
52 	},
53 	.num_vregs = 4,
54 	.use_48mhz_xo = true,
55 };
56 
57 static const struct iris_data wcn3680_data = {
58 	.vregs = (struct wcnss_vreg_info[]) {
59 		{ "vddxo",  1800000, 1800000, 10000 },
60 		{ "vddrfa", 1300000, 1300000, 100000 },
61 		{ "vddpa",  3300000, 3300000, 515000 },
62 		{ "vdddig", 1800000, 1800000, 10000 },
63 	},
64 	.num_vregs = 4,
65 	.use_48mhz_xo = true,
66 };
67 
68 int qcom_iris_enable(struct qcom_iris *iris)
69 {
70 	int ret;
71 
72 	ret = regulator_bulk_enable(iris->num_vregs, iris->vregs);
73 	if (ret)
74 		return ret;
75 
76 	ret = clk_prepare_enable(iris->xo_clk);
77 	if (ret) {
78 		dev_err(&iris->dev, "failed to enable xo clk\n");
79 		goto disable_regulators;
80 	}
81 
82 	return 0;
83 
84 disable_regulators:
85 	regulator_bulk_disable(iris->num_vregs, iris->vregs);
86 
87 	return ret;
88 }
89 
90 void qcom_iris_disable(struct qcom_iris *iris)
91 {
92 	clk_disable_unprepare(iris->xo_clk);
93 	regulator_bulk_disable(iris->num_vregs, iris->vregs);
94 }
95 
96 static const struct of_device_id iris_of_match[] = {
97 	{ .compatible = "qcom,wcn3620", .data = &wcn3620_data },
98 	{ .compatible = "qcom,wcn3660", .data = &wcn3660_data },
99 	{ .compatible = "qcom,wcn3660b", .data = &wcn3680_data },
100 	{ .compatible = "qcom,wcn3680", .data = &wcn3680_data },
101 	{}
102 };
103 
104 static void qcom_iris_release(struct device *dev)
105 {
106 	struct qcom_iris *iris = container_of(dev, struct qcom_iris, dev);
107 
108 	of_node_put(iris->dev.of_node);
109 	kfree(iris);
110 }
111 
112 struct qcom_iris *qcom_iris_probe(struct device *parent, bool *use_48mhz_xo)
113 {
114 	const struct of_device_id *match;
115 	const struct iris_data *data;
116 	struct device_node *of_node;
117 	struct qcom_iris *iris;
118 	int ret;
119 	int i;
120 
121 	of_node = of_get_child_by_name(parent->of_node, "iris");
122 	if (!of_node) {
123 		dev_err(parent, "No child node \"iris\" found\n");
124 		return ERR_PTR(-EINVAL);
125 	}
126 
127 	iris = kzalloc(sizeof(*iris), GFP_KERNEL);
128 	if (!iris) {
129 		of_node_put(of_node);
130 		return ERR_PTR(-ENOMEM);
131 	}
132 
133 	device_initialize(&iris->dev);
134 	iris->dev.parent = parent;
135 	iris->dev.release = qcom_iris_release;
136 	iris->dev.of_node = of_node;
137 
138 	dev_set_name(&iris->dev, "%s.iris", dev_name(parent));
139 
140 	ret = device_add(&iris->dev);
141 	if (ret) {
142 		put_device(&iris->dev);
143 		return ERR_PTR(ret);
144 	}
145 
146 	match = of_match_device(iris_of_match, &iris->dev);
147 	if (!match) {
148 		dev_err(&iris->dev, "no matching compatible for iris\n");
149 		ret = -EINVAL;
150 		goto err_device_del;
151 	}
152 
153 	data = match->data;
154 
155 	iris->xo_clk = devm_clk_get(&iris->dev, "xo");
156 	if (IS_ERR(iris->xo_clk)) {
157 		ret = PTR_ERR(iris->xo_clk);
158 		if (ret != -EPROBE_DEFER)
159 			dev_err(&iris->dev, "failed to acquire xo clk\n");
160 		goto err_device_del;
161 	}
162 
163 	iris->num_vregs = data->num_vregs;
164 	iris->vregs = devm_kcalloc(&iris->dev,
165 				   iris->num_vregs,
166 				   sizeof(struct regulator_bulk_data),
167 				   GFP_KERNEL);
168 	if (!iris->vregs) {
169 		ret = -ENOMEM;
170 		goto err_device_del;
171 	}
172 
173 	for (i = 0; i < iris->num_vregs; i++)
174 		iris->vregs[i].supply = data->vregs[i].name;
175 
176 	ret = devm_regulator_bulk_get(&iris->dev, iris->num_vregs, iris->vregs);
177 	if (ret) {
178 		dev_err(&iris->dev, "failed to get regulators\n");
179 		goto err_device_del;
180 	}
181 
182 	for (i = 0; i < iris->num_vregs; i++) {
183 		if (data->vregs[i].max_voltage)
184 			regulator_set_voltage(iris->vregs[i].consumer,
185 					      data->vregs[i].min_voltage,
186 					      data->vregs[i].max_voltage);
187 
188 		if (data->vregs[i].load_uA)
189 			regulator_set_load(iris->vregs[i].consumer,
190 					   data->vregs[i].load_uA);
191 	}
192 
193 	*use_48mhz_xo = data->use_48mhz_xo;
194 
195 	return iris;
196 
197 err_device_del:
198 	device_del(&iris->dev);
199 
200 	return ERR_PTR(ret);
201 }
202 
203 void qcom_iris_remove(struct qcom_iris *iris)
204 {
205 	device_del(&iris->dev);
206 }
207