Lines Matching +full:sdm845 +full:- +full:aoss +full:- +full:qmp
1 // SPDX-License-Identifier: GPL-2.0
5 #include <dt-bindings/power/qcom-aoss-qmp.h>
6 #include <linux/clk-provider.h>
20 /* AOP-side offsets */
28 /* Linux-side offsets */
51 struct qmp *qmp; member
57 * struct qmp - driver state for QMP implementation
59 * @dev: reference to QMP device
70 struct qmp { struct
90 struct qmp *qmp; argument
96 static void qmp_kick(struct qmp *qmp) in qmp_kick() argument
98 mbox_send_message(qmp->mbox_chan, NULL); in qmp_kick()
99 mbox_client_txdone(qmp->mbox_chan, 0); in qmp_kick()
102 static bool qmp_magic_valid(struct qmp *qmp) in qmp_magic_valid() argument
104 return readl(qmp->msgram + QMP_DESC_MAGIC) == QMP_MAGIC; in qmp_magic_valid()
107 static bool qmp_link_acked(struct qmp *qmp) in qmp_link_acked() argument
109 return readl(qmp->msgram + QMP_DESC_MCORE_LINK_STATE_ACK) == QMP_STATE_UP; in qmp_link_acked()
112 static bool qmp_mcore_channel_acked(struct qmp *qmp) in qmp_mcore_channel_acked() argument
114 return readl(qmp->msgram + QMP_DESC_MCORE_CH_STATE_ACK) == QMP_STATE_UP; in qmp_mcore_channel_acked()
117 static bool qmp_ucore_channel_up(struct qmp *qmp) in qmp_ucore_channel_up() argument
119 return readl(qmp->msgram + QMP_DESC_UCORE_CH_STATE) == QMP_STATE_UP; in qmp_ucore_channel_up()
122 static int qmp_open(struct qmp *qmp) in qmp_open() argument
127 if (!qmp_magic_valid(qmp)) { in qmp_open()
128 dev_err(qmp->dev, "QMP magic doesn't match\n"); in qmp_open()
129 return -EINVAL; in qmp_open()
132 val = readl(qmp->msgram + QMP_DESC_VERSION); in qmp_open()
134 dev_err(qmp->dev, "unsupported QMP version %d\n", val); in qmp_open()
135 return -EINVAL; in qmp_open()
138 qmp->offset = readl(qmp->msgram + QMP_DESC_MCORE_MBOX_OFFSET); in qmp_open()
139 qmp->size = readl(qmp->msgram + QMP_DESC_MCORE_MBOX_SIZE); in qmp_open()
140 if (!qmp->size) { in qmp_open()
141 dev_err(qmp->dev, "invalid mailbox size\n"); in qmp_open()
142 return -EINVAL; in qmp_open()
146 val = readl(qmp->msgram + QMP_DESC_UCORE_LINK_STATE); in qmp_open()
147 writel(val, qmp->msgram + QMP_DESC_UCORE_LINK_STATE_ACK); in qmp_open()
150 writel(QMP_STATE_UP, qmp->msgram + QMP_DESC_MCORE_LINK_STATE); in qmp_open()
152 qmp_kick(qmp); in qmp_open()
154 ret = wait_event_timeout(qmp->event, qmp_link_acked(qmp), HZ); in qmp_open()
156 dev_err(qmp->dev, "ucore didn't ack link\n"); in qmp_open()
160 writel(QMP_STATE_UP, qmp->msgram + QMP_DESC_MCORE_CH_STATE); in qmp_open()
162 qmp_kick(qmp); in qmp_open()
164 ret = wait_event_timeout(qmp->event, qmp_ucore_channel_up(qmp), HZ); in qmp_open()
166 dev_err(qmp->dev, "ucore didn't open channel\n"); in qmp_open()
171 writel(QMP_STATE_UP, qmp->msgram + QMP_DESC_UCORE_CH_STATE_ACK); in qmp_open()
173 qmp_kick(qmp); in qmp_open()
175 ret = wait_event_timeout(qmp->event, qmp_mcore_channel_acked(qmp), HZ); in qmp_open()
177 dev_err(qmp->dev, "ucore didn't ack channel\n"); in qmp_open()
184 writel(QMP_STATE_DOWN, qmp->msgram + QMP_DESC_MCORE_CH_STATE); in qmp_open()
187 writel(QMP_STATE_DOWN, qmp->msgram + QMP_DESC_MCORE_LINK_STATE); in qmp_open()
188 qmp_kick(qmp); in qmp_open()
190 return -ETIMEDOUT; in qmp_open()
193 static void qmp_close(struct qmp *qmp) in qmp_close() argument
195 writel(QMP_STATE_DOWN, qmp->msgram + QMP_DESC_MCORE_CH_STATE); in qmp_close()
196 writel(QMP_STATE_DOWN, qmp->msgram + QMP_DESC_MCORE_LINK_STATE); in qmp_close()
197 qmp_kick(qmp); in qmp_close()
202 struct qmp *qmp = data; in qmp_intr() local
204 wake_up_all(&qmp->event); in qmp_intr()
209 static bool qmp_message_empty(struct qmp *qmp) in qmp_message_empty() argument
211 return readl(qmp->msgram + qmp->offset) == 0; in qmp_message_empty()
215 * qmp_send() - send a message to the AOSS
216 * @qmp: qmp context
220 * Transmit @data to AOSS and wait for the AOSS to acknowledge the message.
226 static int qmp_send(struct qmp *qmp, const void *data, size_t len) in qmp_send() argument
231 if (WARN_ON(len + sizeof(u32) > qmp->size)) in qmp_send()
232 return -EINVAL; in qmp_send()
235 return -EINVAL; in qmp_send()
237 mutex_lock(&qmp->tx_lock); in qmp_send()
239 /* The message RAM only implements 32-bit accesses */ in qmp_send()
240 __iowrite32_copy(qmp->msgram + qmp->offset + sizeof(u32), in qmp_send()
242 writel(len, qmp->msgram + qmp->offset); in qmp_send()
245 readl(qmp->msgram + qmp->offset); in qmp_send()
246 qmp_kick(qmp); in qmp_send()
248 time_left = wait_event_interruptible_timeout(qmp->event, in qmp_send()
249 qmp_message_empty(qmp), HZ); in qmp_send()
251 dev_err(qmp->dev, "ucore did not ack channel\n"); in qmp_send()
252 ret = -ETIMEDOUT; in qmp_send()
255 writel(0, qmp->msgram + qmp->offset); in qmp_send()
260 mutex_unlock(&qmp->tx_lock); in qmp_send()
268 struct qmp *qmp = container_of(hw, struct qmp, qdss_clk); in qmp_qdss_clk_prepare() local
270 return qmp_send(qmp, buf, sizeof(buf)); in qmp_qdss_clk_prepare()
276 struct qmp *qmp = container_of(hw, struct qmp, qdss_clk); in qmp_qdss_clk_unprepare() local
278 qmp_send(qmp, buf, sizeof(buf)); in qmp_qdss_clk_unprepare()
286 static int qmp_qdss_clk_add(struct qmp *qmp) in qmp_qdss_clk_add() argument
294 qmp->qdss_clk.init = &qdss_init; in qmp_qdss_clk_add()
295 ret = clk_hw_register(qmp->dev, &qmp->qdss_clk); in qmp_qdss_clk_add()
297 dev_err(qmp->dev, "failed to register qdss clock\n"); in qmp_qdss_clk_add()
301 ret = of_clk_add_hw_provider(qmp->dev->of_node, of_clk_hw_simple_get, in qmp_qdss_clk_add()
302 &qmp->qdss_clk); in qmp_qdss_clk_add()
304 dev_err(qmp->dev, "unable to register of clk hw provider\n"); in qmp_qdss_clk_add()
305 clk_hw_unregister(&qmp->qdss_clk); in qmp_qdss_clk_add()
311 static void qmp_qdss_clk_remove(struct qmp *qmp) in qmp_qdss_clk_remove() argument
313 of_clk_del_provider(qmp->dev->of_node); in qmp_qdss_clk_remove()
314 clk_hw_unregister(&qmp->qdss_clk); in qmp_qdss_clk_remove()
323 res->pd.name, enable ? "on" : "off"); in qmp_pd_power_toggle()
324 return qmp_send(res->qmp, buf, sizeof(buf)); in qmp_pd_power_toggle()
346 static int qmp_pd_add(struct qmp *qmp) in qmp_pd_add() argument
348 struct genpd_onecell_data *data = &qmp->pd_data; in qmp_pd_add()
349 struct device *dev = qmp->dev; in qmp_pd_add()
357 return -ENOMEM; in qmp_pd_add()
359 data->domains = devm_kcalloc(dev, num, sizeof(*data->domains), in qmp_pd_add()
361 if (!data->domains) in qmp_pd_add()
362 return -ENOMEM; in qmp_pd_add()
365 res[i].qmp = qmp; in qmp_pd_add()
376 data->domains[i] = &res[i].pd; in qmp_pd_add()
379 data->num_domains = i; in qmp_pd_add()
381 ret = of_genpd_add_provider_onecell(dev->of_node, data); in qmp_pd_add()
388 for (i--; i >= 0; i--) in qmp_pd_add()
389 pm_genpd_remove(data->domains[i]); in qmp_pd_add()
394 static void qmp_pd_remove(struct qmp *qmp) in qmp_pd_remove() argument
396 struct genpd_onecell_data *data = &qmp->pd_data; in qmp_pd_remove()
397 struct device *dev = qmp->dev; in qmp_pd_remove()
400 of_genpd_del_provider(dev->of_node); in qmp_pd_remove()
402 for (i = 0; i < data->num_domains; i++) in qmp_pd_remove()
403 pm_genpd_remove(data->domains[i]); in qmp_pd_remove()
416 struct qmp_cooling_device *qmp_cdev = cdev->devdata; in qmp_cdev_get_cur_state()
418 *state = qmp_cdev->state; in qmp_cdev_get_cur_state()
425 struct qmp_cooling_device *qmp_cdev = cdev->devdata; in qmp_cdev_set_cur_state()
433 if (qmp_cdev->state == state) in qmp_cdev_set_cur_state()
438 qmp_cdev->name, in qmp_cdev_set_cur_state()
441 ret = qmp_send(qmp_cdev->qmp, buf, sizeof(buf)); in qmp_cdev_set_cur_state()
444 qmp_cdev->state = cdev_state; in qmp_cdev_set_cur_state()
455 static int qmp_cooling_device_add(struct qmp *qmp, in qmp_cooling_device_add() argument
459 char *cdev_name = (char *)node->name; in qmp_cooling_device_add()
461 qmp_cdev->qmp = qmp; in qmp_cooling_device_add()
462 qmp_cdev->state = !qmp_cdev_max_state; in qmp_cooling_device_add()
463 qmp_cdev->name = cdev_name; in qmp_cooling_device_add()
464 qmp_cdev->cdev = devm_thermal_of_cooling_device_register in qmp_cooling_device_add()
465 (qmp->dev, node, in qmp_cooling_device_add()
469 if (IS_ERR(qmp_cdev->cdev)) in qmp_cooling_device_add()
470 dev_err(qmp->dev, "unable to register %s cooling device\n", in qmp_cooling_device_add()
473 return PTR_ERR_OR_ZERO(qmp_cdev->cdev); in qmp_cooling_device_add()
476 static int qmp_cooling_devices_register(struct qmp *qmp) in qmp_cooling_devices_register() argument
482 np = qmp->dev->of_node; in qmp_cooling_devices_register()
484 qmp->cooling_devs = devm_kcalloc(qmp->dev, QMP_NUM_COOLING_RESOURCES, in qmp_cooling_devices_register()
485 sizeof(*qmp->cooling_devs), in qmp_cooling_devices_register()
488 if (!qmp->cooling_devs) in qmp_cooling_devices_register()
489 return -ENOMEM; in qmp_cooling_devices_register()
492 if (!of_find_property(child, "#cooling-cells", NULL)) in qmp_cooling_devices_register()
494 ret = qmp_cooling_device_add(qmp, &qmp->cooling_devs[count++], in qmp_cooling_devices_register()
501 devm_kfree(qmp->dev, qmp->cooling_devs); in qmp_cooling_devices_register()
506 while (--count >= 0) in qmp_cooling_devices_register()
508 (qmp->cooling_devs[count].cdev); in qmp_cooling_devices_register()
509 devm_kfree(qmp->dev, qmp->cooling_devs); in qmp_cooling_devices_register()
514 static void qmp_cooling_devices_remove(struct qmp *qmp) in qmp_cooling_devices_remove() argument
519 thermal_cooling_device_unregister(qmp->cooling_devs[i].cdev); in qmp_cooling_devices_remove()
525 struct qmp *qmp; in qmp_probe() local
529 qmp = devm_kzalloc(&pdev->dev, sizeof(*qmp), GFP_KERNEL); in qmp_probe()
530 if (!qmp) in qmp_probe()
531 return -ENOMEM; in qmp_probe()
533 qmp->dev = &pdev->dev; in qmp_probe()
534 init_waitqueue_head(&qmp->event); in qmp_probe()
535 mutex_init(&qmp->tx_lock); in qmp_probe()
538 qmp->msgram = devm_ioremap_resource(&pdev->dev, res); in qmp_probe()
539 if (IS_ERR(qmp->msgram)) in qmp_probe()
540 return PTR_ERR(qmp->msgram); in qmp_probe()
542 qmp->mbox_client.dev = &pdev->dev; in qmp_probe()
543 qmp->mbox_client.knows_txdone = true; in qmp_probe()
544 qmp->mbox_chan = mbox_request_channel(&qmp->mbox_client, 0); in qmp_probe()
545 if (IS_ERR(qmp->mbox_chan)) { in qmp_probe()
546 dev_err(&pdev->dev, "failed to acquire ipc mailbox\n"); in qmp_probe()
547 return PTR_ERR(qmp->mbox_chan); in qmp_probe()
551 ret = devm_request_irq(&pdev->dev, irq, qmp_intr, IRQF_ONESHOT, in qmp_probe()
552 "aoss-qmp", qmp); in qmp_probe()
554 dev_err(&pdev->dev, "failed to request interrupt\n"); in qmp_probe()
558 ret = qmp_open(qmp); in qmp_probe()
562 ret = qmp_qdss_clk_add(qmp); in qmp_probe()
566 ret = qmp_pd_add(qmp); in qmp_probe()
570 ret = qmp_cooling_devices_register(qmp); in qmp_probe()
572 dev_err(&pdev->dev, "failed to register aoss cooling devices\n"); in qmp_probe()
574 platform_set_drvdata(pdev, qmp); in qmp_probe()
579 qmp_qdss_clk_remove(qmp); in qmp_probe()
581 qmp_close(qmp); in qmp_probe()
583 mbox_free_channel(qmp->mbox_chan); in qmp_probe()
590 struct qmp *qmp = platform_get_drvdata(pdev); in qmp_remove() local
592 qmp_qdss_clk_remove(qmp); in qmp_remove()
593 qmp_pd_remove(qmp); in qmp_remove()
594 qmp_cooling_devices_remove(qmp); in qmp_remove()
596 qmp_close(qmp); in qmp_remove()
597 mbox_free_channel(qmp->mbox_chan); in qmp_remove()
603 { .compatible = "qcom,sc7180-aoss-qmp", },
604 { .compatible = "qcom,sc7280-aoss-qmp", },
605 { .compatible = "qcom,sdm845-aoss-qmp", },
606 { .compatible = "qcom,sm8150-aoss-qmp", },
607 { .compatible = "qcom,sm8250-aoss-qmp", },
608 { .compatible = "qcom,sm8350-aoss-qmp", },
609 { .compatible = "qcom,aoss-qmp", },
624 MODULE_DESCRIPTION("Qualcomm AOSS QMP driver");