usb: gadget: g_ffs: Allow to set bmAttributes of configuration
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / misc / sprd_tks.c
1 /*
2  * sprd trusted key storage driver
3  *
4  * Copyright (C)
5  *
6  * This driver is for ali trusted key storage
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  */
23
24 #include <asm/io.h>
25 #include <linux/delay.h>
26 #include <linux/dma-mapping.h>
27 #include <linux/errno.h>
28 #include <linux/fs.h>
29 #include <linux/init.h>
30 #include <linux/ion.h>
31 #include <linux/ioport.h>
32 #include <linux/jiffies.h>
33 #include <linux/miscdevice.h>
34 #include <linux/module.h>
35 #include <linux/moduleparam.h>
36 #include <linux/platform_device.h>
37 #include <linux/string.h>
38 #include <linux/timer.h>
39 #include <linux/types.h>
40 #include <linux/uaccess.h>
41 #include <soc/sprd/sci.h>
42 #include <uapi/linux/sprd_tks.h>
43
44 #ifdef CONFIG_OF
45 #include <linux/of_address.h>
46 #include <linux/of_device.h>
47 #endif
48
49 #define TSP_TKS_SHM_REQ_ADDR    0x2005
50 #define TSP_TKS                 0x2010
51
52 /*from arm trusted firmware */
53 #define TSP_STD_FID(fid)        ((fid) | 0x72000000 | (0 << 31))
54 #define TSP_FAST_FID(fid)       ((fid) | 0x72000000 | (1 << 31))
55
56 /*c6e7c860-9299-455c-b5eb-68686d2c739c*/
57 #define SEC_SHAREMEM_MAX_SIZE   4096
58
59 #define TKS_KEY_LEN(p)  (sizeof(enum key_type)+sizeof(int)+(p)->keylen)
60 #define PACK_DATA_LEN(p)        (sizeof(int)+(p)->len)
61
62 #define KEYLEN_OFF      (offsetof(struct tks_key_cal, keylen))
63 #define DATA_OFF        (offsetof(struct tks_key_cal, keydata))
64 /*#define GEN_KEYPARI_LEN(p) (TKS_KEY_LEN(&((p)->rsaprv)) + \
65                 TKS_KEY_LEN((&(p)->out_rsapub)))
66 #define DEC_SIMPLE_LEN(p) (TKS_KEY_LEN(&((p)->encryptkey)) + \
67                 PACK_DATA_LEN(&((p)->data)))*/
68
69 #define SHM_SIZE        (4096ul)
70 #define ERRNO_BASE      (1000)
71 #define ARM7_CFG_BUS_OFFSET     (0x0124)
72 #define SLEEP_STATUS_OFFSET     (0x00d4)
73 #define SLEEP_STATUS_MASK       (0xf << 20)
74 #define SLEEP_STATUS_VAL        (0x6 << 20)
75
76 static unsigned long *shm_vaddr;
77 static dma_addr_t phy_addr;
78 static ulong arm7_cfg_bus;
79 static ulong sleep_status;
80 static ulong reg_val = 0;
81
82 __packed struct shm_mem_view {
83         u32 cmd;
84         u8  cmd_data[SEC_SHAREMEM_MAX_SIZE-sizeof(u32)];
85 };
86
87
88 static inline void readbyte(unsigned long addr, void *buffer, int count)
89 {
90         u8 *buf = buffer;
91         while (count--)
92                 *buf++ = __raw_readb((void __iomem *)addr++);
93 }
94
95 static inline void writebyte(unsigned long addr, const void *buffer, int count)
96 {
97         const u8 *buf = buffer;
98         while (count--)
99                 __raw_writeb(*buf++, (void __iomem *)addr++);
100 }
101
102 static noinline int __invoke_tks_fn_smc(u64 function_id, u64 arg0, u64 arg1,
103                                                                 u64 arg2)
104 {
105         asm volatile(
106                         __asmeq("%0", "x0")
107                         __asmeq("%1", "x1")
108                         __asmeq("%2", "x2")
109                         __asmeq("%3", "x3")
110                         "smc    #0\n"
111                         : "+r" (function_id)
112                         : "r" (arg0), "r" (arg1), "r" (arg2));
113
114         return function_id;
115 }
116
117
118 static int (*invoke_tks_fn)(u64, u64, u64, u64);
119
120 static int wake_secure_ap(void)
121 {
122         ulong state = 0;
123         int loop = 1000;
124
125         reg_val = sci_glb_read(arm7_cfg_bus, 0x1);
126         sci_glb_clr(arm7_cfg_bus, BIT(0));
127         while (loop--) {
128                 state = sci_glb_read(sleep_status, SLEEP_STATUS_MASK);
129                 if (state == SLEEP_STATUS_VAL)
130                         break;
131                 cpu_relax();
132                 msleep(1);
133         }
134         pr_info("%s secure ap awake!", __func__);
135
136         return 0;
137 }
138
139 static int resume_bus_status(void)
140 {
141         return sci_glb_write(arm7_cfg_bus, reg_val, 0x1);
142 }
143
144 static int invoke_tks_fn_awake(u64 func_id, u64 arg0, u64 arg1, u64 arg2)
145 {
146         wake_secure_ap();
147         invoke_tks_fn(func_id, arg0, arg1, arg2);
148         resume_bus_status();
149
150         return 0;
151 }
152
153 /* filesystem operations */
154 static int sprd_tks_open(struct inode *inode, struct file *file)
155 {
156
157         return nonseekable_open(inode, file);
158 }
159
160 static int sprd_tks_release(struct inode *inode, struct file *file)
161 {
162         return 0;
163 }
164
165 static long sprd_tks_ioctl(struct file *file, unsigned int cmd,
166                 unsigned long arg)
167 {
168         struct shm_mem_view *buf;
169         unsigned char *databuf;
170         unsigned int cnt;
171         unsigned int keylen;
172         unsigned char * __user userdata;
173         unsigned char op;
174         unsigned char *bakloc1;
175         int ret = -ENOTTY;
176         void __user *argp = (void *)arg;
177
178         buf = (struct shm_mem_view *)shm_vaddr;
179
180         switch (cmd) {
181         case SEC_IOC_GEN_KEYPAIR:
182                 buf->cmd = _IOC_NR(SEC_IOC_GEN_KEYPAIR);
183                 invoke_tks_fn_awake((TSP_FAST_FID(TSP_TKS)),
184                                 SEC_IOC_GEN_KEYPAIR, 0, 0);
185                 invoke_tks_fn_awake((TSP_FAST_FID(TSP_TKS)),
186                                 SEC_IOC_GEN_KEYPAIR, 0, 0);
187                 if (buf->cmd)
188                         return -(ERRNO_BASE + buf->cmd);
189                 databuf = buf->cmd_data;
190                 readbyte((unsigned long)(databuf + KEYLEN_OFF),
191                                 &keylen, sizeof(keylen));       /*get rsaprv*/
192                 pr_info("%s:%d:databuf=0x%p,argp=0x%p, len1= 0x%x \n",
193                                 __func__, __LINE__, databuf, argp, keylen);
194                 if (unlikely(keylen >= SHM_SIZE)) {
195                         pr_err("%s:%d:tks keylen=0x%x out of range.\n",
196                                         __func__, __LINE__, keylen);
197                         return -EIO;
198                 }
199                 if (!access_ok(VERIFY_WRITE, argp, DATA_OFF + keylen))
200                         return -EFAULT;
201                 /*can not use copy_to_user ,bc .
202                   the 8 alignment fault.do it in byte copy.*/
203                 for (cnt = 0; cnt < (keylen + DATA_OFF); cnt++) {
204                         ret = put_user(*((char *)databuf + cnt),
205                                         (char *)argp + cnt);
206                         if (ret)
207                                 return -EIO;
208                 }
209                 /*get out_rsapub*/
210                 databuf +=  (DATA_OFF + keylen);
211                 argp += offsetof(struct request_gen_keypair, out_rsapub);
212                 /*bc. this is maybe not a alignment addr, so use byteget
213                   method to get keylen.*/
214                 readbyte((unsigned long)(databuf + KEYLEN_OFF),
215                                 &keylen, sizeof(keylen));
216                 pr_info("%s:%d:databuf=0x%p,argp=0x%p, len1= 0x%x \n",
217                                 __func__, __LINE__, databuf, argp, keylen);
218                 if (unlikely(keylen >= SHM_SIZE)) {
219                         pr_err("%s:%d:tks keylen=0x%x out of range.\n",
220                                         __func__, __LINE__, keylen);
221                         return -EIO;
222                 }
223                 if (!access_ok(VERIFY_WRITE, argp, DATA_OFF + keylen))
224                         return -EFAULT;
225                 for (cnt = 0; cnt < (keylen + DATA_OFF); cnt++) {
226                         ret = put_user(*((char *)databuf + cnt),
227                                         (char *)argp + cnt);
228                         if (ret)
229                                 return -EIO;
230                 }
231                 break;
232         case SEC_IOC_DEC_SIMPLE:
233                 buf->cmd = _IOC_NR(SEC_IOC_DEC_SIMPLE);
234                 databuf = buf->cmd_data;
235                 /*user view*/
236                 ret = get_user(keylen,
237                 &(((struct request_dec_simple *)argp)->encryptkey.keylen));
238                 if (ret)
239                         return -EIO;
240                 if (unlikely(keylen >= SHM_SIZE)) {
241                         pr_err("%s:%d:tks keylen=0x%x out of range.\n",
242                                         __func__, __LINE__, keylen);
243                         return -EIO;
244                 }
245                 for (cnt = 0; cnt < (keylen + DATA_OFF); cnt++) {
246                         ret = get_user(databuf[cnt], (char *)argp + cnt);
247                         if (ret)
248                                 return -EIO;
249                 }
250                 /*updata databuf pto pack_data*/
251                 databuf += cnt;
252                 /*get keylen  form user space.*/
253                 ret = get_user(keylen,
254                 &(((struct request_dec_simple *)argp)->data.len));
255                 if (ret)
256                         return -EIO;
257                 if (unlikely(keylen >= SHM_SIZE)) {
258                         pr_err("%s %d:tks keylen=0x%x out of range.\n",
259                                         __func__, __LINE__, keylen);
260                         return -EIO;
261                 }
262                 writebyte((unsigned long)databuf, &keylen, sizeof(keylen));
263                 databuf += sizeof(keylen);
264                 /*get data pto usermemmory form userspace.*/
265                 ret = get_user(userdata,
266                 &(((struct request_dec_simple *)argp)->data.data));
267                 if (ret)
268                         return -EIO;
269                 for (cnt = 0; cnt < keylen; cnt++) {
270                         ret = get_user(databuf[cnt], userdata + cnt);
271                         if (ret)
272                                 return -EIO;
273                 }
274                 invoke_tks_fn_awake((TSP_FAST_FID(TSP_TKS)),
275                                         SEC_IOC_DEC_SIMPLE, 0, 0);
276                 if (buf->cmd)
277                         return -(ERRNO_BASE + buf->cmd);
278                 /*rollback tothe shm packdata locate.*/
279                 databuf -= sizeof(keylen);
280                 userdata = (unsigned char * __user)
281                 (&(((struct request_dec_simple *)argp)->data.len));
282                 readbyte((unsigned long)databuf, &keylen, sizeof(keylen));
283                 if (unlikely(keylen >= SHM_SIZE)) {
284                         pr_err("%s:%d:tks keylen=0x%x out of range.\n",
285                                         __func__, __LINE__, keylen);
286                         return -EIO;
287                 }
288                 for (cnt = 0; cnt < sizeof(keylen); cnt++) {
289                         ret = put_user(databuf[cnt], userdata + cnt);
290                         if (ret)
291                                 return -EIO;
292                 }
293                 databuf += sizeof(keylen);
294                 /*get packdata.data ,the user space memmory heap*/
295                 /*userdata = ((struct request_dec_simple*)argp)->data.data*/
296                 ret = get_user(userdata,
297                 &(((struct request_dec_simple *)argp)->data.data));
298                 if (ret)
299                         return -EIO;
300                 for (cnt = 0; cnt < keylen; cnt++) {
301                         ret = put_user(databuf[cnt], userdata + cnt);
302                         if (ret)
303                                 return -EIO;
304                 }
305                 break;
306         case SEC_IOC_DEC_PACK_USERPASS:
307                 buf->cmd = _IOC_NR(SEC_IOC_DEC_PACK_USERPASS);
308                 databuf = buf->cmd_data;
309                 /*write shm the endryptkey from user space.
310                 get keylen from user*/
311                 ret = get_user(keylen,
312                 &(
313                 ((struct request_dec_pack_userpass *)argp)->encryptkey.keylen
314                 ));
315                 if (ret)
316                         return -EIO;
317                 if (unlikely(keylen >= SHM_SIZE)) {
318                         pr_err("%s:%d:tks keylen=0x%x out of range.\n",
319                                         __func__, __LINE__, keylen);
320                         return -EIO;
321                 }
322                 for (cnt = 0; cnt < (keylen + DATA_OFF); cnt++) {
323                         ret = get_user(databuf[cnt], (char *)argp + cnt);
324                         if (ret)
325                                 return -EIO;
326                 }
327                 /*write shm the userpasskey from user space.*/
328                 databuf +=  cnt;
329                 /*updata userdata pos.*/
330                 userdata = (unsigned char * __user)
331                 (&(((struct request_dec_pack_userpass *)argp)->userpass));
332                 /*get keylen from user*/
333                 ret = get_user(keylen,
334                 &(((struct request_dec_pack_userpass *)argp)->userpass.keylen));
335                 if (ret)
336                         return -EIO;
337                 if (unlikely(keylen >= SHM_SIZE)) {
338                         pr_err("%s %d:tks keylen=0x%x out of range.\n",
339                                         __func__, __LINE__, keylen);
340                         return -EIO;
341                 }
342                 for (cnt = 0; cnt < (keylen + DATA_OFF); cnt++) {
343                         ret = get_user(databuf[cnt], (char *)userdata + cnt);
344                         if (ret)
345                                 return -EIO;
346                 }
347                 invoke_tks_fn_awake((TSP_FAST_FID(TSP_TKS)),
348                                 SEC_IOC_DEC_PACK_USERPASS, 0, 0);
349                 if (buf->cmd)
350                         return -(ERRNO_BASE + buf->cmd);
351                 /*databuf is remained; userdata is remianed*/
352                 readbyte((unsigned long)(databuf + KEYLEN_OFF),
353                                                 &keylen, sizeof(keylen));
354                 if (unlikely(keylen >= SHM_SIZE)) {
355                         pr_err("%s:%d:tks keylen=0x%x out of range.\n",
356                                         __func__, __LINE__, keylen);
357                         return -EIO;
358                 }
359                 for (cnt = 0; cnt < (keylen + DATA_OFF); cnt++) {
360                         ret = put_user(*((char *)databuf + cnt),
361                                                 (char *)userdata + cnt);
362                         if (ret)
363                                 return -EIO;
364                 }
365                 break;
366         case SEC_IOC_CRYPTO:
367                 buf->cmd = _IOC_NR(SEC_IOC_CRYPTO);
368                 databuf = buf->cmd_data;
369                 ret = get_user(op, (char *)argp);       /*write op*/
370                 writebyte((unsigned long)databuf, &op, sizeof(op));
371                 /*write shm the endryptkey from user space.*/
372                 /*keylen = ((struct request_crypto*)argp)->encryptkey.keylen;*/
373                 ret = get_user(keylen,
374                 &(((struct request_crypto *)argp)->encryptkey.keylen));
375                 if (ret)
376                         return -EIO;
377                 if (unlikely(keylen >= SHM_SIZE)) {
378                         pr_err("%s:%d:tks keylen=0x%x out of range.\n",
379                                         __func__, __LINE__, keylen);
380                         return -EIO;
381                 }
382                 /*updata databuf,userdata.*/
383                 databuf += sizeof(op);
384                 userdata = (char *)argp
385                                 + offsetof(struct request_crypto, encryptkey);
386                 /*write encryptkey to shm.*/
387                 for (cnt = 0; cnt < (keylen + DATA_OFF); cnt++) {
388                         ret = get_user(databuf[cnt], (char *)userdata + cnt);
389                         if (ret)
390                                 return -EIO;
391                 }
392                 /*write shm the userpasskey from user space.*/
393                 databuf +=  cnt; /*updata the databuf pos.*/
394                 /*updata userdata pos.*/
395                 userdata = (char *)argp +
396                                 offsetof(struct request_crypto, userpass);
397                 ret = get_user(keylen,
398                 &(((struct request_crypto *)argp)->userpass.keylen));
399                 if (ret)
400                         return -EIO;
401                 if (unlikely(keylen >= SHM_SIZE)) {
402                         pr_err("%s:%d:tks keylen=0x%x out of range.\n",
403                                         __func__, __LINE__, keylen);
404                         return -EIO;
405                 }
406                 for (cnt = 0; cnt < (keylen + DATA_OFF); cnt++) {
407                         ret = get_user(databuf[cnt], (char *)userdata + cnt);
408                         if (ret)
409                                 return -EIO;
410                 }
411                 /*packdata write to shm*/
412                 databuf +=  cnt; /*updata the databuf pos.*/
413                 bakloc1 = databuf;/*backup the pointer locate of the packdata*/
414                 userdata = (char *)argp +
415                                 offsetof(struct request_crypto, data);
416                 ret = get_user(keylen,
417                 &(((struct request_crypto *)argp)->data.len));
418                 if (ret)
419                         return -EIO;
420                 if (unlikely(keylen >= SHM_SIZE)) {
421                         pr_err("%s:%d:tks keylen=0x%x out of range.\n",
422                                         __func__, __LINE__, keylen);
423                         return -EIO;
424                 }
425                 writebyte((unsigned long)databuf, &keylen, sizeof(keylen));
426                 databuf += sizeof(keylen);
427                 ret = get_user(userdata,
428                 &(((struct request_crypto *)argp)->data.data));
429                 if (ret)
430                         return -EIO;
431                 for (cnt = 0; cnt < keylen; cnt++) {
432                         ret = get_user(databuf[cnt], (char *)userdata + cnt);
433                         if (ret)
434                                 return -EIO;
435                 }
436                 /*write signature*/
437                 if (op == 1) { /*0=SIGN,1=VERIFY,2=ENC,3=DEC; [in]*/
438                         /*write the signature to shm*/
439                         databuf +=  cnt; /*updata the databuf pos.*/
440                         /*updata userdata pos.*/
441                         userdata = (char *)argp +
442                                 offsetof(struct request_crypto, signature);
443                         ret = get_user(keylen,
444                         &(((struct request_crypto *)argp)->signature.len));
445                         if (ret)
446                                 return -EIO;
447                         if (unlikely(keylen >= SHM_SIZE)) {
448                                 pr_err("%s:%d:tks keylen=0x%x out of range.\n",
449                                                 __func__, __LINE__, keylen);
450                                 return -EIO;
451                         }
452                         writebyte((unsigned long)databuf, &keylen,
453                                                         sizeof(keylen));
454                         /*updata databuf*/
455                         databuf += sizeof(keylen);
456                         ret = get_user(userdata,
457                         &(((struct request_crypto *)argp)->signature.data));
458                         if (ret)
459                                 return -EIO;
460                         for (cnt = 0; cnt < keylen; cnt++) {
461                                 ret = get_user(databuf[cnt],
462                                                 (char *)userdata + cnt);
463                                 if (ret)
464                                         return -EIO;
465                         }
466                 }
467                 invoke_tks_fn_awake((TSP_FAST_FID(TSP_TKS)),
468                                                         SEC_IOC_CRYPTO, 0, 0);
469                 if (buf->cmd)
470                         return -(ERRNO_BASE + buf->cmd);
471                 /* copy pack_data form shm to user space.*/
472                 databuf = bakloc1; /*the shm packdata locate.*/
473                 /*updata userdata pos.*/
474                 userdata = (char *)argp + offsetof(struct request_crypto, data);
475                 readbyte((unsigned long)databuf, &keylen, sizeof(keylen));
476                 if (unlikely(keylen >= SHM_SIZE)) {
477                         pr_err("%s:%d:tks keylen=0x%x out of range.\n",
478                                         __func__, __LINE__, keylen);
479                         return -EIO;
480                 }
481                 for (cnt = 0; cnt < sizeof(keylen); cnt++) {
482                         ret = put_user(databuf[cnt], userdata + cnt);
483                         if (ret)
484                                 return -EIO;
485                 }
486                 databuf += sizeof(keylen);
487                 ret = get_user(userdata,
488                         &(((struct request_crypto *)argp)->data.data));
489                 if (ret)
490                         return -EIO;
491                 for (cnt = 0; cnt < keylen; cnt++) {
492                         ret = put_user(databuf[cnt], userdata + cnt);
493                         if (ret)
494                                 return -EIO;
495                 }
496                 break;
497         case SEC_IOC_GEN_DHKEY:
498                 buf->cmd = _IOC_NR(SEC_IOC_GEN_DHKEY);
499                 databuf = buf->cmd_data;
500                 /*write user space encryptkey to shm*/
501                 ret = get_user(keylen,
502                 &(((struct request_gen_dhkey *)argp)->encryptkey.keylen));
503                 if (ret)
504                         return -EIO;
505                 if (unlikely(keylen >= SHM_SIZE)) {
506                         pr_err("%s:%d:tks keylen=0x%x out of range.\n",
507                                         __func__, __LINE__, keylen);
508                         return -EIO;
509                 }
510                 for (cnt = 0; cnt < (keylen + DATA_OFF); cnt++) {
511                         ret = get_user(databuf[cnt], (char *)argp + cnt);
512                         if (ret)
513                                 return -EIO;
514                 }
515                 /*write param*/
516                 databuf += cnt;
517                 userdata = (char *)argp +
518                                 offsetof(struct request_gen_dhkey, param) +
519                                 offsetof(struct dh_param, a);/*big_int a*/
520                 ret = get_user(keylen,
521                         &(((struct request_gen_dhkey *)argp)->param.a.len));
522                 if (ret)
523                         return -EIO;
524                 if (unlikely(keylen >= SHM_SIZE)) {
525                         pr_err("%s:%d:tks keylen=0x%x out of range.\n",
526                                         __func__, __LINE__, keylen);
527                         return -EIO;
528                 }
529                 /*write bit_int a keylen*/
530                 writebyte((unsigned long)databuf, &keylen, sizeof(keylen));
531                 databuf += sizeof(keylen);
532                 ret = get_user(userdata,
533                         &(((struct request_gen_dhkey *)argp)->param.a.data));
534                 if (ret)
535                         return -EIO;
536                 for (cnt = 0; cnt < keylen; cnt++) {
537                         ret = get_user(databuf[cnt], (char *)userdata + cnt);
538                         if (ret)
539                                 return -EIO;
540                 }
541                 /*write big_int g*/
542                 databuf += cnt;
543                 userdata = (char *)argp +
544                                 offsetof(struct request_gen_dhkey, param) +
545                                 offsetof(struct dh_param, g); /*big_int g*/
546                 ret = get_user(keylen,
547                         &(((struct request_gen_dhkey *)argp)->param.g.len));
548                 if (ret)
549                         return -EIO;
550                 if (unlikely(keylen >= SHM_SIZE)) {
551                         pr_err("%s:%d:tks keylen=0x%x out of range.\n",
552                                         __func__, __LINE__, keylen);
553                         return -EIO;
554                 }
555                 /*write bit_int a keylen*/
556                 writebyte((unsigned long)databuf, &keylen, sizeof(keylen));
557                 databuf += sizeof(keylen);
558                 ret = get_user(userdata,
559                         &(((struct request_gen_dhkey *)argp)->param.g.data));
560                 if (ret)
561                         return -EIO;
562                 for (cnt = 0; cnt < keylen; cnt++) {
563                         ret = get_user(databuf[cnt], (char *)userdata + cnt);
564                         if (ret)
565                                 return -EIO;
566                 }
567                 /*write big_int p*/
568                 databuf += cnt;
569                 userdata = (char *)argp +
570                                 offsetof(struct request_gen_dhkey, param) +
571                                 offsetof(struct dh_param, p); /*big_int g*/
572                 ret = get_user(keylen,
573                         &(((struct request_gen_dhkey *)argp)->param.p.len));
574                 if (ret)
575                         return -EIO;
576                 if (unlikely(keylen >= SHM_SIZE)) {
577                         pr_err("%s:%d:tks keylen=0x%x out of range.\n",
578                                         __func__, __LINE__, keylen);
579                         return -EIO;
580                 }
581                 /*write bit_int a keylen*/
582                 writebyte((unsigned long)databuf, &keylen, sizeof(keylen));
583                 databuf += sizeof(keylen);
584                 ret = get_user(userdata,
585                         &(((struct request_gen_dhkey *)argp)->param.p.data));
586                 if (ret)
587                         return -EIO;
588                 for (cnt = 0; cnt < keylen; cnt++) {
589                         ret = get_user(databuf[cnt], (char *)userdata + cnt);
590                         if (ret)
591                                 return -EIO;
592                 }
593
594                 invoke_tks_fn_awake((TSP_FAST_FID(TSP_TKS)),
595                                                 SEC_IOC_GEN_DHKEY, 0, 0);
596                 if (buf->cmd)
597                         return -(ERRNO_BASE + buf->cmd);
598                 databuf += cnt;
599                 userdata = (char *)argp +
600                                 offsetof(struct request_gen_dhkey, b);
601                 readbyte((unsigned long)databuf, &keylen, sizeof(keylen));
602                 if (unlikely(keylen >= SHM_SIZE)) {
603                         pr_err("%s:%d:tks keylen=0x%x out of range.\n",
604                                         __func__, __LINE__, keylen);
605                         return -EIO;
606                 }
607                 for (cnt = 0; cnt < sizeof(keylen); cnt++) {
608                         ret = put_user(databuf[cnt], userdata + cnt);
609                         if (ret)
610                                 return -EIO;
611                 }
612                 databuf += sizeof(keylen);
613                 ret = get_user(userdata,
614                                 &(((struct request_gen_dhkey *)argp)->b.data));
615                 if (ret)
616                         return -EIO;
617                 for (cnt = 0; cnt < keylen; cnt++) {
618                         ret = put_user(databuf[cnt], userdata + cnt);
619                         if (ret)
620                                 return -EIO;
621                 }
622                 /*write big_int k*/
623                 databuf += cnt;
624                 userdata = (char *)argp + offsetof(struct request_gen_dhkey, k);
625                 readbyte((unsigned long)databuf, &keylen, sizeof(keylen));
626                 if (unlikely(keylen >= SHM_SIZE)) {
627                         pr_err("%s:%d:tks keylen=0x%x out of range.\n",
628                                         __func__, __LINE__, keylen);
629                         return -EIO;
630                 }
631                 for (cnt = 0; cnt < sizeof(keylen); cnt++) {
632                         ret = put_user(databuf[cnt], userdata + cnt);
633                         if (ret)
634                                 return -EIO;
635                 }
636                 databuf += sizeof(keylen);
637                 ret = get_user(userdata,
638                                 &(((struct request_gen_dhkey *)argp)->k.data));
639                 if (ret)
640                         return -EIO;
641                 for (cnt = 0; cnt < keylen; cnt++) {
642                         ret = put_user(databuf[cnt], userdata + cnt);
643                         if (ret)
644                                 return -EIO;
645                 }
646                 break;
647         case SEC_IOC_HMAC:
648                 buf->cmd = _IOC_NR(SEC_IOC_HMAC);
649                 databuf = buf->cmd_data;
650                 ret = get_user(keylen,
651                                 &(((struct request_hmac *)argp)->message.len));
652                 if (ret)
653                         return -EIO;
654                 if (unlikely(keylen >= SHM_SIZE)) {
655                         pr_err("%s:%d:tks keylen=0x%x out of range.\n",
656                                         __func__, __LINE__, keylen);
657                         return -EIO;
658                 }
659                 writebyte((unsigned long)databuf, &keylen, sizeof(keylen));
660                 databuf += sizeof(keylen);
661                 ret = get_user(userdata,
662                                 &(((struct request_hmac *)argp)->message.data));
663                 if (ret)
664                         return -EIO;
665                 for (cnt = 0; cnt < keylen; cnt++) {
666                         ret = get_user(databuf[cnt], userdata + cnt);
667                         if (ret)
668                                 return -EIO;
669                 }
670                 invoke_tks_fn_awake((TSP_FAST_FID(TSP_TKS)),
671                                                         SEC_IOC_HMAC, 0, 0);
672                 if (buf->cmd)
673                         return -(ERRNO_BASE + buf->cmd);
674                 databuf = buf->cmd_data;
675                 userdata = (char *)argp;
676                 readbyte((unsigned long)databuf, &keylen, sizeof(keylen));
677                 if (unlikely(keylen >= SHM_SIZE)) {
678                         pr_err("%s:%d:tks keylen=0x%x out of range.\n",
679                                         __func__, __LINE__, keylen);
680                         return -EIO;
681                 }
682                 for (cnt = 0; cnt < sizeof(keylen); cnt++) {
683                         ret = put_user(databuf[cnt], userdata + cnt);
684                         if (ret)
685                                 return -EIO;
686                 }
687                 databuf += sizeof(keylen);
688                 ret = get_user(userdata,
689                                 &(((struct request_hmac *)argp)->message.data));
690                 if (ret)
691                         return -EIO;
692                 for (cnt = 0; cnt < keylen; cnt++) {
693                         ret = put_user(databuf[cnt], userdata + cnt);
694                         if (ret)
695                                 return -EIO;
696                 }
697                 break;
698         case SEC_IDC_TEST_USED:
699                 ret = copy_from_user(buf, argp, sizeof(struct shm_mem_view));
700                 if (ret)
701                         return -EIO;
702                 break;
703         default:
704                 return -ENOTTY;
705         }
706         return ret;
707 }
708
709 static ssize_t sprd_tks_write(struct file *file, const char __user *buf,
710                 size_t count, loff_t *ppos)
711 {
712         return count;
713 }
714
715 static void get_cfg_addr(void)
716 {
717         struct device_node *np;
718         struct resource res;
719
720         np = of_find_compatible_node(NULL, NULL, "sprd,aon_apb");
721         if(!np)
722                 pr_err("sprd_tks_init: get aon_apb node failed!\n");
723         of_address_to_resource(np, 0, &res);
724         arm7_cfg_bus = (unsigned long)ioremap_nocache(res.start
725                                 + ARM7_CFG_BUS_OFFSET, 0x4);
726         np = of_find_compatible_node(NULL, NULL, "sprd,pmu_apb");
727         if(!np)
728                 pr_err("sprd_tks_init: get pmu_apb node failed!\n");
729         of_address_to_resource(np, 0, &res);
730         sleep_status = (unsigned long)ioremap_nocache(res.start
731                                 + SLEEP_STATUS_OFFSET, 0x4);
732 }
733
734 static const struct file_operations sprd_tks_fops = {
735         .owner          = THIS_MODULE,
736         .llseek         = no_llseek,
737         .unlocked_ioctl = sprd_tks_ioctl,
738         .open           = sprd_tks_open,
739         .write          = sprd_tks_write,
740         .release        = sprd_tks_release,
741 };
742
743 static struct miscdevice sprd_tks_miscdev = {
744         .minor  = MISC_DYNAMIC_MINOR,
745         .name   = "sprdtks",
746         .fops   = &sprd_tks_fops,
747 };
748
749 static int __init sprd_tks_init(void)
750 {
751         int ret;
752
753         get_cfg_addr();
754         ret = misc_register(&sprd_tks_miscdev);
755         if (ret)
756                 dev_err(sprd_tks_miscdev.this_device, "sprd tks reg error\n");
757         invoke_tks_fn = __invoke_tks_fn_smc;
758         shm_vaddr = dma_alloc_coherent(sprd_tks_miscdev.this_device, SHM_SIZE,
759                                                         &phy_addr, GFP_KERNEL);
760         if (!shm_vaddr) {
761                 dev_err(sprd_tks_miscdev.this_device, "shm_vaddr failure\n");
762                 return -ENOMEM;
763         }
764         memset(shm_vaddr, 0, SHM_SIZE);
765         /* the first argument of invoke_tks_fn_awake is the case that used to
766            initialize the share memory.*/
767         invoke_tks_fn_awake((TSP_FAST_FID(TSP_TKS_SHM_REQ_ADDR)),
768                                                                 phy_addr, 0, 0);
769         pr_info("%s:shm_vaddr:%p, phy_addr:0x%lx\n",
770                                         __func__, shm_vaddr, (ulong)phy_addr);
771
772         return ret;
773 }
774
775 static void __exit sprd_tks_exit(void)
776 {
777         dev_info(sprd_tks_miscdev.this_device, "sprd tks driver eixt!\n");
778         dma_free_coherent(sprd_tks_miscdev.this_device, SHM_SIZE,
779                                 shm_vaddr, phy_addr);
780         misc_deregister(&sprd_tks_miscdev);
781 }
782
783 module_init(sprd_tks_init);
784 module_exit(sprd_tks_exit);
785
786
787 MODULE_AUTHOR("spreadtrum");
788 MODULE_DESCRIPTION("sprd tks driver");
789 MODULE_LICENSE("GPL");