315 lines
7.3 KiB
Diff
315 lines
7.3 KiB
Diff
|
From e791d8951d749bcfddd9741c730fed4cafb0f38e Mon Sep 17 00:00:00 2001
|
||
|
From: brian <brian@vamrs.com>
|
||
|
Date: Tue, 30 Oct 2018 11:18:48 +0800
|
||
|
Subject: [PATCH 08/97] add mcu driver for rockpi lcd module
|
||
|
|
||
|
Change-Id: I4d9eb75bc69bb59ffe2b7b110431c9ceab2cb3b8
|
||
|
---
|
||
|
arch/arm64/configs/rockchip_linux_defconfig | 1 +
|
||
|
drivers/misc/Kconfig | 7 +
|
||
|
drivers/misc/Makefile | 1 +
|
||
|
drivers/misc/rockpi_mcu.c | 242 ++++++++++++++++++++
|
||
|
drivers/misc/rockpi_mcu.h | 14 ++
|
||
|
5 files changed, 265 insertions(+)
|
||
|
create mode 100644 drivers/misc/rockpi_mcu.c
|
||
|
create mode 100644 drivers/misc/rockpi_mcu.h
|
||
|
|
||
|
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
|
||
|
index 77fa126eb1f2..eec5802fd989 100644
|
||
|
--- a/drivers/misc/Kconfig
|
||
|
+++ b/drivers/misc/Kconfig
|
||
|
@@ -564,6 +564,13 @@ config GPIO_DET
|
||
|
help
|
||
|
Enable this driver will support gpio detection.
|
||
|
|
||
|
+config ROCKPI_MCU
|
||
|
+ tristate "rockpi mcu"
|
||
|
+ default y
|
||
|
+ depends on I2C
|
||
|
+ help
|
||
|
+ Control the power of touch screen for rockpi board.
|
||
|
+
|
||
|
source "drivers/misc/c2port/Kconfig"
|
||
|
source "drivers/misc/eeprom/Kconfig"
|
||
|
source "drivers/misc/cb710/Kconfig"
|
||
|
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
|
||
|
index b58f922dd5a0..059722165095 100644
|
||
|
--- a/drivers/misc/Makefile
|
||
|
+++ b/drivers/misc/Makefile
|
||
|
@@ -61,3 +61,4 @@ obj-$(CONFIG_CXL_BASE) += cxl/
|
||
|
obj-$(CONFIG_UID_SYS_STATS) += uid_sys_stats.o
|
||
|
obj-$(CONFIG_MEMORY_STATE_TIME) += memory_state_time.o
|
||
|
obj-$(CONFIG_USB_CAM_GPIO) += usb_cam_gpio.o
|
||
|
+obj-$(CONFIG_ROCKPI_MCU) += rockpi_mcu.o
|
||
|
diff --git a/drivers/misc/rockpi_mcu.c b/drivers/misc/rockpi_mcu.c
|
||
|
new file mode 100644
|
||
|
index 000000000000..38e7af802119
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/misc/rockpi_mcu.c
|
||
|
@@ -0,0 +1,242 @@
|
||
|
+/*
|
||
|
+ *
|
||
|
+ * Rockpi board Touchscreen MCU driver.
|
||
|
+ *
|
||
|
+ * Copyright (c) 2016 ASUSTek Computer Inc.
|
||
|
+ * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
|
||
|
+ *
|
||
|
+ * This software is licensed under the terms of the GNU General Public
|
||
|
+ * License version 2, as published by the Free Software Foundation, and
|
||
|
+ * may be copied, distributed, and modified under those terms.
|
||
|
+ *
|
||
|
+ * This program is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU General Public License for more details.
|
||
|
+ *
|
||
|
+ */
|
||
|
+
|
||
|
+#include <linux/module.h>
|
||
|
+#include <linux/slab.h>
|
||
|
+#include <linux/delay.h>
|
||
|
+#include <linux/i2c.h>
|
||
|
+#include <linux/module.h>
|
||
|
+#include <linux/workqueue.h>
|
||
|
+#include "rockpi_mcu.h"
|
||
|
+
|
||
|
+static struct rockpi_mcu_data *g_mcu_data;
|
||
|
+static int connected = 0;
|
||
|
+
|
||
|
+static int is_hex(char num)
|
||
|
+{
|
||
|
+ //0-9, a-f, A-F
|
||
|
+ if ((47 < num && num < 58) || (64 < num && num < 71) || (96 < num && num < 103))
|
||
|
+ return 1;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int string_to_byte(const char *source, unsigned char *destination, int size)
|
||
|
+{
|
||
|
+ int i = 0, counter = 0;
|
||
|
+ char c[3] = {0};
|
||
|
+ unsigned char bytes;
|
||
|
+
|
||
|
+ if (size%2 == 1)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ for(i = 0; i < size; i++){
|
||
|
+ if(!is_hex(source[i])) {
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+ if(0 == i%2){
|
||
|
+ c[0] = source[i];
|
||
|
+ c[1] = source[i+1];
|
||
|
+ sscanf(c, "%hhx", &bytes);
|
||
|
+ destination[counter] = bytes;
|
||
|
+ counter++;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int send_cmds(struct i2c_client *client, const char *buf)
|
||
|
+{
|
||
|
+ int ret, size = strlen(buf);
|
||
|
+ unsigned char byte_cmd[size/2];
|
||
|
+
|
||
|
+ if ((size%2) != 0) {
|
||
|
+ LOG_ERR("size should be even\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ LOG_INFO("%s\n", buf);
|
||
|
+
|
||
|
+ string_to_byte(buf, byte_cmd, size);
|
||
|
+
|
||
|
+ ret = i2c_master_send(client, byte_cmd, size/2);
|
||
|
+ if (ret <= 0) {
|
||
|
+ //LOG_ERR("send command failed, ret = %d\n", ret);
|
||
|
+ printk("send command failed, ret = %d\n", ret);
|
||
|
+ return ret!=0 ? ret : -ECOMM;
|
||
|
+ }
|
||
|
+ msleep(20);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int recv_cmds(struct i2c_client *client, char *buf, int size)
|
||
|
+{
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ ret = i2c_master_recv(client, buf, size);
|
||
|
+ if (ret <= 0) {
|
||
|
+ LOG_ERR("receive commands failed, %d\n", ret);
|
||
|
+ return ret!=0 ? ret : -ECOMM;
|
||
|
+ }
|
||
|
+ msleep(20);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int init_cmd_check(struct rockpi_mcu_data *mcu_data)
|
||
|
+{
|
||
|
+ int ret;
|
||
|
+ char recv_buf[1] = {0};
|
||
|
+
|
||
|
+ ret = send_cmds(mcu_data->client, "80");
|
||
|
+ if (ret < 0)
|
||
|
+ goto error;
|
||
|
+
|
||
|
+ recv_cmds(mcu_data->client, recv_buf, 1);
|
||
|
+ if (ret < 0)
|
||
|
+ goto error;
|
||
|
+
|
||
|
+ LOG_INFO("recv_cmds: 0x%X\n", recv_buf[0]);
|
||
|
+ if (recv_buf[0] != 0xDE && recv_buf[0] != 0xC3) {
|
||
|
+ LOG_ERR("read wrong info\n");
|
||
|
+ ret = -EINVAL;
|
||
|
+ goto error;
|
||
|
+
|
||
|
+ }
|
||
|
+ return 0;
|
||
|
+
|
||
|
+error:
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+int rockpi_mcu_screen_power_up(void)
|
||
|
+{
|
||
|
+ int res = 0;
|
||
|
+ if (!connected)
|
||
|
+ return -ENODEV;
|
||
|
+
|
||
|
+ LOG_INFO("\n");
|
||
|
+
|
||
|
+ res = send_cmds(g_mcu_data->client, "8500");
|
||
|
+ if(res < 0)
|
||
|
+ printk("send 8500 failed\n");
|
||
|
+ msleep(800);
|
||
|
+ res = send_cmds(g_mcu_data->client, "8501");
|
||
|
+ if(res < 0)
|
||
|
+ printk("send 8501 failed\n");
|
||
|
+ msleep(800);
|
||
|
+ res = send_cmds(g_mcu_data->client, "8104");
|
||
|
+ if(res < 0)
|
||
|
+ printk("send 8104 failed\n");
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+EXPORT_SYMBOL_GPL(rockpi_mcu_screen_power_up);
|
||
|
+
|
||
|
+int rockpi_mcu_set_bright(int bright)
|
||
|
+{
|
||
|
+ unsigned char cmd[2];
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ if (!connected)
|
||
|
+ return -ENODEV;
|
||
|
+
|
||
|
+ if (bright > 0xff || bright < 0)
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
+ LOG_INFO("bright = 0x%x\n", bright);
|
||
|
+
|
||
|
+ cmd[0] = 0x86;
|
||
|
+ cmd[1] = bright;
|
||
|
+
|
||
|
+ ret = i2c_master_send(g_mcu_data->client, cmd, 2);
|
||
|
+ if (ret <= 0) {
|
||
|
+ LOG_ERR("send command failed, ret = %d\n", ret);
|
||
|
+ return ret != 0 ? ret : -ECOMM;
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+EXPORT_SYMBOL_GPL(rockpi_mcu_set_bright);
|
||
|
+
|
||
|
+int rockpi_mcu_is_connected(void)
|
||
|
+{
|
||
|
+ return connected;
|
||
|
+}
|
||
|
+EXPORT_SYMBOL_GPL(rockpi_mcu_is_connected);
|
||
|
+
|
||
|
+static int rockpi_mcu_probe(struct i2c_client *client,
|
||
|
+ const struct i2c_device_id *id)
|
||
|
+{
|
||
|
+ struct rockpi_mcu_data *mcu_data;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ LOG_INFO("address = 0x%x\n", client->addr);
|
||
|
+
|
||
|
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
|
||
|
+ LOG_ERR("I2C check functionality failed\n");
|
||
|
+ return -ENODEV;
|
||
|
+ }
|
||
|
+
|
||
|
+ mcu_data = kzalloc(sizeof(struct rockpi_mcu_data), GFP_KERNEL);
|
||
|
+ if (mcu_data == NULL) {
|
||
|
+ LOG_ERR("no memory for device\n");
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ mcu_data->client = client;
|
||
|
+ i2c_set_clientdata(client, mcu_data);
|
||
|
+ g_mcu_data = mcu_data;
|
||
|
+
|
||
|
+ ret = init_cmd_check(mcu_data);
|
||
|
+ if (ret < 0) {
|
||
|
+ LOG_ERR("init_cmd_check failed, %d\n", ret);
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ connected = 1;
|
||
|
+
|
||
|
+ return 0;
|
||
|
+
|
||
|
+error:
|
||
|
+ kfree(mcu_data);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static int rockpi_mcu_remove(struct i2c_client *client)
|
||
|
+{
|
||
|
+ struct rockpi_mcu_data *mcu_data = i2c_get_clientdata(client);
|
||
|
+ connected = 0;
|
||
|
+ kfree(mcu_data);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static const struct i2c_device_id rockpi_mcu_id[] = {
|
||
|
+ {"rockpi_mcu", 0},
|
||
|
+ {},
|
||
|
+};
|
||
|
+
|
||
|
+static struct i2c_driver rockpi_mcu_driver = {
|
||
|
+ .driver = {
|
||
|
+ .name = "rockpi_mcu",
|
||
|
+ },
|
||
|
+ .probe = rockpi_mcu_probe,
|
||
|
+ .remove = rockpi_mcu_remove,
|
||
|
+ .id_table = rockpi_mcu_id,
|
||
|
+};
|
||
|
+module_i2c_driver(rockpi_mcu_driver);
|
||
|
+
|
||
|
+MODULE_DESCRIPTION("rockpi Board TouchScreen MCU driver");
|
||
|
+MODULE_LICENSE("GPL v2");
|
||
|
diff --git a/drivers/misc/rockpi_mcu.h b/drivers/misc/rockpi_mcu.h
|
||
|
new file mode 100644
|
||
|
index 000000000000..5be872fa3b5d
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/misc/rockpi_mcu.h
|
||
|
@@ -0,0 +1,14 @@
|
||
|
+#ifndef _ROCKPI_MCU_H_
|
||
|
+#define _ROCKPI_MCU_H_
|
||
|
+
|
||
|
+#define LOG_INFO(fmt,arg...) pr_info("rockpi-mcu: %s: "fmt, __func__, ##arg);
|
||
|
+#define LOG_ERR(fmt,arg...) pr_err("rockpi-mcu: %s: "fmt, __func__, ##arg);
|
||
|
+
|
||
|
+#define MAX_I2C_LEN 255
|
||
|
+
|
||
|
+struct rockpi_mcu_data {
|
||
|
+ struct device *dev;
|
||
|
+ struct i2c_client *client;
|
||
|
+};
|
||
|
+
|
||
|
+#endif
|
||
|
--
|
||
|
2.25.1
|
||
|
|