From 170c1c0fa90ad9f762d1877f8a57efce706fc95a Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 06 Nov 2023 07:26:34 +0000
Subject: [PATCH] add nkmcu

---
 kernel/drivers/misc/nkmcu/nk_mcu.c |  161 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 kernel/drivers/misc/nkmcu/Makefile |    1 
 2 files changed, 162 insertions(+), 0 deletions(-)

diff --git a/kernel/drivers/misc/nkmcu/Makefile b/kernel/drivers/misc/nkmcu/Makefile
new file mode 100644
index 0000000..aca06fb
--- /dev/null
+++ b/kernel/drivers/misc/nkmcu/Makefile
@@ -0,0 +1 @@
+obj-y += nk_mcu.o 
diff --git a/kernel/drivers/misc/nkmcu/nk_mcu.c b/kernel/drivers/misc/nkmcu/nk_mcu.c
new file mode 100755
index 0000000..b0702be
--- /dev/null
+++ b/kernel/drivers/misc/nkmcu/nk_mcu.c
@@ -0,0 +1,161 @@
+#include <linux/module.h>
+#include <linux/clk-provider.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+
+static struct i2c_client s_m_client;
+static struct i2c_client* m_client;
+ 
+//写16位寄存器
+static inline int nkmcu_reg_write(struct i2c_client *client,int index,unsigned short reg, unsigned char val)
+{
+	unsigned char u8_buf[3] = { 0 };
+	unsigned int buf_len = 3;
+	int retry, timeout = 5;
+	int ret;
+
+	ret = 0;
+	u8_buf[0] = (reg >> 8) & 0xFF;//寄存器地址高位
+	u8_buf[1] = reg & 0xFF;  //寄存器地址低位
+	u8_buf[2] = val; //要发送的数据
+
+	//pdata->client->addr = ADDR + index;
+	for (retry = 0; retry < timeout; retry++) 
+    {
+		if (i2c_master_send(client, u8_buf, buf_len) < 0) 
+        {
+			pr_err("%s:write reg error: reg=0x%x, val=0x%x, retry = %d.\n", __func__, reg, val, retry);
+			ret = -1;
+			msleep(5);
+			continue;
+		}
+		else
+        {      
+			pr_err("%s:write reg ok: reg=0x%x, val=0x%x, retry = %d.\n", __func__, reg, val, retry);
+			ret = 0;
+            break;
+        }
+	}
+	return ret;
+}
+
+//16位读
+static inline int nkmcu_reg_read(struct i2c_client *client, int index, unsigned short reg)
+{
+	unsigned char u8_buf[2] = { 0 };
+	unsigned int buf_len = 2;
+	int retry, timeout = 5;
+	unsigned char u8_val = 0;
+
+	u8_buf[0] = (reg >> 8) & 0xFF;//寄存器地址高位
+	u8_buf[1] = reg & 0xFF;//寄存器地址低位
+
+	//pdata->client->addr = ADDR + index;
+	for (retry = 0; retry < timeout; retry++) 
+    {
+		if (i2c_master_send(client, u8_buf, buf_len) < 0) 
+        {
+			pr_err("%s:read reg error on send: reg=0x%x, retry = %d.\n", __func__, reg, retry);
+			msleep(5);
+			continue;
+		}
+		if (i2c_master_recv(client, &u8_val, 1) != 1) {
+			pr_err("%s:read reg error on recv: reg=0x%x, retry = %d.\n", __func__, reg, retry);
+			msleep(5);
+			continue;
+		}
+		break;
+	}
+
+	if (retry >= timeout) {
+		pr_err("%s:read reg error: reg=0x%x.\n", __func__, reg);
+		return -1;
+	}
+
+	return u8_val;
+}
+
+void nkmcu_device_shutdown(void)
+{
+	int ret;
+	
+	pr_err("nkmcu_device_shutdown.. \n");
+	
+	//powenoff
+	if (m_client != NULL)
+	{	
+		ret = nkmcu_reg_write(m_client, 0x00, 0x06, 0x01);
+		if (ret < 0)	
+			pr_err("nkmcu_device_shutdown..failed \n");	
+		else
+			pr_err("nkmcu_device_shutdown.. ok \n");
+	}	
+	
+}
+EXPORT_SYMBOL(nkmcu_device_shutdown);
+	
+static int  nk_mcu_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	struct device_node *np = client->dev.of_node;
+	int ret;
+	
+	printk("%s: probe\n", __FUNCTION__);
+	
+	/* check state of calendar information */
+	//device id
+	//i2c_smbus_read_word_data
+	msleep(100);
+	//ret = i2c_smbus_read_byte_data(client, 0x00);
+	ret = nkmcu_reg_read(client, 0x00, 0x00);
+	printk("device id:%x \n", ret);
+	if (ret != 0xaa)
+		goto error;
+	
+	//powenon
+	msleep(100);
+	//ret = i2c_smbus_write_word_data(client, 0x07, 0x01);
+	ret = nkmcu_reg_write(client, 0x00, 0x07, 0x01);
+	printk("poweron command:%x \n", ret);
+	if (ret < 0)
+		goto error;
+	
+	//m_client = client;
+	memcpy(&s_m_client, client, sizeof(struct i2c_client));
+	m_client = &s_m_client;
+	return 0;
+	
+error:
+	return -1;			
+}
+
+static const struct i2c_device_id nk_mcu_id[] = {
+        { "nk_mcu", 0 },
+        { }
+};
+
+static struct i2c_driver nk_mcu_driver = {
+        .driver         = {
+                .name   = "nk_mcu",
+                .owner  = THIS_MODULE,
+        },
+        .probe          = nk_mcu_probe,
+        .id_table       = nk_mcu_id,
+};
+
+static int __init nk_mcu_init(void)
+{
+        return i2c_add_driver(&nk_mcu_driver);
+}
+
+static void __exit nk_mcu_exit(void)
+{
+        i2c_del_driver(&nk_mcu_driver);
+}
+
+
+MODULE_AUTHOR("ben@hotmail.com");
+MODULE_DESCRIPTION("nodka mcu driver");
+MODULE_LICENSE("GPL");
+
+late_initcall(nk_mcu_init);
+module_exit(nk_mcu_exit);

--
Gitblit v1.6.2