NXP恩智浦PN544driver驱动程序.docx
《NXP恩智浦PN544driver驱动程序.docx》由会员分享,可在线阅读,更多相关《NXP恩智浦PN544driver驱动程序.docx(24页珍藏版)》请在冰豆网上搜索。
NXP恩智浦PN544driver驱动程序
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
siyahkernel/drivers/misc/pn544・c
iy*
*Copyright(C)20JOTrustedLogicSA.
*
*Thisprogramisfreesoftware;youcanredistributeitand/ormodify
*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby
*theFreeSoftwareFoundation;eitherversion2oftheLicense,or
*(atyouroption)anylaterversion.
*
*Thisprogramisdistributedinthehopethatitwillbeuseful,
*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe
*GNUGeneralPublicLicenseformoredetails.
*
*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense
*alongwiththisprogram;ifnot.writetotheFreeSoftware
*Foundation,Inc.,51FranklinSt,FifthFloor,Boston,MA02110-1301USA
*
V
20#include
21#include
22#include
23#include
24#include
25#include
26#include
27#include
28#include
29#include
30#include
31#include
32#include
33#include
34#include
35#include
36#include
37#include
38
38#defineMAXBUFFERSIZE512
39#defineMAXLLCFRAMESIZE0x20
40#defineMAXTRYI2CREAD10
42
43#defineNFCDEBUG0
44
do_reading;
voidpn544_disable_irq(structpn544_dev*pn544_dev)
unsignedlongflags;
spinjock_irqsave(&pn544_dev・>irq_enablcd_lock,flags);
if(pn544_dev->irq_enabled){disablejrq_nosync(pn544_dev->client->irq);pn544_dev->irq_enabled=false;
}
spin_unlock_irqrestore(&pn544_dev->irq_enabled_lock,flags);
irqreturn_tpn544_dev_irq_handler(intirq,void*dev_id)structpn544_dev*pn544_dev=devoid;
if(!
gpio_get_value(pn544_dev->irq_gpio))
returnIRQ_HANDLED:
pn544_disable_irq(pn544_dev);
/*Wakeupwaitingreaders*/
46
47
48
49
50
51
52
53
54
55};
56
57bool
58
59static
60{
61
62
63
64
65
66
67
68
69}
70
71static
72{
73
74
75
76
77
78
79
80
wake_up(&pn544_dev・>read_wq);
81do_reading=l;
82
82#ifNFC_DEBUG
83pr_info("pn544:
call\n);
84#endif
86
85returnIRQ_HANDLED;
86}
89
87staticssize_tpn544_dev_read(structfile*filp,char_user*buf,
88size_tcount,loffLt^offset)
89{
90structpn544_dev*pn544_dev=filp->private_data;
91chartmp[MAX_BUFFER_SIZE];
92intret;
93chardatasizelength=1;
94chardatasize=0;
95charreadingWatchdog=0;
99
100
101if(count>MAX_BUFFER_SIZE)
102count=MAX_BUFFER_SIZE;
103
103pr_debug("%s:
reading%zubytes.irq=%s\n'\_func_,
104count,gpio_get_value(pn544_dev->irq_gpio)?
'10);
106
105#ifNFC_DEBUG
106pr_info("pn544:
+r\n");
107#endif
110
108mutex_Iock(&pn544_dev->read_mutex);
112
114
115
116
117
118
119
120
121
113wait_irq:
if(!
gpio_get_value(pn544_dev->irq_gpio)){
if(filp->f_flags&O_NONBLOCK){
prJnfoCs:
O_NONBLOCK\n”,_func_);ret=-EAGAIN;
gotofail;
1
122
123
124
125
126
127
128
129
130
131
pn544_dev->irq_enabled=true;do_reading=0;
enable_irq(pn544_dev->client->irq);
ret=wait_evenMnterruptible(pn544_dev・>read_wq,do_reading);
/*gpio_get_value(pn544_dev->irq_gpio));*/
/*pr_info("pn544:
h\/i*/pn544_disable_irq(pn544_dev);
132#ifNFC_DEBUG
133pr_info(Hpn544:
h\nH);
134#endif
135
136if(ret)
137gotofail;
138}
139/*Readdata*/
140
141
142
143
144
145
146
147
148
149
150
151down*/
if(count==1y^NonnalmodeV
{
ret=i2c_master_recv(pn544_dev->client,tmp.datasizelength);
if(copy_to_user(buf,tmp,datasizelength)){
pr_warning(H%s:
failedtocopytouserspaceXn",_func_)return-EFAULT;
}
Ifbadframeisreceivedfrompn544,weneedtoreadagainafterwaitingthatI
152
153
154
155
156
157
158
159
160
161
162
if(MAX_LLC_FRAME_SIZEpr_err(1'pn544_devsize>MAX_LLC_FRAME_SIZEreceived!
M)msleep
(2)/<$7^7?
2mstowaitIRQfalldown
readingWatchdog++;
gotowaitjrq;
)
datasize=tnip[0];
ret=i2c_master_recv(pn544_dev->client,tmp.datasize);
mutex_unlock(&pn544_dev->read_mutex);
if(ret<0){
pr-errC'^s:
i2c_master_recvreturned%d\n",_func_,ret);
returnret;
}
if(ret>datasize+1){
pr_err('%s:
receivedtoomanybytesfromi2c(%d)\n*\
—func—,ret);
return・EIO;
I
if(copy_to_user(buf+l,tmp,ret)){
pr_err('%s:
failedtocopytouserspace\nH,_func_);
return-EFAULT;
}
//addonemorebyteforsizebyte(readonfirsttime)
ret++;
1
else/^downloadmode^/
{
ret=i2c_master_recv(pn544_dev->client,tmp,count);
Ifbadframeisreceivedfrompn544.weneedtoreadagainafterwaitingthatI
if(MAX_LLC_FRAME_SIZEpr_err(''pn544_dev_read:
size>MAX_LLC_FRAME_SIZEreceived!
Jmsleep
(2)/2mstowaitIRQfalldown
readingWatchdog++:
gotowait_irq;
I
mutex^unlock(&pn544_dev・>read_mutex);
if(ret<0){
pr_err("%s:
i2c_master_recvreturned%d\n'\_func_,ret);
returnret;
}
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188down*/
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
if(ret>count){
pr_err("r7s:
receivedtoomanybytesfromi2c(%d)\n",—func—,ret);
return-EIO;
if(copy_to_iiser(biif,tmp,ret)){
pr_err(,65s:
failedtocopytouserspace'rf;_func_);return-EFAULT;
I
}
returnret;
mutex^unlock(&pn544_dev・>read_mutex);
223staticssize_tpn544_dev_write(structfile*filp,constchar_user*buf,
224size_tcount,loff_t^offset)
225{
226structpn544_dev*pn544_dev;
227chartmp[MAX_BUFFER_SIZE];
228intret;
229
229pn544_dev=filp->private_data;
231
232#ifNFC_DEBUG
if(count>MAX_BUFFER_SIZE)
count=MAX_BUFFER_SIZE;
if(copy_from_user(tmp,buf,count)){
pr_err(*s:
failedtocopyfromuserspaccXn",_func_);return-EFAULT;
}
pr_debug(writing%zubytes.\iiH,_func_,count);
251
252
253
254
255
256
257
258)
259
260static
261{
262
263
264
265
266
267
268
269
270
271}
272
273static
274
275{
276
277
278
279
280
281
282
283
284
285
ret=i2c_master_send(pn544_dev->client,tmp,count);
247248#ifNFCDEBUG
249
250#endif
pr_info("pn544:
-w\n");
if(ret!
=count){
pr_err("^s:
i2c_master_sendreturned%d\n'\_func_,ret);ret=-EIO;
)
returnret;
intpn544_dev_open(structinode*inode,structfile*filp)
structpn544_dev*pn544_dev=container_of(filp->private_data,structpn544_dev,pn544_device);
filp->private_data=pn544_dev;
pr_debug("%s:
%d,%d\n",_func_,imajor(inode),iininor(inode));
return0;
intpn544_dev_ioctl(structinode*inode,structfile*filp.
unsignedintcmd,unsignedlongarg)
structpn544_dev*pn544_dev=filp->private_data;
switch(cmd){
casePN544_SET_PWR:
if(arg==2){
/*poweronwithfirmwaredownload(requireshwreset)*/
pr_info('%spoweronwithfirniware\n\_func_);gpio_set_value(pn544_dev・>ven_gpio.1);gpio_seCvakie(pn544_dev->firm_gpio,1);
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314)
315
316static
317
318
319
320
321
322
323};
324
325static
326
msleep(lO);gpio_set_value(pn544_dev->ven_gpio,0);msleep(lO);
gpio_set_value(pn544_dev->ven_gpio,1);msleep(lO);
}elseif(arg==1){
/*poweron*/pr_info("%spoweron\n",_func_);gpio_set_value(pn544_dev->firm_gpio,0);gpio_set_value(pn544_dev->ven_gpio,1);msleep(lO);
}elseif(arg==0){
/*poweroff*/
pr_info("%spoweroffXn_func_);
gpio_set_value(pn544_dev->firm_gpio,0);gpio_set_value(pn544_dev->ven_gpio,0);msleep(10);
}else{
pr_err("%sbadarg%u\n",_func_,arg);return-EINVAL;
}
break;
default:
pr_err(M%sbadioctl%u\nM,_func_,cmd);return-EINVAL;
}return0;
conststructfile_operationspn544_dev_fops={.owner=THIS_MODULE,
.llseek=no_llseek,
・read=pn544_dev_read,
・write=pn544_dev_write,
・open=pn544_dev_open,
.ioctl=pn544_dev_ioctl,
intpn544_probe(structi2c_client^client,
conststructi2c_device_id*id)
intret;
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
structpn544_i2c_platform_data*platform_data;
structpn544_dev*pn544_dev;
platform_data=client->dev.platform_data;
if(platform_data=NULL){
pr_err("%s:
nfcprobe_func_);
return-ENODEV;
)
if(!
i2c_check_functionality(client->adapter,I2C_FUNC_I2C)){
pr_err(“心:
needI2C_FUNC_I2C\n",_func_);
return-ENODEV;
}
ret=gpio_request(platform_data->irq_gpio,"nfc_int);
if(ret)
return-ENODEV;
ret=gpio_request(platform_data->ven_gpio,nnfc_ven);
if(ret)
gotoerr_ven;
ret=gpio_request(platform_data->firm_gpio,Hnfc_firm);
if(ret)
gotoerr_firm;
pn544_dev=kzalloc(sizeof(*pn544_dev),GFP_KERNEL);
if(pn544_dev==NULL){
dev_err(&clien卜〉dev,
"failedtoallocatememoryformoduledata\nM);ret=-ENOMEM;
gotoerr_exit;
}
pMnfoC*%s:
IRQmini_func_,client->irq);
pn544_dev->irq_gpio=platform_data->irq_gpio;
pn544_dev->ven_gpio=platform_data->ven_gpio;pn544_dev->firni_gpio=platform_data->firm_gpio;pn544_dev->client=client;
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
/*initmutexandqueuesV
init_waitqueue_head(&pn544_dev->read_wq);mutex_init(&pn544_dev->read_mutex);
spin_lock_init(&pn544_dev->irq_enabled_lock);
pn544_dev->pn544_device,minor=MISC_DYNAMIC_MINOR;pn544_dev->pn544_device.name=pn54