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