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