xref: /linux/drivers/soc/qcom/pmic_glink.c (revision 2d7eaeb05ae265bd64270376e6a2c0d80244771f)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
4  * Copyright (c) 2022, Linaro Ltd
5  */
6 #include <linux/auxiliary_bus.h>
7 #include <linux/cleanup.h>
8 #include <linux/delay.h>
9 #include <linux/module.h>
10 #include <linux/of.h>
11 #include <linux/platform_device.h>
12 #include <linux/rpmsg.h>
13 #include <linux/slab.h>
14 #include <linux/soc/qcom/pdr.h>
15 #include <linux/soc/qcom/pmic_glink.h>
16 #include <linux/spinlock.h>
17 
18 #define PMIC_GLINK_SEND_TIMEOUT (5 * HZ)
19 
20 enum {
21 	PMIC_GLINK_CLIENT_BATT = 0,
22 	PMIC_GLINK_CLIENT_ALTMODE,
23 	PMIC_GLINK_CLIENT_UCSI,
24 };
25 
26 struct pmic_glink_data {
27 	unsigned long	client_mask;
28 	const char	*charger_pdr_service_name;
29 	const char	*charger_pdr_service_path;
30 };
31 
32 struct pmic_glink {
33 	struct device *dev;
34 	struct pdr_handle *pdr;
35 
36 	struct rpmsg_endpoint *ept;
37 
38 	const struct pmic_glink_data *data;
39 
40 	struct auxiliary_device altmode_aux;
41 	struct auxiliary_device ps_aux;
42 	struct auxiliary_device ucsi_aux;
43 
44 	/* serializing client_state and pdr_state updates */
45 	struct mutex state_lock;
46 	unsigned int client_state;
47 	unsigned int pdr_state;
48 	bool pdr_available;
49 
50 	/* serializing clients list updates */
51 	spinlock_t client_lock;
52 	struct list_head clients;
53 };
54 
55 static struct pmic_glink *__pmic_glink;
56 static DEFINE_MUTEX(__pmic_glink_lock);
57 
58 struct pmic_glink_client {
59 	struct list_head node;
60 
61 	struct pmic_glink *pg;
62 	unsigned int id;
63 
64 	void (*cb)(const void *data, size_t len, void *priv);
65 	void (*pdr_notify)(void *priv, int state);
66 	void *priv;
67 };
68 
69 static void _devm_pmic_glink_release_client(struct device *dev, void *res)
70 {
71 	struct pmic_glink_client *client = (struct pmic_glink_client *)res;
72 	struct pmic_glink *pg = client->pg;
73 	unsigned long flags;
74 
75 	spin_lock_irqsave(&pg->client_lock, flags);
76 	list_del(&client->node);
77 	spin_unlock_irqrestore(&pg->client_lock, flags);
78 }
79 
80 struct pmic_glink_client *devm_pmic_glink_client_alloc(struct device *dev,
81 						       unsigned int id,
82 						       void (*cb)(const void *, size_t, void *),
83 						       void (*pdr)(void *, int),
84 						       void *priv)
85 {
86 	struct pmic_glink_client *client;
87 	struct pmic_glink *pg = dev_get_drvdata(dev->parent);
88 
89 	client = devres_alloc(_devm_pmic_glink_release_client, sizeof(*client), GFP_KERNEL);
90 	if (!client)
91 		return ERR_PTR(-ENOMEM);
92 
93 	client->pg = pg;
94 	client->id = id;
95 	client->cb = cb;
96 	client->pdr_notify = pdr;
97 	client->priv = priv;
98 	INIT_LIST_HEAD(&client->node);
99 
100 	devres_add(dev, client);
101 
102 	return client;
103 }
104 EXPORT_SYMBOL_GPL(devm_pmic_glink_client_alloc);
105 
106 void pmic_glink_client_register(struct pmic_glink_client *client)
107 {
108 	struct pmic_glink *pg = client->pg;
109 	unsigned long flags;
110 
111 	guard(mutex)(&pg->state_lock);
112 	spin_lock_irqsave(&pg->client_lock, flags);
113 
114 	list_add(&client->node, &pg->clients);
115 	client->pdr_notify(client->priv, pg->client_state);
116 
117 	spin_unlock_irqrestore(&pg->client_lock, flags);
118 }
119 EXPORT_SYMBOL_GPL(pmic_glink_client_register);
120 
121 int pmic_glink_send(struct pmic_glink_client *client, void *data, size_t len)
122 {
123 	struct pmic_glink *pg = client->pg;
124 	bool timeout_reached = false;
125 	unsigned long start;
126 	int ret;
127 
128 	guard(mutex)(&pg->state_lock);
129 	if (!pg->ept) {
130 		return -ECONNRESET;
131 	}
132 
133 	start = jiffies;
134 	for (;;) {
135 		ret = rpmsg_send(pg->ept, data, len);
136 		if (ret != -EAGAIN)
137 			break;
138 
139 		if (timeout_reached) {
140 			ret = -ETIMEDOUT;
141 			break;
142 		}
143 
144 		usleep_range(1000, 5000);
145 		timeout_reached = time_after(jiffies, start + PMIC_GLINK_SEND_TIMEOUT);
146 	}
147 
148 	return ret;
149 }
150 EXPORT_SYMBOL_GPL(pmic_glink_send);
151 
152 static int pmic_glink_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
153 				     int len, void *priv, u32 addr)
154 {
155 	struct pmic_glink_client *client;
156 	struct pmic_glink_hdr *hdr;
157 	struct pmic_glink *pg = dev_get_drvdata(&rpdev->dev);
158 	unsigned long flags;
159 
160 	if (len < sizeof(*hdr)) {
161 		dev_warn(pg->dev, "ignoring truncated message\n");
162 		return 0;
163 	}
164 
165 	hdr = data;
166 
167 	spin_lock_irqsave(&pg->client_lock, flags);
168 	list_for_each_entry(client, &pg->clients, node) {
169 		if (client->id == le32_to_cpu(hdr->owner))
170 			client->cb(data, len, client->priv);
171 	}
172 	spin_unlock_irqrestore(&pg->client_lock, flags);
173 
174 	return 0;
175 }
176 
177 static void pmic_glink_aux_release(struct device *dev)
178 {
179 	of_node_put(dev->of_node);
180 }
181 
182 static int pmic_glink_add_aux_device(struct pmic_glink *pg,
183 				     struct auxiliary_device *aux,
184 				     const char *name)
185 {
186 	struct device *parent = pg->dev;
187 	int ret;
188 
189 	aux->name = name;
190 	aux->dev.parent = parent;
191 	aux->dev.release = pmic_glink_aux_release;
192 	device_set_of_node_from_dev(&aux->dev, parent);
193 	ret = auxiliary_device_init(aux);
194 	if (ret) {
195 		of_node_put(aux->dev.of_node);
196 		return ret;
197 	}
198 
199 	ret = auxiliary_device_add(aux);
200 	if (ret)
201 		auxiliary_device_uninit(aux);
202 
203 	return ret;
204 }
205 
206 static void pmic_glink_del_aux_device(struct pmic_glink *pg,
207 				      struct auxiliary_device *aux)
208 {
209 	auxiliary_device_delete(aux);
210 	auxiliary_device_uninit(aux);
211 }
212 
213 static void pmic_glink_state_notify_clients(struct pmic_glink *pg)
214 {
215 	struct pmic_glink_client *client;
216 	unsigned int new_state = pg->client_state;
217 	unsigned long flags;
218 
219 	if (pg->client_state != SERVREG_SERVICE_STATE_UP) {
220 		if (pg->pdr_state == SERVREG_SERVICE_STATE_UP && pg->ept)
221 			new_state = SERVREG_SERVICE_STATE_UP;
222 	} else {
223 		if (pg->pdr_state == SERVREG_SERVICE_STATE_DOWN || !pg->ept)
224 			new_state = SERVREG_SERVICE_STATE_DOWN;
225 	}
226 
227 	if (new_state != pg->client_state) {
228 		spin_lock_irqsave(&pg->client_lock, flags);
229 		list_for_each_entry(client, &pg->clients, node)
230 			client->pdr_notify(client->priv, new_state);
231 		spin_unlock_irqrestore(&pg->client_lock, flags);
232 		pg->client_state = new_state;
233 	}
234 }
235 
236 static void pmic_glink_pdr_callback(int state, char *svc_path, void *priv)
237 {
238 	struct pmic_glink *pg = priv;
239 
240 	guard(mutex)(&pg->state_lock);
241 	pg->pdr_state = state;
242 
243 	pmic_glink_state_notify_clients(pg);
244 }
245 
246 static int pmic_glink_rpmsg_probe(struct rpmsg_device *rpdev)
247 {
248 	struct pmic_glink *pg;
249 
250 	guard(mutex)(&__pmic_glink_lock);
251 	pg = __pmic_glink;
252 	if (!pg)
253 		return dev_err_probe(&rpdev->dev, -EPROBE_DEFER,
254 				     "no pmic_glink device to attach to\n");
255 
256 	dev_set_drvdata(&rpdev->dev, pg);
257 	pg->pdr_available = rpdev->id.driver_data;
258 
259 	guard(mutex)(&pg->state_lock);
260 	pg->ept = rpdev->ept;
261 	if (!pg->pdr_available)
262 		pg->pdr_state = SERVREG_SERVICE_STATE_UP;
263 	pmic_glink_state_notify_clients(pg);
264 
265 	return 0;
266 }
267 
268 static void pmic_glink_rpmsg_remove(struct rpmsg_device *rpdev)
269 {
270 	struct pmic_glink *pg;
271 
272 	guard(mutex)(&__pmic_glink_lock);
273 	pg = __pmic_glink;
274 	if (!pg)
275 		return;
276 
277 	guard(mutex)(&pg->state_lock);
278 	pg->ept = NULL;
279 	if (!pg->pdr_available)
280 		pg->pdr_state = SERVREG_SERVICE_STATE_DOWN;
281 	pmic_glink_state_notify_clients(pg);
282 }
283 
284 static const struct rpmsg_device_id pmic_glink_rpmsg_id_match[] = {
285 	{.name = "PMIC_RTR_ADSP_APPS", .driver_data = true },
286 	{.name = "PMIC_RTR_SOCCP_APPS", .driver_data = false },
287 	{}
288 };
289 
290 static struct rpmsg_driver pmic_glink_rpmsg_driver = {
291 	.probe = pmic_glink_rpmsg_probe,
292 	.remove = pmic_glink_rpmsg_remove,
293 	.callback = pmic_glink_rpmsg_callback,
294 	.id_table = pmic_glink_rpmsg_id_match,
295 	.drv  = {
296 		.name  = "qcom_pmic_glink_rpmsg",
297 	},
298 };
299 
300 static int pmic_glink_probe(struct platform_device *pdev)
301 {
302 	struct pdr_service *service;
303 	struct pmic_glink *pg;
304 	int ret;
305 
306 	pg = devm_kzalloc(&pdev->dev, sizeof(*pg), GFP_KERNEL);
307 	if (!pg)
308 		return -ENOMEM;
309 
310 	dev_set_drvdata(&pdev->dev, pg);
311 
312 	pg->dev = &pdev->dev;
313 
314 	INIT_LIST_HEAD(&pg->clients);
315 	spin_lock_init(&pg->client_lock);
316 	mutex_init(&pg->state_lock);
317 
318 	pg->data = of_device_get_match_data(&pdev->dev);
319 	if (!pg->data)
320 		return -EINVAL;
321 
322 	pg->pdr = pdr_handle_alloc(pmic_glink_pdr_callback, pg);
323 	if (IS_ERR(pg->pdr)) {
324 		ret = dev_err_probe(&pdev->dev, PTR_ERR(pg->pdr),
325 				    "failed to initialize pdr\n");
326 		return ret;
327 	}
328 
329 	if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) {
330 		ret = pmic_glink_add_aux_device(pg, &pg->ucsi_aux, "ucsi");
331 		if (ret)
332 			goto out_release_pdr_handle;
333 	}
334 	if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE)) {
335 		ret = pmic_glink_add_aux_device(pg, &pg->altmode_aux, "altmode");
336 		if (ret)
337 			goto out_release_ucsi_aux;
338 	}
339 	if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_BATT)) {
340 		ret = pmic_glink_add_aux_device(pg, &pg->ps_aux, "power-supply");
341 		if (ret)
342 			goto out_release_altmode_aux;
343 	}
344 
345 	if (pg->data->charger_pdr_service_name && pg->data->charger_pdr_service_path) {
346 		service = pdr_add_lookup(pg->pdr, pg->data->charger_pdr_service_name,
347 					 pg->data->charger_pdr_service_path);
348 		if (IS_ERR(service)) {
349 			ret = dev_err_probe(&pdev->dev, PTR_ERR(service),
350 					    "failed adding pdr lookup for charger_pd\n");
351 			goto out_release_aux_devices;
352 		}
353 	}
354 
355 	mutex_lock(&__pmic_glink_lock);
356 	__pmic_glink = pg;
357 	mutex_unlock(&__pmic_glink_lock);
358 
359 	return 0;
360 
361 out_release_aux_devices:
362 	if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_BATT))
363 		pmic_glink_del_aux_device(pg, &pg->ps_aux);
364 out_release_altmode_aux:
365 	if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE))
366 		pmic_glink_del_aux_device(pg, &pg->altmode_aux);
367 out_release_ucsi_aux:
368 	if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI))
369 		pmic_glink_del_aux_device(pg, &pg->ucsi_aux);
370 out_release_pdr_handle:
371 	pdr_handle_release(pg->pdr);
372 
373 	return ret;
374 }
375 
376 static void pmic_glink_remove(struct platform_device *pdev)
377 {
378 	struct pmic_glink *pg = dev_get_drvdata(&pdev->dev);
379 
380 	pdr_handle_release(pg->pdr);
381 
382 	if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_BATT))
383 		pmic_glink_del_aux_device(pg, &pg->ps_aux);
384 	if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE))
385 		pmic_glink_del_aux_device(pg, &pg->altmode_aux);
386 	if (pg->data->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI))
387 		pmic_glink_del_aux_device(pg, &pg->ucsi_aux);
388 
389 	guard(mutex)(&__pmic_glink_lock);
390 	__pmic_glink = NULL;
391 }
392 
393 static const struct pmic_glink_data pmic_glink_adsp_data = {
394 	.client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
395 		       BIT(PMIC_GLINK_CLIENT_ALTMODE) |
396 		       BIT(PMIC_GLINK_CLIENT_UCSI),
397 	.charger_pdr_service_name = "tms/servreg",
398 	.charger_pdr_service_path = "msm/adsp/charger_pd",
399 };
400 
401 static const struct pmic_glink_data pmic_glink_soccp_data = {
402 	.client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
403 		       BIT(PMIC_GLINK_CLIENT_ALTMODE) |
404 		       BIT(PMIC_GLINK_CLIENT_UCSI),
405 };
406 
407 static const struct of_device_id pmic_glink_of_match[] = {
408 	{ .compatible = "qcom,glymur-pmic-glink", .data = &pmic_glink_soccp_data },
409 	{ .compatible = "qcom,kaanapali-pmic-glink", .data = &pmic_glink_soccp_data },
410 	{ .compatible = "qcom,pmic-glink", .data = &pmic_glink_adsp_data },
411 	{}
412 };
413 MODULE_DEVICE_TABLE(of, pmic_glink_of_match);
414 
415 static struct platform_driver pmic_glink_driver = {
416 	.probe = pmic_glink_probe,
417 	.remove = pmic_glink_remove,
418 	.driver = {
419 		.name = "qcom_pmic_glink",
420 		.of_match_table = pmic_glink_of_match,
421 	},
422 };
423 
424 static int pmic_glink_init(void)
425 {
426 	int ret;
427 
428 	ret = platform_driver_register(&pmic_glink_driver);
429 	if (ret < 0)
430 		return ret;
431 
432 	ret = register_rpmsg_driver(&pmic_glink_rpmsg_driver);
433 	if (ret < 0) {
434 		platform_driver_unregister(&pmic_glink_driver);
435 		return ret;
436 	}
437 
438 	return 0;
439 }
440 module_init(pmic_glink_init);
441 
442 static void pmic_glink_exit(void)
443 {
444 	unregister_rpmsg_driver(&pmic_glink_rpmsg_driver);
445 	platform_driver_unregister(&pmic_glink_driver);
446 }
447 module_exit(pmic_glink_exit);
448 
449 MODULE_DESCRIPTION("Qualcomm PMIC GLINK driver");
450 MODULE_LICENSE("GPL");
451