18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * arch/arm/common/bL_switcher_dummy_if.c -- b.L switcher dummy interface
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Created by:	Nicolas Pitre, November 2012
68c2ecf20Sopenharmony_ci * Copyright:	(C) 2012-2013  Linaro Limited
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Dummy interface to user space for debugging purpose only.
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/init.h>
128c2ecf20Sopenharmony_ci#include <linux/module.h>
138c2ecf20Sopenharmony_ci#include <linux/fs.h>
148c2ecf20Sopenharmony_ci#include <linux/miscdevice.h>
158c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
168c2ecf20Sopenharmony_ci#include <asm/bL_switcher.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_cistatic ssize_t bL_switcher_write(struct file *file, const char __user *buf,
198c2ecf20Sopenharmony_ci			size_t len, loff_t *pos)
208c2ecf20Sopenharmony_ci{
218c2ecf20Sopenharmony_ci	unsigned char val[3];
228c2ecf20Sopenharmony_ci	unsigned int cpu, cluster;
238c2ecf20Sopenharmony_ci	int ret;
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	pr_debug("%s\n", __func__);
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	if (len < 3)
288c2ecf20Sopenharmony_ci		return -EINVAL;
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	if (copy_from_user(val, buf, 3))
318c2ecf20Sopenharmony_ci		return -EFAULT;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	/* format: <cpu#>,<cluster#> */
348c2ecf20Sopenharmony_ci	if (val[0] < '0' || val[0] > '9' ||
358c2ecf20Sopenharmony_ci	    val[1] != ',' ||
368c2ecf20Sopenharmony_ci	    val[2] < '0' || val[2] > '1')
378c2ecf20Sopenharmony_ci		return -EINVAL;
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	cpu = val[0] - '0';
408c2ecf20Sopenharmony_ci	cluster = val[2] - '0';
418c2ecf20Sopenharmony_ci	ret = bL_switch_request(cpu, cluster);
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	return ret ? : len;
448c2ecf20Sopenharmony_ci}
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_cistatic const struct file_operations bL_switcher_fops = {
478c2ecf20Sopenharmony_ci	.write		= bL_switcher_write,
488c2ecf20Sopenharmony_ci	.owner	= THIS_MODULE,
498c2ecf20Sopenharmony_ci};
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_cistatic struct miscdevice bL_switcher_device = {
528c2ecf20Sopenharmony_ci	MISC_DYNAMIC_MINOR,
538c2ecf20Sopenharmony_ci	"b.L_switcher",
548c2ecf20Sopenharmony_ci	&bL_switcher_fops
558c2ecf20Sopenharmony_ci};
568c2ecf20Sopenharmony_cimodule_misc_device(bL_switcher_device);
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ciMODULE_AUTHOR("Nicolas Pitre <nico@linaro.org>");
598c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
608c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("big.LITTLE switcher dummy user interface");
61