162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Remote processor messaging - sample client driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2011 Texas Instruments, Inc.
662306a36Sopenharmony_ci * Copyright (C) 2011 Google, Inc.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Ohad Ben-Cohen <ohad@wizery.com>
962306a36Sopenharmony_ci * Brian Swetland <swetland@google.com>
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/kernel.h>
1362306a36Sopenharmony_ci#include <linux/module.h>
1462306a36Sopenharmony_ci#include <linux/rpmsg.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define MSG		"hello world!"
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistatic int count = 100;
1962306a36Sopenharmony_cimodule_param(count, int, 0644);
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cistruct instance_data {
2262306a36Sopenharmony_ci	int rx_count;
2362306a36Sopenharmony_ci};
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic int rpmsg_sample_cb(struct rpmsg_device *rpdev, void *data, int len,
2662306a36Sopenharmony_ci						void *priv, u32 src)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	int ret;
2962306a36Sopenharmony_ci	struct instance_data *idata = dev_get_drvdata(&rpdev->dev);
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	dev_info(&rpdev->dev, "incoming msg %d (src: 0x%x)\n",
3262306a36Sopenharmony_ci		 ++idata->rx_count, src);
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	print_hex_dump_debug(__func__, DUMP_PREFIX_NONE, 16, 1, data, len,
3562306a36Sopenharmony_ci			     true);
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	/* samples should not live forever */
3862306a36Sopenharmony_ci	if (idata->rx_count >= count) {
3962306a36Sopenharmony_ci		dev_info(&rpdev->dev, "goodbye!\n");
4062306a36Sopenharmony_ci		return 0;
4162306a36Sopenharmony_ci	}
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	/* send a new message now */
4462306a36Sopenharmony_ci	ret = rpmsg_send(rpdev->ept, MSG, strlen(MSG));
4562306a36Sopenharmony_ci	if (ret)
4662306a36Sopenharmony_ci		dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	return 0;
4962306a36Sopenharmony_ci}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cistatic int rpmsg_sample_probe(struct rpmsg_device *rpdev)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	int ret;
5462306a36Sopenharmony_ci	struct instance_data *idata;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
5762306a36Sopenharmony_ci					rpdev->src, rpdev->dst);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	idata = devm_kzalloc(&rpdev->dev, sizeof(*idata), GFP_KERNEL);
6062306a36Sopenharmony_ci	if (!idata)
6162306a36Sopenharmony_ci		return -ENOMEM;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	dev_set_drvdata(&rpdev->dev, idata);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	/* send a message to our remote processor */
6662306a36Sopenharmony_ci	ret = rpmsg_send(rpdev->ept, MSG, strlen(MSG));
6762306a36Sopenharmony_ci	if (ret) {
6862306a36Sopenharmony_ci		dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
6962306a36Sopenharmony_ci		return ret;
7062306a36Sopenharmony_ci	}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	return 0;
7362306a36Sopenharmony_ci}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistatic void rpmsg_sample_remove(struct rpmsg_device *rpdev)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	dev_info(&rpdev->dev, "rpmsg sample client driver is removed\n");
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistatic struct rpmsg_device_id rpmsg_driver_sample_id_table[] = {
8162306a36Sopenharmony_ci	{ .name	= "rpmsg-client-sample" },
8262306a36Sopenharmony_ci	{ },
8362306a36Sopenharmony_ci};
8462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_sample_id_table);
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cistatic struct rpmsg_driver rpmsg_sample_client = {
8762306a36Sopenharmony_ci	.drv.name	= KBUILD_MODNAME,
8862306a36Sopenharmony_ci	.id_table	= rpmsg_driver_sample_id_table,
8962306a36Sopenharmony_ci	.probe		= rpmsg_sample_probe,
9062306a36Sopenharmony_ci	.callback	= rpmsg_sample_cb,
9162306a36Sopenharmony_ci	.remove		= rpmsg_sample_remove,
9262306a36Sopenharmony_ci};
9362306a36Sopenharmony_cimodule_rpmsg_driver(rpmsg_sample_client);
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ciMODULE_DESCRIPTION("Remote processor messaging sample client driver");
9662306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
97