cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

qcom_aoss.c (13462B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2019, Linaro Ltd
      4 */
      5#include <linux/clk-provider.h>
      6#include <linux/interrupt.h>
      7#include <linux/io.h>
      8#include <linux/mailbox_client.h>
      9#include <linux/module.h>
     10#include <linux/of_platform.h>
     11#include <linux/platform_device.h>
     12#include <linux/thermal.h>
     13#include <linux/slab.h>
     14#include <linux/soc/qcom/qcom_aoss.h>
     15
     16#define QMP_DESC_MAGIC			0x0
     17#define QMP_DESC_VERSION		0x4
     18#define QMP_DESC_FEATURES		0x8
     19
     20/* AOP-side offsets */
     21#define QMP_DESC_UCORE_LINK_STATE	0xc
     22#define QMP_DESC_UCORE_LINK_STATE_ACK	0x10
     23#define QMP_DESC_UCORE_CH_STATE		0x14
     24#define QMP_DESC_UCORE_CH_STATE_ACK	0x18
     25#define QMP_DESC_UCORE_MBOX_SIZE	0x1c
     26#define QMP_DESC_UCORE_MBOX_OFFSET	0x20
     27
     28/* Linux-side offsets */
     29#define QMP_DESC_MCORE_LINK_STATE	0x24
     30#define QMP_DESC_MCORE_LINK_STATE_ACK	0x28
     31#define QMP_DESC_MCORE_CH_STATE		0x2c
     32#define QMP_DESC_MCORE_CH_STATE_ACK	0x30
     33#define QMP_DESC_MCORE_MBOX_SIZE	0x34
     34#define QMP_DESC_MCORE_MBOX_OFFSET	0x38
     35
     36#define QMP_STATE_UP			GENMASK(15, 0)
     37#define QMP_STATE_DOWN			GENMASK(31, 16)
     38
     39#define QMP_MAGIC			0x4d41494c /* mail */
     40#define QMP_VERSION			1
     41
     42/* 64 bytes is enough to store the requests and provides padding to 4 bytes */
     43#define QMP_MSG_LEN			64
     44
     45#define QMP_NUM_COOLING_RESOURCES	2
     46
     47static bool qmp_cdev_max_state = 1;
     48
     49struct qmp_cooling_device {
     50	struct thermal_cooling_device *cdev;
     51	struct qmp *qmp;
     52	char *name;
     53	bool state;
     54};
     55
     56/**
     57 * struct qmp - driver state for QMP implementation
     58 * @msgram: iomem referencing the message RAM used for communication
     59 * @dev: reference to QMP device
     60 * @mbox_client: mailbox client used to ring the doorbell on transmit
     61 * @mbox_chan: mailbox channel used to ring the doorbell on transmit
     62 * @offset: offset within @msgram where messages should be written
     63 * @size: maximum size of the messages to be transmitted
     64 * @event: wait_queue for synchronization with the IRQ
     65 * @tx_lock: provides synchronization between multiple callers of qmp_send()
     66 * @qdss_clk: QDSS clock hw struct
     67 * @cooling_devs: thermal cooling devices
     68 */
     69struct qmp {
     70	void __iomem *msgram;
     71	struct device *dev;
     72
     73	struct mbox_client mbox_client;
     74	struct mbox_chan *mbox_chan;
     75
     76	size_t offset;
     77	size_t size;
     78
     79	wait_queue_head_t event;
     80
     81	struct mutex tx_lock;
     82
     83	struct clk_hw qdss_clk;
     84	struct qmp_cooling_device *cooling_devs;
     85};
     86
     87static void qmp_kick(struct qmp *qmp)
     88{
     89	mbox_send_message(qmp->mbox_chan, NULL);
     90	mbox_client_txdone(qmp->mbox_chan, 0);
     91}
     92
     93static bool qmp_magic_valid(struct qmp *qmp)
     94{
     95	return readl(qmp->msgram + QMP_DESC_MAGIC) == QMP_MAGIC;
     96}
     97
     98static bool qmp_link_acked(struct qmp *qmp)
     99{
    100	return readl(qmp->msgram + QMP_DESC_MCORE_LINK_STATE_ACK) == QMP_STATE_UP;
    101}
    102
    103static bool qmp_mcore_channel_acked(struct qmp *qmp)
    104{
    105	return readl(qmp->msgram + QMP_DESC_MCORE_CH_STATE_ACK) == QMP_STATE_UP;
    106}
    107
    108static bool qmp_ucore_channel_up(struct qmp *qmp)
    109{
    110	return readl(qmp->msgram + QMP_DESC_UCORE_CH_STATE) == QMP_STATE_UP;
    111}
    112
    113static int qmp_open(struct qmp *qmp)
    114{
    115	int ret;
    116	u32 val;
    117
    118	if (!qmp_magic_valid(qmp)) {
    119		dev_err(qmp->dev, "QMP magic doesn't match\n");
    120		return -EINVAL;
    121	}
    122
    123	val = readl(qmp->msgram + QMP_DESC_VERSION);
    124	if (val != QMP_VERSION) {
    125		dev_err(qmp->dev, "unsupported QMP version %d\n", val);
    126		return -EINVAL;
    127	}
    128
    129	qmp->offset = readl(qmp->msgram + QMP_DESC_MCORE_MBOX_OFFSET);
    130	qmp->size = readl(qmp->msgram + QMP_DESC_MCORE_MBOX_SIZE);
    131	if (!qmp->size) {
    132		dev_err(qmp->dev, "invalid mailbox size\n");
    133		return -EINVAL;
    134	}
    135
    136	/* Ack remote core's link state */
    137	val = readl(qmp->msgram + QMP_DESC_UCORE_LINK_STATE);
    138	writel(val, qmp->msgram + QMP_DESC_UCORE_LINK_STATE_ACK);
    139
    140	/* Set local core's link state to up */
    141	writel(QMP_STATE_UP, qmp->msgram + QMP_DESC_MCORE_LINK_STATE);
    142
    143	qmp_kick(qmp);
    144
    145	ret = wait_event_timeout(qmp->event, qmp_link_acked(qmp), HZ);
    146	if (!ret) {
    147		dev_err(qmp->dev, "ucore didn't ack link\n");
    148		goto timeout_close_link;
    149	}
    150
    151	writel(QMP_STATE_UP, qmp->msgram + QMP_DESC_MCORE_CH_STATE);
    152
    153	qmp_kick(qmp);
    154
    155	ret = wait_event_timeout(qmp->event, qmp_ucore_channel_up(qmp), HZ);
    156	if (!ret) {
    157		dev_err(qmp->dev, "ucore didn't open channel\n");
    158		goto timeout_close_channel;
    159	}
    160
    161	/* Ack remote core's channel state */
    162	writel(QMP_STATE_UP, qmp->msgram + QMP_DESC_UCORE_CH_STATE_ACK);
    163
    164	qmp_kick(qmp);
    165
    166	ret = wait_event_timeout(qmp->event, qmp_mcore_channel_acked(qmp), HZ);
    167	if (!ret) {
    168		dev_err(qmp->dev, "ucore didn't ack channel\n");
    169		goto timeout_close_channel;
    170	}
    171
    172	return 0;
    173
    174timeout_close_channel:
    175	writel(QMP_STATE_DOWN, qmp->msgram + QMP_DESC_MCORE_CH_STATE);
    176
    177timeout_close_link:
    178	writel(QMP_STATE_DOWN, qmp->msgram + QMP_DESC_MCORE_LINK_STATE);
    179	qmp_kick(qmp);
    180
    181	return -ETIMEDOUT;
    182}
    183
    184static void qmp_close(struct qmp *qmp)
    185{
    186	writel(QMP_STATE_DOWN, qmp->msgram + QMP_DESC_MCORE_CH_STATE);
    187	writel(QMP_STATE_DOWN, qmp->msgram + QMP_DESC_MCORE_LINK_STATE);
    188	qmp_kick(qmp);
    189}
    190
    191static irqreturn_t qmp_intr(int irq, void *data)
    192{
    193	struct qmp *qmp = data;
    194
    195	wake_up_all(&qmp->event);
    196
    197	return IRQ_HANDLED;
    198}
    199
    200static bool qmp_message_empty(struct qmp *qmp)
    201{
    202	return readl(qmp->msgram + qmp->offset) == 0;
    203}
    204
    205/**
    206 * qmp_send() - send a message to the AOSS
    207 * @qmp: qmp context
    208 * @data: message to be sent
    209 * @len: length of the message
    210 *
    211 * Transmit @data to AOSS and wait for the AOSS to acknowledge the message.
    212 * @len must be a multiple of 4 and not longer than the mailbox size. Access is
    213 * synchronized by this implementation.
    214 *
    215 * Return: 0 on success, negative errno on failure
    216 */
    217int qmp_send(struct qmp *qmp, const void *data, size_t len)
    218{
    219	long time_left;
    220	int ret;
    221
    222	if (WARN_ON(IS_ERR_OR_NULL(qmp) || !data))
    223		return -EINVAL;
    224
    225	if (WARN_ON(len + sizeof(u32) > qmp->size))
    226		return -EINVAL;
    227
    228	if (WARN_ON(len % sizeof(u32)))
    229		return -EINVAL;
    230
    231	mutex_lock(&qmp->tx_lock);
    232
    233	/* The message RAM only implements 32-bit accesses */
    234	__iowrite32_copy(qmp->msgram + qmp->offset + sizeof(u32),
    235			 data, len / sizeof(u32));
    236	writel(len, qmp->msgram + qmp->offset);
    237
    238	/* Read back len to confirm data written in message RAM */
    239	readl(qmp->msgram + qmp->offset);
    240	qmp_kick(qmp);
    241
    242	time_left = wait_event_interruptible_timeout(qmp->event,
    243						     qmp_message_empty(qmp), HZ);
    244	if (!time_left) {
    245		dev_err(qmp->dev, "ucore did not ack channel\n");
    246		ret = -ETIMEDOUT;
    247
    248		/* Clear message from buffer */
    249		writel(0, qmp->msgram + qmp->offset);
    250	} else {
    251		ret = 0;
    252	}
    253
    254	mutex_unlock(&qmp->tx_lock);
    255
    256	return ret;
    257}
    258EXPORT_SYMBOL(qmp_send);
    259
    260static int qmp_qdss_clk_prepare(struct clk_hw *hw)
    261{
    262	static const char buf[QMP_MSG_LEN] = "{class: clock, res: qdss, val: 1}";
    263	struct qmp *qmp = container_of(hw, struct qmp, qdss_clk);
    264
    265	return qmp_send(qmp, buf, sizeof(buf));
    266}
    267
    268static void qmp_qdss_clk_unprepare(struct clk_hw *hw)
    269{
    270	static const char buf[QMP_MSG_LEN] = "{class: clock, res: qdss, val: 0}";
    271	struct qmp *qmp = container_of(hw, struct qmp, qdss_clk);
    272
    273	qmp_send(qmp, buf, sizeof(buf));
    274}
    275
    276static const struct clk_ops qmp_qdss_clk_ops = {
    277	.prepare = qmp_qdss_clk_prepare,
    278	.unprepare = qmp_qdss_clk_unprepare,
    279};
    280
    281static int qmp_qdss_clk_add(struct qmp *qmp)
    282{
    283	static const struct clk_init_data qdss_init = {
    284		.ops = &qmp_qdss_clk_ops,
    285		.name = "qdss",
    286	};
    287	int ret;
    288
    289	qmp->qdss_clk.init = &qdss_init;
    290	ret = clk_hw_register(qmp->dev, &qmp->qdss_clk);
    291	if (ret < 0) {
    292		dev_err(qmp->dev, "failed to register qdss clock\n");
    293		return ret;
    294	}
    295
    296	ret = of_clk_add_hw_provider(qmp->dev->of_node, of_clk_hw_simple_get,
    297				     &qmp->qdss_clk);
    298	if (ret < 0) {
    299		dev_err(qmp->dev, "unable to register of clk hw provider\n");
    300		clk_hw_unregister(&qmp->qdss_clk);
    301	}
    302
    303	return ret;
    304}
    305
    306static void qmp_qdss_clk_remove(struct qmp *qmp)
    307{
    308	of_clk_del_provider(qmp->dev->of_node);
    309	clk_hw_unregister(&qmp->qdss_clk);
    310}
    311
    312static int qmp_cdev_get_max_state(struct thermal_cooling_device *cdev,
    313				  unsigned long *state)
    314{
    315	*state = qmp_cdev_max_state;
    316	return 0;
    317}
    318
    319static int qmp_cdev_get_cur_state(struct thermal_cooling_device *cdev,
    320				  unsigned long *state)
    321{
    322	struct qmp_cooling_device *qmp_cdev = cdev->devdata;
    323
    324	*state = qmp_cdev->state;
    325	return 0;
    326}
    327
    328static int qmp_cdev_set_cur_state(struct thermal_cooling_device *cdev,
    329				  unsigned long state)
    330{
    331	struct qmp_cooling_device *qmp_cdev = cdev->devdata;
    332	char buf[QMP_MSG_LEN] = {};
    333	bool cdev_state;
    334	int ret;
    335
    336	/* Normalize state */
    337	cdev_state = !!state;
    338
    339	if (qmp_cdev->state == state)
    340		return 0;
    341
    342	snprintf(buf, sizeof(buf),
    343		 "{class: volt_flr, event:zero_temp, res:%s, value:%s}",
    344			qmp_cdev->name,
    345			cdev_state ? "on" : "off");
    346
    347	ret = qmp_send(qmp_cdev->qmp, buf, sizeof(buf));
    348
    349	if (!ret)
    350		qmp_cdev->state = cdev_state;
    351
    352	return ret;
    353}
    354
    355static const struct thermal_cooling_device_ops qmp_cooling_device_ops = {
    356	.get_max_state = qmp_cdev_get_max_state,
    357	.get_cur_state = qmp_cdev_get_cur_state,
    358	.set_cur_state = qmp_cdev_set_cur_state,
    359};
    360
    361static int qmp_cooling_device_add(struct qmp *qmp,
    362				  struct qmp_cooling_device *qmp_cdev,
    363				  struct device_node *node)
    364{
    365	char *cdev_name = (char *)node->name;
    366
    367	qmp_cdev->qmp = qmp;
    368	qmp_cdev->state = !qmp_cdev_max_state;
    369	qmp_cdev->name = cdev_name;
    370	qmp_cdev->cdev = devm_thermal_of_cooling_device_register
    371				(qmp->dev, node,
    372				cdev_name,
    373				qmp_cdev, &qmp_cooling_device_ops);
    374
    375	if (IS_ERR(qmp_cdev->cdev))
    376		dev_err(qmp->dev, "unable to register %s cooling device\n",
    377			cdev_name);
    378
    379	return PTR_ERR_OR_ZERO(qmp_cdev->cdev);
    380}
    381
    382static int qmp_cooling_devices_register(struct qmp *qmp)
    383{
    384	struct device_node *np, *child;
    385	int count = 0;
    386	int ret;
    387
    388	np = qmp->dev->of_node;
    389
    390	qmp->cooling_devs = devm_kcalloc(qmp->dev, QMP_NUM_COOLING_RESOURCES,
    391					 sizeof(*qmp->cooling_devs),
    392					 GFP_KERNEL);
    393
    394	if (!qmp->cooling_devs)
    395		return -ENOMEM;
    396
    397	for_each_available_child_of_node(np, child) {
    398		if (!of_find_property(child, "#cooling-cells", NULL))
    399			continue;
    400		ret = qmp_cooling_device_add(qmp, &qmp->cooling_devs[count++],
    401					     child);
    402		if (ret)
    403			goto unroll;
    404	}
    405
    406	if (!count)
    407		devm_kfree(qmp->dev, qmp->cooling_devs);
    408
    409	return 0;
    410
    411unroll:
    412	while (--count >= 0)
    413		thermal_cooling_device_unregister
    414			(qmp->cooling_devs[count].cdev);
    415	devm_kfree(qmp->dev, qmp->cooling_devs);
    416
    417	return ret;
    418}
    419
    420static void qmp_cooling_devices_remove(struct qmp *qmp)
    421{
    422	int i;
    423
    424	for (i = 0; i < QMP_NUM_COOLING_RESOURCES; i++)
    425		thermal_cooling_device_unregister(qmp->cooling_devs[i].cdev);
    426}
    427
    428/**
    429 * qmp_get() - get a qmp handle from a device
    430 * @dev: client device pointer
    431 *
    432 * Return: handle to qmp device on success, ERR_PTR() on failure
    433 */
    434struct qmp *qmp_get(struct device *dev)
    435{
    436	struct platform_device *pdev;
    437	struct device_node *np;
    438	struct qmp *qmp;
    439
    440	if (!dev || !dev->of_node)
    441		return ERR_PTR(-EINVAL);
    442
    443	np = of_parse_phandle(dev->of_node, "qcom,qmp", 0);
    444	if (!np)
    445		return ERR_PTR(-ENODEV);
    446
    447	pdev = of_find_device_by_node(np);
    448	of_node_put(np);
    449	if (!pdev)
    450		return ERR_PTR(-EINVAL);
    451
    452	qmp = platform_get_drvdata(pdev);
    453
    454	if (!qmp) {
    455		put_device(&pdev->dev);
    456		return ERR_PTR(-EPROBE_DEFER);
    457	}
    458	return qmp;
    459}
    460EXPORT_SYMBOL(qmp_get);
    461
    462/**
    463 * qmp_put() - release a qmp handle
    464 * @qmp: qmp handle obtained from qmp_get()
    465 */
    466void qmp_put(struct qmp *qmp)
    467{
    468	/*
    469	 * Match get_device() inside of_find_device_by_node() in
    470	 * qmp_get()
    471	 */
    472	if (!IS_ERR_OR_NULL(qmp))
    473		put_device(qmp->dev);
    474}
    475EXPORT_SYMBOL(qmp_put);
    476
    477static int qmp_probe(struct platform_device *pdev)
    478{
    479	struct qmp *qmp;
    480	int irq;
    481	int ret;
    482
    483	qmp = devm_kzalloc(&pdev->dev, sizeof(*qmp), GFP_KERNEL);
    484	if (!qmp)
    485		return -ENOMEM;
    486
    487	qmp->dev = &pdev->dev;
    488	init_waitqueue_head(&qmp->event);
    489	mutex_init(&qmp->tx_lock);
    490
    491	qmp->msgram = devm_platform_ioremap_resource(pdev, 0);
    492	if (IS_ERR(qmp->msgram))
    493		return PTR_ERR(qmp->msgram);
    494
    495	qmp->mbox_client.dev = &pdev->dev;
    496	qmp->mbox_client.knows_txdone = true;
    497	qmp->mbox_chan = mbox_request_channel(&qmp->mbox_client, 0);
    498	if (IS_ERR(qmp->mbox_chan)) {
    499		dev_err(&pdev->dev, "failed to acquire ipc mailbox\n");
    500		return PTR_ERR(qmp->mbox_chan);
    501	}
    502
    503	irq = platform_get_irq(pdev, 0);
    504	ret = devm_request_irq(&pdev->dev, irq, qmp_intr, 0,
    505			       "aoss-qmp", qmp);
    506	if (ret < 0) {
    507		dev_err(&pdev->dev, "failed to request interrupt\n");
    508		goto err_free_mbox;
    509	}
    510
    511	ret = qmp_open(qmp);
    512	if (ret < 0)
    513		goto err_free_mbox;
    514
    515	ret = qmp_qdss_clk_add(qmp);
    516	if (ret)
    517		goto err_close_qmp;
    518
    519	ret = qmp_cooling_devices_register(qmp);
    520	if (ret)
    521		dev_err(&pdev->dev, "failed to register aoss cooling devices\n");
    522
    523	platform_set_drvdata(pdev, qmp);
    524
    525	return 0;
    526
    527err_close_qmp:
    528	qmp_close(qmp);
    529err_free_mbox:
    530	mbox_free_channel(qmp->mbox_chan);
    531
    532	return ret;
    533}
    534
    535static int qmp_remove(struct platform_device *pdev)
    536{
    537	struct qmp *qmp = platform_get_drvdata(pdev);
    538
    539	qmp_qdss_clk_remove(qmp);
    540	qmp_cooling_devices_remove(qmp);
    541
    542	qmp_close(qmp);
    543	mbox_free_channel(qmp->mbox_chan);
    544
    545	return 0;
    546}
    547
    548static const struct of_device_id qmp_dt_match[] = {
    549	{ .compatible = "qcom,sc7180-aoss-qmp", },
    550	{ .compatible = "qcom,sc7280-aoss-qmp", },
    551	{ .compatible = "qcom,sdm845-aoss-qmp", },
    552	{ .compatible = "qcom,sm8150-aoss-qmp", },
    553	{ .compatible = "qcom,sm8250-aoss-qmp", },
    554	{ .compatible = "qcom,sm8350-aoss-qmp", },
    555	{ .compatible = "qcom,aoss-qmp", },
    556	{}
    557};
    558MODULE_DEVICE_TABLE(of, qmp_dt_match);
    559
    560static struct platform_driver qmp_driver = {
    561	.driver = {
    562		.name		= "qcom_aoss_qmp",
    563		.of_match_table	= qmp_dt_match,
    564		.suppress_bind_attrs = true,
    565	},
    566	.probe = qmp_probe,
    567	.remove	= qmp_remove,
    568};
    569module_platform_driver(qmp_driver);
    570
    571MODULE_DESCRIPTION("Qualcomm AOSS QMP driver");
    572MODULE_LICENSE("GPL v2");