Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 518e2976 authored by jionzhao's avatar jionzhao Committed by Gerrit - the friendly Code Review server
Browse files

misc: add qrc ioctl functions



1,add qrc gpio init functions.
2,add qrc ioctl functions to control gpios.

Change-Id: I539c3d934b6fab1e68e78b910982e482e9f8151f
Signed-off-by: default avatarjionzhao <jionzhao@codeaurora.org>
parent 459fb44e
Loading
Loading
Loading
Loading
+109 −9
Original line number Diff line number Diff line
@@ -13,6 +13,10 @@
#include <linux/poll.h>
#include <linux/platform_device.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/delay.h>

#include "qrc_core.h"

@@ -54,20 +58,114 @@ static int qrc_cdev_release(struct inode *inode, struct file *filp)
	return 0;
}

/* GPIO control  */
static int
qrc_control_gpio_init(struct qrc_dev *qdev, struct device_node *node)
{
	int ret;

	/* QRC BOOT0 GPIO */
	qdev->qrc_boot0_gpio = of_get_named_gpio(node,
	"qcom,qrc-boot-gpio", 0);
	if (qdev->qrc_boot0_gpio < 0)
		pr_err("qrc_boot0_gpio is not available\n");

	/* UART RESET GPIO */
	qdev->qrc_reset_gpio = of_get_named_gpio(node,
	"qcom,qrc-reset-gpio", 0);
	if (qdev->qrc_reset_gpio < 0)
		pr_err("qrc_reset_gpio is not available\n");

	if (gpio_is_valid(qdev->qrc_boot0_gpio)) {
		ret = gpio_request(qdev->qrc_boot0_gpio, "QRC_BOOT0_GPIO");
		if (unlikely(ret)) {
			pr_err("gpio request qrc_boot0_gpio failed for:%d\n",
					qdev->qrc_boot0_gpio);
			return ret;
		}
	}

	if (gpio_is_valid(qdev->qrc_reset_gpio)) {
		ret = gpio_request(qdev->qrc_reset_gpio, "QRC_RESET_GPIO");
		if (unlikely(ret)) {
			pr_err("gpio request qrc_reset_gpio failed for:%d\n",
			qdev->qrc_reset_gpio);
			return ret;
		}
	}

	ret = gpio_direction_output(qdev->qrc_reset_gpio, 0);
	ret += gpio_export(qdev->qrc_reset_gpio, 0);

	if (ret) {
		pr_err("Unable to configure GPIO%d (RESET)\n",
			qdev->qrc_reset_gpio);
		ret = -EBUSY;
		gpio_free(qdev->qrc_reset_gpio);
		return ret;
	}

	ret = gpio_direction_output(qdev->qrc_boot0_gpio, 1);
	ret += gpio_export(qdev->qrc_boot0_gpio, 0);
	if (ret) {
		pr_err("Unable to configure GPIO%d (BOOT0)\n",
			qdev->qrc_boot0_gpio);
		ret = -EBUSY;
		gpio_free(qdev->qrc_boot0_gpio);
		return ret;
	}
	/* default config gpio status.boot=1,reset=0 */
	gpio_set_value(qdev->qrc_boot0_gpio, 1);
	gpio_set_value(qdev->qrc_reset_gpio, 0);

	return 0;
}

static void
qrc_control_gpio_uninit(struct qrc_dev *qdev)
{
	gpio_free(qdev->qrc_boot0_gpio);
	gpio_free(qdev->qrc_reset_gpio);
}

static void qrc_gpio_reboot(struct qrc_dev *qdev)
{
	gpio_set_value(qdev->qrc_reset_gpio, 0);
	msleep(100);
	gpio_set_value(qdev->qrc_reset_gpio, 1);
}
static long qrc_cdev_ioctl(struct file *filp, unsigned int cmd,
			     unsigned long arg)
{
	struct qrc_dev *qrc;
	struct qrc_dev *qdev;

	qrc = filp->private_data;
	qdev = filp->private_data;
	switch (cmd) {
	case FIFO_CLEAR:
		mutex_lock(&qrc->mutex);
		//check kfifo if have data
		mutex_unlock(&qrc->mutex);

		break;

	case QRC_FIFO_CLEAR:
		mutex_lock(&qdev->mutex);
		qdev->qrc_ops->qrcops_data_clean(qdev);
		mutex_unlock(&qdev->mutex);
		return 0;
	case QRC_REBOOT:
		if (gpio_is_valid(qdev->qrc_reset_gpio)) {
			qrc_gpio_reboot(qdev);
			return 0;
		} else
			return -EFAULT;
	case QRC_BOOT_TO_MEM:
		if (gpio_is_valid(qdev->qrc_boot0_gpio)) {
			gpio_set_value(qdev->qrc_boot0_gpio, 1);
			qrc_gpio_reboot(qdev);
			return 0;
		} else
			return -EFAULT;
	case QRC_BOOT_TO_FLASH:
		if (gpio_is_valid(qdev->qrc_boot0_gpio)) {
			gpio_set_value(qdev->qrc_boot0_gpio, 0);
			qrc_gpio_reboot(qdev);
			return 0;
		} else
			return -EFAULT;
	default:
		return -EINVAL;
	}
@@ -186,6 +284,7 @@ int qrc_register_device(struct qrc_dev *qdev, struct device *dev)
	devt = MKDEV(MAJOR(qrc_devt), 0);

	cdev_init(&qdev->cdev, &qrc_cdev_fops);
	ret = qrc_control_gpio_init(qdev, dev->of_node);

	ret = cdev_add(&qdev->cdev, devt, 1);
	if (ret) {
@@ -211,5 +310,6 @@ int qrc_register_device(struct qrc_dev *qdev, struct device *dev)
void qrc_unregister(struct qrc_dev *qdev)
{
	device_destroy(qrc_class, qdev->dev->devt);
	qrc_control_gpio_uninit(qdev);
	dev_info(qdev->dev, "qrc drv unregistered\n");
}
+17 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/kfifo.h>
#include <linux/sched/signal.h>
#include <linux/uaccess.h>
#include <linux/ioctl.h>

#define QRC_NAME_SIZE 30
#define QRC_INTERFACE_SIZE 30
@@ -21,6 +22,19 @@

struct qrc_dev;

/* IOCTL commands */
#define QRC_IOC_MAGIC   'q'

/* Clear read fifo */
#define QRC_FIFO_CLEAR	_IO(QRC_IOC_MAGIC, 1)
/* Reboot QRC controller */
#define QRC_REBOOT	_IO(QRC_IOC_MAGIC, 2)
/* QRC boot from memory */
#define QRC_BOOT_TO_MEM	_IO(QRC_IOC_MAGIC, 3)
/* QRC boot from flash */
#define QRC_BOOT_TO_FLASH	_IO(QRC_IOC_MAGIC, 4)


enum qrcdev_state_t {
	__STATE_IDLE,
	__STATE_READING,
@@ -62,6 +76,7 @@ struct qrc_device_ops {
	int		(*qrcops_data_status)
			(struct qrc_dev *dev);
	int		(*qrcops_config)(struct qrc_dev *dev);
	void	(*qrcops_data_clean)(struct qrc_dev *dev);
};

/* qrc char device */
@@ -76,6 +91,8 @@ struct qrc_dev {
	struct cdev cdev;
	struct device *dev;
	void *data;
	int qrc_boot0_gpio;
	int qrc_reset_gpio;
};

/**
+10 −0
Original line number Diff line number Diff line
@@ -168,6 +168,14 @@ static int qrcuart_data_status(struct qrc_dev *dev)
	return kfifo_len(&qrc->qrc_rx_fifo);
}

static void qrcuart_data_clean(struct qrc_dev *dev)
{
	struct qrcuart *qrc = qrc_get_data(dev);

	kfifo_reset(&qrc->qrc_rx_fifo);
}


static enum qrcdev_tx qrcuart_xmit(const char __user  *buf,
				size_t data_length, struct qrc_dev *dev)
{
@@ -220,6 +228,7 @@ static const struct qrc_device_ops qrcuart_qrc_ops = {
	.qrcops_config = qrcuart_config,
	.qrcops_setup = qrcuart_setup,
	.qrcops_data_status = qrcuart_data_status,
	.qrcops_data_clean = qrcuart_data_clean,
};

static int qrcuart_setup(struct qrc_dev *dev)
@@ -269,6 +278,7 @@ static int qrc_uart_probe(struct serdev_device *serdev)
	serdev_device_set_flow_control(serdev, false);

	ret = qrc_register_device(qdev, &serdev->dev);

	if (ret) {
		pr_err("qrcuart: Unable to register qrc device %s\n");
		serdev_device_close(serdev);