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