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