• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 */
18 
19 #include <asm/io.h>
20 #include <asm/irq.h>
21 #include <asm/uaccess.h>
22 
23 #include <linux/delay.h>
24 #include <linux/module.h>
25 #include <linux/kernel.h>
26 #include <linux/types.h>
27 #include <linux/fs.h>
28 #include <linux/errno.h>
29 #include <linux/miscdevice.h>
30 #include <linux/fcntl.h>
31 #include <linux/init.h>
32 #include <linux/proc_fs.h>
33 #include <linux/slab.h>
34 #include <linux/string.h>
35 #include <linux/i2c.h>
36 
37 #include "hi_drv_i2c.h"
38 #include "hi_osal.h"
39 #include "hi_module.h"
40 #include "hi_drv_gpio.h"
41 #include "fm11nt081d.h"
42 
43 #define NFC_EEPROM_BASE_ADDR (0x0010)
44 #define NFC_EEPROM_FINALY_ADDR (0x0384)
45 #define NFC_CMD_LEN (2)
46 #define NFC_WECHAT_NDEF_LEN (34)
47 #define READ_NFC_WECHAT_NDEF_LEN (50)
48 #define NFC_TOUTIAO_NDEF_LEN (47)
49 #define READ_NFC_TOUTIAO_NDEF_LEN (63)
50 #define NFC_EERROM_READ_BUFF_LEN_MAX (888)
51 #define NFC_CSN_GPIO_NUM (44) // GPIO5_4 5*8+4 = 44
52 
53 #define C081_NFC_ADDR (0xAE)
54 #define I2C_WR (0x00)
55 #define I2C_RD (0x01)
56 #define C081_NFC_WRITE_ADDR (C081_NFC_ADDR|I2C_WR)
57 #define C081_NFC_READ_ADDR (C081_NFC_ADDR|I2C_RD)
58 #define FM11_E2_USER_ADDR (0x0010)
59 #define FM11_E2_MAUNF_ADDR (0x03FF)
60 #define FM11_E2_BLOCK_SIZE (16)
61 #define DEFAULT_MD_LEN (128)
62 #define RIGHR_MOVE_8_BIT (8)
63 #define NFC_NDEF_MAX_LEN (888)
64 
65 #define LOW_LEVEL  0
66 #define HIGH_LEVEL 1
67 #define I2C1_SDA 0x03
68 #define I2C1_SCL 0x03
69 #define GPIO5_4 0xF8A2149C
70 #define CSN_DOWN 0x0
71 #define GPIO0_4 0xF8A21000
72 #define GPIO0_5 0xF8A21004
73 
74 static struct miscdevice nfc_miscdevice = { 0, };
75 hi_u8 wbuf[5] = {0x05, 0x78, 0xF7, 0x90, 0x02};
76 
77 i2c_ext_func *i2c_func = HI_NULL;
78 gpio_ext_func *g_gpio_func = HI_NULL;
79 
80 typedef enum {
81     I2C_CHANNEL_0 = 0,
82     I2C_CHANNEL_1 = 1
83 } i2c_channel_def;
84 
C081NfcI2cWrite(hi_u16 cmd,hi_u8 * data_buff,hi_u8 len)85 static hi_u32 C081NfcI2cWrite(hi_u16 cmd, hi_u8 *data_buff, hi_u8 len)
86 {
87     hi_u32 status = 0;
88     hi_u32 ret = 0;
89     hi_u32 id = I2C_CHANNEL_1;
90 
91     if (i2c_func == HI_NULL) {
92         NFC_ERR("HI_ID_ I2C handle get failed \r\n");
93         return HI_FAILURE;
94     }
95 
96     if (data_buff == HI_NULL) {
97         NFC_ERR("C081NfcI2cWrite data is null\r\n");
98     }
99 
100     status = i2c_func->pfn_i2c_write(id, C081_NFC_ADDR & 0xFE, cmd, NFC_CMD_LEN, data_buff, len);
101     if (status != 0) {
102         return HI_FAILURE;
103     }
104 
105     return 0;
106 }
107 
PullSetCsn(hi_s32 level)108 static hi_void PullSetCsn(hi_s32 level)
109 {
110     g_gpio_func->pfn_gpio_write_bit(NFC_CSN_GPIO_NUM, level);
111 }
112 
EepWritePage(hi_u8 * pBuffer,hi_u16 writeAddr,hi_u8 dataLen)113 static hi_void EepWritePage(hi_u8 *pBuffer, hi_u16 writeAddr, hi_u8 dataLen)
114 {
115     hi_u32 status;
116     if (pBuffer == NULL) {
117         NFC_ERR("eepWritePage buffer is null\r\n");
118     }
119     PullSetCsn(LOW_LEVEL);
120     status = C081NfcI2cWrite(writeAddr, pBuffer, dataLen);
121     msleep(10); // The delay time must be 10ms
122     PullSetCsn(HIGH_LEVEL);
123 }
124 
Fm11nt081dWriteEeprom(hi_u16 baseAddr,hi_u32 len,hi_u8 * wbuf)125 static hi_void Fm11nt081dWriteEeprom(hi_u16 baseAddr, hi_u32 len, hi_u8 *wbuf)
126 {
127     hi_u8 offset = 0;
128     hi_u8 *writeBuff = wbuf;
129     hi_u32 writeLen = len;
130     hi_u16 addr = baseAddr;
131 
132     if (writeBuff == NULL) {
133         NFC_ERR("write ndef is null\r\n");
134         return;
135     }
136 
137     if (addr < FM11_E2_USER_ADDR || addr >= FM11_E2_MAUNF_ADDR) {
138         offset = FM11_E2_BLOCK_SIZE - (addr % FM11_E2_BLOCK_SIZE);
139         NFC_ERR("offset = %d, writeLen = %d\r\n", offset, writeLen);
140         if (writeLen > offset) {
141             EepWritePage(writeBuff, addr, offset);
142             addr += offset;
143             writeBuff += offset;
144             writeLen -= offset;
145         } else {
146             EepWritePage(writeBuff, addr, writeLen);
147             writeLen = 0;
148         }
149     }
150     while (writeLen) {
151         if (writeLen >= FM11_E2_BLOCK_SIZE) {
152             EepWritePage(writeBuff, addr, FM11_E2_BLOCK_SIZE);
153             addr += FM11_E2_BLOCK_SIZE;
154             writeBuff += FM11_E2_BLOCK_SIZE;
155             writeLen -= FM11_E2_BLOCK_SIZE;
156         } else {
157             EepWritePage(writeBuff, addr, writeLen);
158             writeLen = 0;
159         }
160     }
161 }
162 
WriteRead(hi_u16 cmd,hi_u8 send_len,hi_u8 read_len)163 static hi_u32 WriteRead(hi_u16 cmd, hi_u8 send_len, hi_u8 read_len)
164 {
165     hi_u32 i = 0;
166     hi_u32 ret = 0;
167     hi_u32 status = 0;
168     hi_u32 id = I2C_CHANNEL_1;
169     hi_u8 recvData[888] = {0};
170 
171     if (i2c_func == HI_NULL) {
172         NFC_ERR("HI_ID_I2C handle get failed \r\n");
173         return HI_FAILURE;
174     }
175 
176     status = i2c_func->pfn_i2c_read(id, C081_NFC_ADDR | I2C_RD, cmd, send_len, recvData, read_len);
177     if (status != 0) {
178         return HI_FAILURE;
179     }
180 
181     NFC_INFO("<Fm11nt081d>: read ndef data\r\n");
182 
183     for (i = 0; i < read_len; i++) {
184         NFC_ERR("0x%x ", recvData[i]);
185     }
186 
187     NFC_INFO("\r\n");
188     return 0;
189 }
190 
Fm11nt081ReadEep(hi_u16 readAddr,hi_u16 len)191 static hi_u32 Fm11nt081ReadEep(hi_u16 readAddr, hi_u16 len)
192 {
193     hi_u32 status;
194 
195     status = WriteRead(readAddr, NFC_CMD_LEN, len);
196     if (status != 0) {
197         return HI_FAILURE;
198     }
199     return  0;
200 }
201 
202 static const struct i2c_device_id nfc_id[] = {
203     {"ft", 0},
204     {}
205 };
206 
207 MODULE_DEVICE_TABLE(i2c, nfc_id);
208 
Fm11nt081dSetReg(hi_u32 addr,hi_u32 value)209 static hi_s32 Fm11nt081dSetReg(hi_u32 addr, hi_u32 value)
210 {
211     void* pmem = ioremap(addr, DEFAULT_MD_LEN);
212 
213     if (pmem == HI_NULL) {
214         return HI_FAILURE;
215     }
216 
217     *(hi_u32*)pmem = value;
218     iounmap(pmem);
219     return 0;
220 }
221 
222 hi_u8 ndefFile[4][NFC_NDEF_MAX_LEN] = {
223     // wechat
224     {
225         0x03, 0x20,
226         0xd4, 0x0f, 0x0e, 0x61, 0x6e, 0x64, 0x72, 0x6f,
227         0x69, 0x64, 0x2e, 0x63, 0x6f, 0x6d, 0x3a, 0x70,
228         0x6b, 0x67, 0x63, 0x6f, 0x6d, 0x2e, 0x74, 0x65,
229         0x6e, 0x63, 0x65, 0x6e, 0x74, 0x2e, 0x6d, 0x6d,
230     },
231     // today headline
232     {
233         0x03, 0x2d,
234         0xd4, 0x0f, 0x1b, 0x61, 0x6e, 0x64, 0x72, 0x6f,
235         0x69, 0x64, 0x2e, 0x63, 0x6f, 0x6d, 0x3a, 0x70,
236         0x6b, 0x67, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x63,
237         0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
238         0x2e, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65,
239     },
240     // taobao
241     {
242         0x03, 0x23,
243         0xd4, 0x0f, 0x11, 0x61, 0x6e, 0x64, 0x72, 0x6f,
244         0x69, 0x64, 0x2e, 0x63, 0x6f, 0x6d, 0x3a, 0x70,
245         0x6b, 0x67, 0x63, 0x6f, 0x6d, 0x2e, 0x74, 0x61,
246         0x6f, 0x62, 0x61, 0x6f, 0x2e, 0x74, 0x61, 0x6f,
247         0x62, 0x61, 0x6f,
248     },
249     // smart life
250     {
251         0x03, 0x26,
252         0xd4, 0x0f, 0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f,
253         0x69, 0x64, 0x2e, 0x63, 0x6f, 0x6d, 0x3a, 0x70,
254         0x6b, 0x67, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x75,
255         0x61, 0x77, 0x65, 0x69, 0x2e, 0x73, 0x6d, 0x61,
256         0x72, 0x74, 0x68, 0x6f, 0x6d, 0x65,
257     }
258 };
259 
nfc_read_ep(hi_u8 * recvData)260 static hi_u32 nfc_read_ep(hi_u8 *recvData)
261 {
262     hi_u32 id = I2C_CHANNEL_1;
263     hi_u32 status = 0;
264     hi_s32 i;
265     hi_u32 ret = 0;
266 
267     if (i2c_func == HI_NULL) {
268         NFC_ERR("HI_ID_I2C handle get failed \r\n");
269         return HI_FAILURE;
270     }
271 
272     status = i2c_func->pfn_i2c_read(id, C081_NFC_ADDR | I2C_RD, NFC_EEPROM_BASE_ADDR, NFC_CMD_LEN, recvData,
273         NFC_TOUTIAO_NDEF_LEN);
274     if (status != 0) {
275         return HI_FAILURE;
276     }
277 
278     NFC_INFO("<Fm11nt081d>: read ndef data\r\n");
279 
280     for (i = 0; i < strlen(recvData); i++) {
281         NFC_ERR("0x%x ", recvData[i]);
282     }
283 
284     NFC_INFO("\r\n");
285     return 0;
286 }
287 
288 
nfc_write_ep(hi_u8 * buf)289 hi_void nfc_write_ep(hi_u8 *buf)
290 {
291     Fm11nt081dWriteEeprom(0x3B1, 1, &wbuf[1]);
292     Fm11nt081dWriteEeprom(0x3B5, 1, &wbuf[3]); // 3 for index
293 
294     /* write NFC EEPROM */
295     Fm11nt081dWriteEeprom(NFC_EEPROM_BASE_ADDR, NFC_TOUTIAO_NDEF_LEN, buf);
296     // csn pull down
297     PullSetCsn(LOW_LEVEL);
298 }
299 
nfc_open(struct inode * inode,struct file * filp)300 static hi_s32 nfc_open(struct inode *inode, struct file *filp)
301 {
302     NFC_INFO("Enter nfc_open");
303     return HI_SUCCESS;
304 }
305 
nfc_release(struct inode * inode,struct file * filp)306 static hi_s32 nfc_release(struct inode *inode, struct file *filp)
307 {
308     NFC_INFO("Enter nfc_release");
309     return HI_SUCCESS;
310 }
311 
312 #ifdef HAVE_UNLOCKED_IOCTL
nfc_ioctl(struct file * filp,hi_u32 cmd,unsigned long arg)313 static long nfc_ioctl(struct file *filp, hi_u32 cmd, unsigned long arg)
314 #else
315 static hi_s32 nfc_ioctl(struct inode *inode, struct file *filp, hi_u32 cmd, unsigned long arg)
316 #endif
317 {
318     hi_s32 ret = 0;
319     hi_char data_buf[120];
320 
321     if (_IOC_TYPE(cmd) != HI_ID_NFC)
322         return -EINVAL;
323 
324     if (_IOC_NR(cmd) > NFC_MAX_CMD)
325         return -EINVAL;
326 
327     switch (cmd) {
328         case NFC_READ:
329             nfc_read_ep(data_buf);
330             ret = copy_to_user((hi_char __user *)arg, data_buf, sizeof(data_buf));
331             if (ret) {
332                 ret = -EFAULT;
333             }
334             NFC_INFO("io ctl read_led: %d", strlen(data_buf));
335             break;
336         case NFC_WRITE:
337             ret = copy_from_user(data_buf, (hi_char __user *)arg, sizeof(data_buf));
338             if (ret) {
339                 ret = -EFAULT;
340             }
341             nfc_write_ep(data_buf);
342             break;
343         default:
344             ret = -EFAULT;
345     }
346     return ret;
347 }
348 
nfc_read(struct file * filp,hi_char __user * buf,size_t size,loff_t * offset)349 static ssize_t nfc_read(struct file *filp, hi_char __user *buf, size_t size, loff_t *offset)
350 {
351     hi_s32 ret;
352     hi_char recv_msg[20];
353     ret = copy_to_user(buf, recv_msg, size);
354     NFC_INFO("nfc_read: %s, %d", buf, size);
355 
356     if (ret < 0) {
357         return -EFAULT;
358     }
359     return ret;
360 }
361 
nfc_write(struct file * filp,const hi_char * buf,size_t size,loff_t * offset)362 static ssize_t nfc_write(struct file *filp, const hi_char *buf, size_t size, loff_t *offset)
363 {
364     hi_s32 ret;
365     hi_char send_msg[20];
366     ret = copy_from_user(send_msg, buf, size);
367     if (ret < 0) {
368         return -EFAULT;
369     }
370     return ret;
371 }
372 
373 struct file_operations nfc_fops = {
374     .owner = THIS_MODULE,
375     .open = nfc_open,
376     .release = nfc_release,
377 #ifdef HAVE_UNLOCKED_IOCTL
378     .unlocked_ioctl = nfc_ioctl,
379 #else
380     .ioctl = nfc_ioctl,
381 #endif
382     .read = nfc_read,
383     .write = nfc_write,
384 };
385 
fm11nt081d_init(hi_void)386 static hi_s32 __init fm11nt081d_init(hi_void)
387 {
388     hi_s32 ret = 0;
389     NFC_INFO("-----------------fm11nt081d_init-----------\n");
390 
391     // fm11nt081d NFC GPIO configure
392     Fm11nt081dSetReg(GPIO5_4, CSN_DOWN);
393     Fm11nt081dSetReg(GPIO0_4, I2C1_SDA);
394     Fm11nt081dSetReg(GPIO5_4, I2C1_SCL);
395 
396     gpio_drv_get_gpio_ext_func(&g_gpio_func);
397     if (g_gpio_func == HI_NULL) {
398         NFC_ERR("get gpio export function failed!\n");
399         return -EFAULT;
400     }
401 
402     /* set GPIO to be output and low level */
403     g_gpio_func->pfn_gpio_dir_set_bit(NFC_CSN_GPIO_NUM, LOW_LEVEL);
404     g_gpio_func->pfn_gpio_write_bit(NFC_CSN_GPIO_NUM, LOW_LEVEL);
405 
406     /* i2c_1 init */
407     ret = hi_drv_i2c_init();
408     if (ret) {
409         NFC_ERR("I2C init failed : %d\n", ret);
410         return -EFAULT;
411     }
412     i2c_drv_get_i2c_ext_func(&i2c_func);
413     if (i2c_func == HI_NULL) {
414         NFC_ERR("HI_ID_I2C handle get failed \r\n");
415         return -EFAULT;
416     }
417 
418     nfc_miscdevice.minor = MISC_DYNAMIC_MINOR;
419     nfc_miscdevice.name = HINFC_DEVICE_NAME;
420     nfc_miscdevice.fops = &nfc_fops;
421 
422     ret = misc_register(&nfc_miscdevice);
423     if (ret != 0) {
424         NFC_ERR("[%s, line: %d]Error: can't register\n", "NFC", __LINE__);
425         return -EFAULT;
426     }
427     return 0;
428 }
429 
fm11nt081d_exit(hi_void)430 static hi_void __exit fm11nt081d_exit(hi_void)
431 {
432     NFC_INFO("-----------------fm11nt081d_exit-----------\n");
433     hi_drv_i2c_de_init();
434 
435     misc_deregister(&nfc_miscdevice);
436 }
437 module_init(fm11nt081d_init);
438 module_exit(fm11nt081d_exit);
439 
440 MODULE_LICENSE("GPL");
441 MODULE_AUTHOR("hisilicon");
442