1 /*
2 * Copyright (c) 2015 South Silicon Valley Microelectronics Inc.
3 * Copyright (c) 2015 iComm Corporation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 #include <linux/irq.h>
18 #include <linux/module.h>
19 #include <linux/vmalloc.h>
20 #include <linux/platform_device.h>
21 #include <linux/mmc/sdio.h>
22 #include <linux/mmc/sdio_func.h>
23 #include <linux/mmc/sdio_ids.h>
24 #include <linux/mmc/card.h>
25 #include <linux/mmc/host.h>
26 #include <linux/gpio.h>
27 #include <linux/pm_runtime.h>
28 #include <linux/printk.h>
29 #include <linux/init.h>
30 #include <linux/module.h>
31 #include <linux/fs.h>
32 #include <linux/cdev.h>
33 #include <linux/slab.h>
34 #include <linux/uaccess.h>
35 #include <linux/version.h>
36 #include <hwif/sdio/sdio_def.h>
37 #include "sdiobridge.h"
38 #include "debug.h"
39 #define BLOCKSIZE 0x40
40 #define RXBUFLENGTH 1024*3
41 #define RXBUFSIZE 512
42 enum ssvcabrio_int
43 {
44 SSVCABRIO_INT_RX = 0x00000001,
45 SSVCABRIO_INT_TX = 0x00000002,
46 SSVCABRIO_INT_GPIO = 0x00000004,
47 SSVCABRIO_INT_SYS = 0x00000008,
48 };
49 #define CHECK_RET(_fun) \
50 do { \
51 if (0 != _fun) \
52 printk("File = %s\nLine = %d\nFunc=%s\nDate=%s\nTime=%s\n", __FILE__, __LINE__, __FUNCTION__, __DATE__, __TIME__); \
53 } while (0)
54 static unsigned int ssv_sdiobridge_ioctl_major = 0;
55 static unsigned int num_of_dev = 1;
56 static struct cdev ssv_sdiobridge_ioctl_cdev;
57 static struct class *fc;
58 static struct ssv_sdiobridge_glue *glue;
59 struct ssv_rxbuf
60 {
61 struct list_head list;
62 u32 rxsize;
63 u8 rxdata[RXBUFLENGTH];
64 };
65 static const struct sdio_device_id ssv_sdiobridge_devices[] =
66 {
67 {SDIO_DEVICE(MANUFACTURER_SSV_CODE, (MANUFACTURER_ID_CABRIO_BASE | 0x0))},
68 {}
69 };
70 MODULE_DEVICE_TABLE(sdio, ssv_sdiobridge_devices);
ssv_sdiobridge_ioctl_getFuncfocus(struct ssv_sdiobridge_glue * glue,unsigned int cmd,struct ssv_sdiobridge_cmd * pcmd_data,struct ssv_sdiobridge_cmd * pucmd_data,bool isCompat)71 static long ssv_sdiobridge_ioctl_getFuncfocus(struct ssv_sdiobridge_glue *glue,unsigned int cmd, struct ssv_sdiobridge_cmd *pcmd_data,struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
72 {
73 long retval =0;
74 if ( pcmd_data->out_data_len < 1)
75 {
76 retval = -1;
77 }
78 else
79 {
80 u8 out_data = glue->funcFocus;
81 if ( isCompat )
82 {
83 CHECK_RET(copy_to_user((int __user *)compat_ptr((unsigned long)pucmd_data->out_data),&out_data,sizeof(out_data)));
84 }
85 else
86 {
87 CHECK_RET(copy_to_user((int __user *)pucmd_data->out_data, &out_data, sizeof(out_data)));
88 }
89 }
90 return retval;
91 }
ssv_sdiobridge_ioctl_setFuncfocus(struct ssv_sdiobridge_glue * glue,unsigned int cmd,struct ssv_sdiobridge_cmd * pcmd_data,struct ssv_sdiobridge_cmd * pucmd_data,bool isCompat)92 static long ssv_sdiobridge_ioctl_setFuncfocus(struct ssv_sdiobridge_glue *glue,unsigned int cmd, struct ssv_sdiobridge_cmd *pcmd_data,struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
93 {
94 int retval =0;
95 if ( pcmd_data->out_data_len < 0)
96 {
97 retval = -EFAULT;
98 dev_err(glue->dev, "%s : input length must < 0",__FUNCTION__);
99 }
100 else
101 {
102 if ( isCompat )
103 {
104 CHECK_RET(copy_from_user(&glue->funcFocus,(int __user *)compat_ptr((unsigned long)pcmd_data->in_data),sizeof(glue->funcFocus)));
105 }
106 else
107 {
108 CHECK_RET(copy_from_user(&glue->funcFocus,(int __user *)pcmd_data->in_data,sizeof(glue->funcFocus)));
109 }
110 }
111 return retval;
112 }
ssv_sdiobridge_ioctl_getBusWidth(struct ssv_sdiobridge_glue * glue,unsigned int cmd,struct ssv_sdiobridge_cmd * pcmd_data,struct ssv_sdiobridge_cmd * pucmd_data,bool isCompat)113 static long ssv_sdiobridge_ioctl_getBusWidth(struct ssv_sdiobridge_glue *glue,unsigned int cmd, struct ssv_sdiobridge_cmd *pcmd_data,struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
114 {
115 struct sdio_func *func = dev_to_sdio_func(glue->dev);
116 long retval =0;
117 if ( pcmd_data->out_data_len < 1)
118 {
119 retval = -1;
120 }
121 else
122 {
123 u8 out_data = 1;
124 if ( func->card->host->ios.bus_width != MMC_BUS_WIDTH_1 )
125 {
126 out_data = 4;
127 }
128 if ( isCompat )
129 {
130 CHECK_RET(copy_to_user((int __user *)compat_ptr((unsigned long)pucmd_data->out_data),&out_data,sizeof(out_data)));
131 }
132 else
133 {
134 CHECK_RET(copy_to_user((int __user *)pucmd_data->out_data,&out_data,sizeof(out_data)));
135 }
136 }
137 return retval;
138 }
139 #if 0
140 static long ssv_sdiobridge_ioctl_setBusWidth(struct ssv_sdiobridge_glue *glue,unsigned int cmd, struct ssv_sdiobridge_cmd *pcmd_data,struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
141 {
142 struct sdio_func *func = dev_to_sdio_func(glue->dev);
143 int retval =0;
144 struct ssv_sdiobridge_cmd *pData;
145 u8 inData[1];
146 copy_from_user(pData,(int __user *)arg,sizeof(*pData));
147 if ( isCompat )
148 {
149 copy_from_user(&cmd_data,(int __user *)compat_ptr((unsigned long)pucmd_data),sizeof(*pucmd_data));
150 }
151 else
152 {
153 copy_from_user(&cmd_data,(int __user *)pucmd_data,sizeof(*pucmd_data));
154 }
155 if ( pData->in_data_len < 0)
156 {
157 retval = -EFAULT;
158 dev_err(glue->dev, "%s : input length must > 1",__FUNCTION__);
159 }
160 else
161 {
162 if ( pData->in_data == 1 )
163 {
164 if ( (func->card->host->caps & MMC_CAP_4_BIT_DATA) && !(func->card->cccr.low_speed && !func->card->cccr.wide_bus) )
165 {
166 extern void mmc_set_bus_width(struct mmc_host *host, unsigned int width);
167 u8 ctrl = sdio_f0_readb(func,SDIO_CCCR_IF,&retval);
168 if (retval)
169 return retval;
170 if (!(ctrl & SDIO_BUS_WIDTH_4BIT))
171 return 0;
172 ctrl &= ~SDIO_BUS_WIDTH_4BIT;
173 ctrl |= SDIO_BUS_ASYNC_INT;
174 sdio_f0_writeb(func,ctrl,SDIO_CCCR_IF,&retval);
175 if (retval)
176 return retval;
177 mmc_set_bus_width(func->card->host, MMC_BUS_WIDTH_1);
178 }
179 }
180 else
181 {
182 if ( func->card->host->ios.bus_width != MMC_BUS_WIDTH_4 )
183 {
184 }
185 }
186 }
187 return retval;
188 }
189 static long ssv_sdiobridge_ioctl_getBlockMode(struct ssv_sdiobridge_glue *glue,unsigned int cmd, struct ssv_sdiobridge_cmd *pcmd_data,struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
190 {
191 long retval =0;
192 if ( pcmd_data->out_data_len < 1)
193 {
194 retval = -1;
195 }
196 else
197 {
198 if ( isCompat )
199 {
200 copy_to_user((int __user *)compat_ptr((unsigned long)pucmd_data->out_data),&out_data,sizeof(out_data));
201 }
202 else
203 {
204 copy_to_user((int __user *)pucmd_data->out_data,&out_data,sizeof(out_data));
205 }
206 }
207 return retval;
208 }
209 static long ssv_sdiobridge_ioctl_setBlockMode(struct ssv_sdiobridge_glue *glue,unsigned int cmd, struct ssv_sdiobridge_cmd *pcmd_data,struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
210 {
211 long retval =0;
212 if ( pcmd_data->in_data_len < 1)
213 {
214 retval = -1;
215 }
216 else
217 {
218 if ( isCompat )
219 {
220 copy_from_user(&glue->blockMode,(int __user *)pucmd_data->in_data,sizeof(glue->blockMode));
221 }
222 }
223 return retval;
224 }
225 #endif
ssv_sdiobridge_ioctl_getBlockSize(struct ssv_sdiobridge_glue * glue,unsigned int cmd,struct ssv_sdiobridge_cmd * pcmd_data,struct ssv_sdiobridge_cmd * pucmd_data,bool isCompat)226 static long ssv_sdiobridge_ioctl_getBlockSize(struct ssv_sdiobridge_glue *glue,unsigned int cmd, struct ssv_sdiobridge_cmd *pcmd_data,struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
227 {
228 long retval =0;
229 if ( pcmd_data->out_data_len < 2)
230 {
231 retval = -1;
232 }
233 else
234 {
235 if ( isCompat )
236 {
237 CHECK_RET(copy_to_user((int __user *)compat_ptr((unsigned long)pucmd_data->out_data),&glue->blockSize,sizeof(glue->blockSize)));
238 }
239 else
240 {
241 CHECK_RET(copy_to_user((int __user *)pucmd_data->out_data,&glue->blockSize,sizeof(glue->blockSize)));
242 }
243 }
244 return retval;
245 }
ssv_sdiobridge_ioctl_setBlockSize(struct ssv_sdiobridge_glue * glue,unsigned int cmd,struct ssv_sdiobridge_cmd * pcmd_data,struct ssv_sdiobridge_cmd * pucmd_data,bool isCompat)246 static long ssv_sdiobridge_ioctl_setBlockSize(struct ssv_sdiobridge_glue *glue,unsigned int cmd, struct ssv_sdiobridge_cmd *pcmd_data,struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
247 {
248 struct sdio_func *func = dev_to_sdio_func(glue->dev);
249 long retval =0;
250 if ( pcmd_data->in_data_len < 2)
251 {
252 retval = -1;
253 }
254 else
255 {
256 if ( isCompat )
257 {
258 CHECK_RET(copy_from_user(&glue->blockSize,(int __user *)compat_ptr((unsigned long)pucmd_data->in_data),sizeof(glue->blockSize)));
259 }
260 else
261 {
262 CHECK_RET(copy_from_user(&glue->blockSize,(int __user *)pucmd_data->in_data,sizeof(glue->blockSize)));
263 }
264 dev_err(glue->dev,"%s: blockSize [%d]\n",__FUNCTION__,glue->blockSize);
265 sdio_claim_host(func);
266 sdio_set_block_size(func,glue->blockSize);
267 sdio_release_host(func);
268 }
269 return retval;
270 }
ssv_sdiobridge_ioctl_readByte(struct ssv_sdiobridge_glue * glue,unsigned int cmd,struct ssv_sdiobridge_cmd * pcmd_data,struct ssv_sdiobridge_cmd * pucmd_data,bool isCompat)271 static long ssv_sdiobridge_ioctl_readByte(struct ssv_sdiobridge_glue *glue,unsigned int cmd, struct ssv_sdiobridge_cmd *pcmd_data,struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
272 {
273 struct sdio_func *func = dev_to_sdio_func(glue->dev);
274 long retval =0;
275 if ( pcmd_data->out_data_len < 4)
276 {
277 retval = -1;
278 }
279 else
280 {
281 u32 address;
282 u8 out_data;
283 int ret = 0;
284 if ( isCompat )
285 {
286 CHECK_RET(copy_from_user(&address,(int __user *)compat_ptr((unsigned long)pucmd_data->in_data),sizeof(address)));
287 }
288 else
289 {
290 CHECK_RET(copy_from_user(&address,(int __user *)pucmd_data->in_data,sizeof(address)));
291 }
292 sdio_claim_host(func);
293 if ( glue->funcFocus == 0 )
294 {
295 out_data = sdio_f0_readb(func, address, &ret);
296 }
297 else
298 {
299 out_data = sdio_readb(func, address, &ret);
300 }
301 sdio_release_host(func);
302 dev_err(glue->dev,"%s: [%X] [%02X] ret:[%d]\n",__FUNCTION__,address,out_data,ret);
303 if ( !ret )
304 {
305 if ( isCompat )
306 {
307 CHECK_RET(copy_to_user((void *)compat_ptr((unsigned long)pucmd_data->out_data),&out_data,sizeof(out_data)));
308 }
309 else
310 {
311 CHECK_RET(copy_to_user((int __user *)pucmd_data->out_data,&out_data,sizeof(out_data)));
312 }
313 }
314 else
315 {
316 dev_err(glue->dev,"%s: error : %d",__FUNCTION__,ret);
317 retval = -1;
318 }
319 }
320 return retval;
321 }
ssv_sdiobridge_ioctl_writeByte(struct ssv_sdiobridge_glue * glue,unsigned int cmd,struct ssv_sdiobridge_cmd * pcmd_data,struct ssv_sdiobridge_cmd * pucmd_data,bool isCompat)322 static long ssv_sdiobridge_ioctl_writeByte(struct ssv_sdiobridge_glue *glue,unsigned int cmd, struct ssv_sdiobridge_cmd *pcmd_data,struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
323 {
324 struct sdio_func *func = dev_to_sdio_func(glue->dev);
325 long retval =0;
326 if ( pcmd_data->in_data_len < 5)
327 {
328 retval = -1;
329 }
330 else
331 {
332 u8 tmp[5];
333 u32 address;
334 u8 data;
335 int ret = 0;
336 if ( isCompat )
337 {
338 CHECK_RET(copy_from_user(tmp,(int __user *)compat_ptr((unsigned long)pucmd_data->in_data),sizeof(tmp)));
339 }
340 else
341 {
342 CHECK_RET(copy_from_user(tmp,(int __user *)pucmd_data->in_data,sizeof(tmp)));
343 }
344 address = *((u32 *)tmp);
345 data = tmp[4];
346 sdio_claim_host(func);
347 if ( glue->funcFocus == 0 )
348 {
349 sdio_f0_writeb(func,data, address, &ret);
350 }
351 else
352 {
353 sdio_writeb(func,data, address, &ret);
354 }
355 sdio_release_host(func);
356 if ( ret )
357 {
358 dev_err(glue->dev,"%s: error : %d",__FUNCTION__,ret);
359 retval = -1;
360 }
361 }
362 return retval;
363 }
ssv_sdiobridge_ioctl_getMultiByteIOPort(struct ssv_sdiobridge_glue * glue,unsigned int cmd,struct ssv_sdiobridge_cmd * pcmd_data,struct ssv_sdiobridge_cmd * pucmd_data,bool isCompat)364 static long ssv_sdiobridge_ioctl_getMultiByteIOPort(struct ssv_sdiobridge_glue *glue,unsigned int cmd, struct ssv_sdiobridge_cmd *pcmd_data,struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
365 {
366 long retval =0;
367 if ( pcmd_data->out_data_len < 4)
368 {
369 retval = -1;
370 }
371 else
372 {
373 if ( isCompat )
374 {
375 CHECK_RET(copy_to_user((int __user *)compat_ptr((unsigned long)pucmd_data->out_data),&glue->dataIOPort,sizeof(glue->dataIOPort)));
376 }
377 else
378 {
379 CHECK_RET(copy_to_user((int __user *)pucmd_data->out_data,&glue->dataIOPort,sizeof(glue->dataIOPort)));
380 }
381 }
382 return retval;
383 }
ssv_sdiobridge_ioctl_setMultiByteIOPort(struct ssv_sdiobridge_glue * glue,unsigned int cmd,struct ssv_sdiobridge_cmd * pcmd_data,struct ssv_sdiobridge_cmd * pucmd_data,bool isCompat)384 static long ssv_sdiobridge_ioctl_setMultiByteIOPort(struct ssv_sdiobridge_glue *glue,unsigned int cmd, struct ssv_sdiobridge_cmd *pcmd_data,struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
385 {
386 long retval =0;
387 if ( pcmd_data->in_data_len < 4)
388 {
389 retval = -1;
390 }
391 else
392 {
393 if ( isCompat )
394 {
395 CHECK_RET(copy_from_user(&glue->dataIOPort,(int __user *)compat_ptr((unsigned long)pucmd_data->in_data),sizeof(glue->dataIOPort)));
396 }
397 else
398 {
399 CHECK_RET(copy_from_user(&glue->dataIOPort,(int __user *)pucmd_data->in_data,sizeof(glue->dataIOPort)));
400 }
401 }
402 return retval;
403 }
ssv_sdiobridge_ioctl_readMultiByte(struct ssv_sdiobridge_glue * glue,unsigned int cmd,struct ssv_sdiobridge_cmd * pcmd_data,struct ssv_sdiobridge_cmd * pucmd_data,bool isCompat)404 static long ssv_sdiobridge_ioctl_readMultiByte(struct ssv_sdiobridge_glue *glue,unsigned int cmd, struct ssv_sdiobridge_cmd *pcmd_data,struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
405 {
406 struct sdio_func *func = dev_to_sdio_func(glue->dev);
407 long retval =0;
408 u8 *tmpdata;
409 int ret;
410 int readsize;
411 tmpdata = kzalloc(pcmd_data->out_data_len, GFP_KERNEL);
412 if ( tmpdata == NULL )
413 {
414 dev_err(glue->dev,"%s: error : alloc buf error size:%d",__FUNCTION__,pcmd_data->out_data_len);
415 return -1;
416 }
417 readsize = sdio_align_size(func,pcmd_data->out_data_len);
418 sdio_claim_host(func);
419 ret = sdio_memcpy_fromio(func, tmpdata,glue->dataIOPort, readsize );
420 sdio_release_host(func);
421 if (unlikely(glue->dump))
422 {
423 printk(KERN_DEBUG "%s: READ data address[%08x] len[%d] readsize[%d]\n",__FUNCTION__,glue->dataIOPort,(int)pcmd_data->out_data_len,readsize);
424 print_hex_dump(KERN_DEBUG, "ssv_sdio: READ ",
425 DUMP_PREFIX_OFFSET, 16, 1,
426 tmpdata, pcmd_data->out_data_len, false);
427 }
428 if ( !ret )
429 {
430 if ( isCompat )
431 {
432 CHECK_RET(copy_to_user((int __user *)compat_ptr((unsigned long)pucmd_data->out_data),tmpdata,pcmd_data->out_data_len));
433 }
434 else
435 {
436 CHECK_RET(copy_to_user((int __user *)pucmd_data->out_data,tmpdata,pcmd_data->out_data_len));
437 }
438 }
439 else
440 {
441 dev_err(glue->dev,"%s: error : %d",__FUNCTION__,ret);
442 retval = -1;
443 }
444 kfree(tmpdata);
445 dev_err(glue->dev,"%s(): %d\n", __FUNCTION__, ret);
446 return retval;
447 }
ssv_sdiobridge_ioctl_writeMultiByte(struct ssv_sdiobridge_glue * glue,unsigned int cmd,struct ssv_sdiobridge_cmd * pcmd_data,struct ssv_sdiobridge_cmd * pucmd_data,bool isCompat)448 static long ssv_sdiobridge_ioctl_writeMultiByte(struct ssv_sdiobridge_glue *glue,unsigned int cmd, struct ssv_sdiobridge_cmd *pcmd_data,struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
449 {
450 struct sdio_func *func = dev_to_sdio_func(glue->dev);
451 long retval =0;
452 u8 *tmpdata;
453 int ret;
454 int readsize ;
455 tmpdata = kzalloc(pcmd_data->in_data_len, GFP_KERNEL);
456 if ( tmpdata == NULL )
457 {
458 dev_err(glue->dev,"%s: error : alloc buf error size:%d",__FUNCTION__,pcmd_data->out_data_len);
459 return -1;
460 }
461 if ( isCompat )
462 {
463 CHECK_RET(copy_from_user(tmpdata,(int __user *)compat_ptr((unsigned long)pucmd_data->in_data),pcmd_data->in_data_len));
464 }
465 else
466 {
467 CHECK_RET(copy_from_user(tmpdata,(int __user *)pucmd_data->in_data,pcmd_data->in_data_len));
468 }
469 readsize = sdio_align_size(func,pcmd_data->in_data_len);
470 if (unlikely(glue->dump))
471 {
472 printk(KERN_DEBUG "%s: READ data address[%08x] len[%d] readsize[%d]\n",__FUNCTION__,glue->dataIOPort,(int)pcmd_data->in_data_len,readsize);
473 print_hex_dump(KERN_DEBUG, "ssv_sdio: WRITE ",
474 DUMP_PREFIX_OFFSET, 16, 1,
475 tmpdata, pcmd_data->in_data_len, false);
476 }
477 sdio_claim_host(func);
478 ret = sdio_memcpy_toio(func, glue->dataIOPort,tmpdata, readsize);
479 sdio_release_host(func);
480 if ( ret )
481 {
482 dev_err(glue->dev,"%s: error : %d",__FUNCTION__,ret);
483 retval = -1;
484 }
485 kfree(tmpdata);
486 return retval;
487 }
ssv_sdiobridge_ioctl_getMultiByteRegIOPort(struct ssv_sdiobridge_glue * glue,unsigned int cmd,struct ssv_sdiobridge_cmd * pcmd_data,struct ssv_sdiobridge_cmd * pucmd_data,bool isCompat)488 static long ssv_sdiobridge_ioctl_getMultiByteRegIOPort(struct ssv_sdiobridge_glue *glue,unsigned int cmd, struct ssv_sdiobridge_cmd *pcmd_data,struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
489 {
490 long retval =0;
491 if ( pcmd_data->out_data_len < 4)
492 {
493 retval = -1;
494 }
495 else
496 {
497 if ( isCompat )
498 {
499 CHECK_RET(copy_to_user((int __user *)compat_ptr((unsigned long)pucmd_data->out_data),&glue->regIOPort,sizeof(glue->regIOPort)));
500 }
501 else
502 {
503 CHECK_RET(copy_to_user((int __user *)pucmd_data->out_data,&glue->regIOPort,sizeof(glue->regIOPort)));
504 }
505 }
506 return retval;
507 }
ssv_sdiobridge_ioctl_setMultiByteRegIOPort(struct ssv_sdiobridge_glue * glue,unsigned int cmd,struct ssv_sdiobridge_cmd * pcmd_data,struct ssv_sdiobridge_cmd * pucmd_data,bool isCompat)508 static long ssv_sdiobridge_ioctl_setMultiByteRegIOPort(struct ssv_sdiobridge_glue *glue,unsigned int cmd, struct ssv_sdiobridge_cmd *pcmd_data,struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
509 {
510 long retval =0;
511 if ( pcmd_data->in_data_len < 4)
512 {
513 retval = -1;
514 }
515 else
516 {
517 if ( isCompat )
518 {
519 CHECK_RET(copy_from_user(&glue->regIOPort,(int __user *)compat_ptr((unsigned long)pucmd_data->in_data),sizeof(glue->regIOPort)));
520 }
521 else
522 {
523 CHECK_RET(copy_from_user(&glue->regIOPort,(int __user *)pucmd_data->in_data,sizeof(glue->regIOPort)));
524 }
525 }
526 return retval;
527 }
ssv_sdiobridge_ioctl_readReg(struct ssv_sdiobridge_glue * glue,unsigned int cmd,struct ssv_sdiobridge_cmd * pcmd_data,struct ssv_sdiobridge_cmd * pucmd_data,bool isCompat)528 static long ssv_sdiobridge_ioctl_readReg(struct ssv_sdiobridge_glue *glue,unsigned int cmd, struct ssv_sdiobridge_cmd *pcmd_data,struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
529 {
530 struct sdio_func *func = dev_to_sdio_func(glue->dev);
531 long retval =0;
532 if ( pcmd_data->in_data_len < 4 || pcmd_data->out_data_len < 4)
533 {
534 retval = -1;
535 }
536 else
537 {
538 u8 tmpdata[4];
539 int ret = 0;
540 if ( isCompat )
541 {
542 CHECK_RET(copy_from_user(tmpdata,(int __user *)compat_ptr((unsigned long)pucmd_data->in_data),sizeof(tmpdata)));
543 }
544 else
545 {
546 CHECK_RET(copy_from_user(tmpdata,(int __user *)pucmd_data->in_data,sizeof(tmpdata)));
547 }
548 sdio_claim_host(func);
549 dev_err(glue->dev,"%s: read reg 1 [%02X][%02X][%02X][%02X]\n",__FUNCTION__,tmpdata[0],tmpdata[1],tmpdata[2],tmpdata[3]);
550 ret = sdio_memcpy_toio(func, glue->regIOPort, tmpdata, 4);
551 ret = sdio_memcpy_fromio(func, tmpdata, glue->regIOPort, 4);
552 sdio_release_host(func);
553 dev_err(glue->dev,"%s: read reg 2 [%02X][%02X][%02X][%02X] ret:%d\n",__FUNCTION__,tmpdata[0],tmpdata[1],tmpdata[2],tmpdata[3],ret);
554 if ( !ret )
555 {
556 if ( isCompat )
557 {
558 CHECK_RET(copy_to_user((int __user *)compat_ptr((unsigned long)pucmd_data->out_data),tmpdata,sizeof(tmpdata)));
559 }
560 else
561 {
562 CHECK_RET(copy_to_user((int __user *)pucmd_data->out_data,tmpdata,sizeof(tmpdata)));
563 }
564 }
565 else
566 {
567 dev_err(glue->dev,"%s: error : %d",__FUNCTION__,ret);
568 retval = -1;
569 }
570 }
571 return retval;
572 }
ssv_sdiobridge_ioctl_writeReg(struct ssv_sdiobridge_glue * glue,unsigned int cmd,struct ssv_sdiobridge_cmd * pcmd_data,struct ssv_sdiobridge_cmd * pucmd_data,bool isCompat)573 static long ssv_sdiobridge_ioctl_writeReg(struct ssv_sdiobridge_glue *glue,unsigned int cmd, struct ssv_sdiobridge_cmd *pcmd_data,struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
574 {
575 struct sdio_func *func = dev_to_sdio_func(glue->dev);
576 long retval =0;
577 if ( pcmd_data->in_data_len < 8)
578 {
579 retval = -1;
580 }
581 else
582 {
583 u8 tmpdata[8];
584 int ret = 0;
585 if ( isCompat )
586 {
587 CHECK_RET(copy_from_user(tmpdata,(int __user *)compat_ptr((unsigned long)pucmd_data->in_data),sizeof(tmpdata)));
588 }
589 else
590 {
591 CHECK_RET(copy_from_user(tmpdata,(int __user *)pucmd_data->in_data,sizeof(tmpdata)));
592 }
593 dev_err(glue->dev,"%s: write reg ADR[%02X%02X%02X%02X] [%02X][%02X][%02X][%02X]\n",__FUNCTION__,tmpdata[3],tmpdata[2],tmpdata[1],tmpdata[0],
594 tmpdata[7], tmpdata[6], tmpdata[5], tmpdata[4]);
595 sdio_claim_host(func);
596 ret = sdio_memcpy_toio(func, glue->regIOPort, tmpdata, 8);
597 sdio_release_host(func);
598 if ( ret )
599 {
600 dev_err(glue->dev,"%s: error : %d",__FUNCTION__,ret);
601 retval = -1;
602 }
603 }
604 return retval;
605 }
ssv_sdiobridge_device_open(struct inode * inode,struct file * filp)606 static int ssv_sdiobridge_device_open(struct inode *inode, struct file *filp)
607 {
608 dev_err(glue->dev,"%s():\n", __FUNCTION__);
609 filp->private_data = glue;
610 return 0;
611 }
ssv_sdiobridge_device_close(struct inode * inode,struct file * filp)612 static int ssv_sdiobridge_device_close(struct inode *inode, struct file *filp)
613 {
614 dev_err(glue->dev,"%s():\n", __FUNCTION__);
615 return 0;
616 }
ssv_sdiobridge_device_ioctl_process(struct ssv_sdiobridge_glue * glue,unsigned int cmd,struct ssv_sdiobridge_cmd * pucmd_data,bool isCompat)617 static long ssv_sdiobridge_device_ioctl_process(struct ssv_sdiobridge_glue *glue, unsigned int cmd, struct ssv_sdiobridge_cmd *pucmd_data,bool isCompat)
618 {
619 struct ssv_sdiobridge_cmd cmd_data;
620 long retval=0;
621 if ( isCompat )
622 {
623 CHECK_RET(copy_from_user(&cmd_data,(int __user *)pucmd_data,sizeof(*pucmd_data)));
624 }
625 else
626 {
627 CHECK_RET(copy_from_user(&cmd_data,(int __user *)pucmd_data,sizeof(*pucmd_data)));
628 }
629 #if 0
630 #ifdef __x86_64
631 dev_err(glue->dev,"%s: isCompat[%d] [%lX] [%lX] [%X] \n",__FUNCTION__,isCompat,IOCTL_SSVSDIO_GET_FUNCTION_FOCUS,IOCTL_SSVSDIO_READ_DATA,cmd);
632 #else
633 dev_err(glue->dev,"%s: isCompat[%d] [%X] [%X] [%X] \n",__FUNCTION__,isCompat,IOCTL_SSVSDIO_GET_FUNCTION_FOCUS,IOCTL_SSVSDIO_READ_DATA,cmd);
634 #endif
635 #endif
636 switch (cmd)
637 {
638 case IOCTL_SSVSDIO_GET_FUNCTION_FOCUS:
639 retval = ssv_sdiobridge_ioctl_getFuncfocus(glue,cmd,&cmd_data,pucmd_data,isCompat);
640 break;
641 case IOCTL_SSVSDIO_SET_FUNCTION_FOCUS:
642 retval = ssv_sdiobridge_ioctl_setFuncfocus(glue,cmd,&cmd_data,pucmd_data,isCompat);
643 break;
644 case IOCTL_SSVSDIO_GET_BUS_WIDTH:
645 retval = ssv_sdiobridge_ioctl_getBusWidth(glue,cmd,&cmd_data,pucmd_data,isCompat);
646 break;
647 #if 0
648 case IOCTL_SSVSDIO_SET_BUS_WIDTH:
649 retval = ssv_sdiobridge_ioctl_setBusWidth(glue,cmd,&cmd_data,pucmd_data,isCompat);
650 break;
651 case IOCTL_SSVSDIO_GET_BUS_CLOCK:
652 break;
653 case IOCTL_SSVSDIO_SET_BUS_CLOCK:
654 break;
655 case IOCTL_SSVSDIO_GET_BLOCK_MODE:
656 retval = ssv_sdiobridge_ioctl_getBlockMode(glue,cmd,&cmd_data,pucmd_data,isCompat);
657 break;
658 case IOCTL_SSVSDIO_SET_BLOCK_MODE:
659 retval = ssv_sdiobridge_ioctl_setBlockMode(glue,cmd,&cmd_data,pucmd_data,isCompat);
660 break;
661 #endif
662 case IOCTL_SSVSDIO_GET_BLOCKLEN:
663 retval = ssv_sdiobridge_ioctl_getBlockSize(glue,cmd,&cmd_data,pucmd_data,isCompat);
664 break;
665 case IOCTL_SSVSDIO_SET_BLOCKLEN:
666 retval = ssv_sdiobridge_ioctl_setBlockSize(glue,cmd,&cmd_data,pucmd_data,isCompat);
667 break;
668 case IOCTL_SSVSDIO_READ_BYTE:
669 retval = ssv_sdiobridge_ioctl_readByte(glue,cmd,&cmd_data,pucmd_data,isCompat);
670 break;
671 case IOCTL_SSVSDIO_WRITE_BYTE:
672 retval = ssv_sdiobridge_ioctl_writeByte(glue,cmd,&cmd_data,pucmd_data,isCompat);
673 break;
674 case IOCTL_SSVSDIO_GET_MULTI_BYTE_IO_PORT:
675 retval = ssv_sdiobridge_ioctl_getMultiByteIOPort(glue,cmd,&cmd_data,pucmd_data,isCompat);
676 break;
677 case IOCTL_SSVSDIO_SET_MULTI_BYTE_IO_PORT:
678 retval = ssv_sdiobridge_ioctl_setMultiByteIOPort(glue,cmd,&cmd_data,pucmd_data,isCompat);
679 break;
680 case IOCTL_SSVSDIO_READ_MULTI_BYTE:
681 retval = ssv_sdiobridge_ioctl_readMultiByte(glue,cmd,&cmd_data,pucmd_data,isCompat);
682 break;
683 case IOCTL_SSVSDIO_WRITE_MULTI_BYTE:
684 retval = ssv_sdiobridge_ioctl_writeMultiByte(glue,cmd,&cmd_data,pucmd_data,isCompat);
685 break;
686 case IOCTL_SSVSDIO_GET_MULTI_BYTE_REG_IO_PORT:
687 retval = ssv_sdiobridge_ioctl_getMultiByteRegIOPort(glue,cmd,&cmd_data,pucmd_data,isCompat);
688 break;
689 case IOCTL_SSVSDIO_SET_MULTI_BYTE_REG_IO_PORT:
690 retval = ssv_sdiobridge_ioctl_setMultiByteRegIOPort(glue,cmd,&cmd_data,pucmd_data,isCompat);
691 break;
692 case IOCTL_SSVSDIO_READ_REG:
693 retval = ssv_sdiobridge_ioctl_readReg(glue,cmd,&cmd_data,pucmd_data,isCompat);
694 break;
695 case IOCTL_SSVSDIO_WRITE_REG:
696 retval = ssv_sdiobridge_ioctl_writeReg(glue,cmd,&cmd_data,pucmd_data,isCompat);
697 break;
698 }
699 return retval;
700 }
ssv_sdiobridge_device_compat_ioctl(struct file * filp,unsigned int cmd,unsigned long arg)701 static long ssv_sdiobridge_device_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
702 {
703 struct ssv_sdiobridge_glue *glue =filp->private_data;
704 long retval=0;
705 struct ssv_sdiobridge_cmd *pucmd_data;
706 pucmd_data = (struct ssv_sdiobridge_cmd *)arg;
707 retval = ssv_sdiobridge_device_ioctl_process( glue,cmd,pucmd_data,true);
708 return retval;
709 }
ssv_sdiobridge_device_ioctl(struct file * filp,unsigned int cmd,unsigned long arg)710 static long ssv_sdiobridge_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
711 {
712 struct ssv_sdiobridge_glue *glue =filp->private_data;
713 long retval=0;
714 struct ssv_sdiobridge_cmd *pucmd_data;
715 pucmd_data = (struct ssv_sdiobridge_cmd *)arg;
716 retval = ssv_sdiobridge_device_ioctl_process( glue,cmd,pucmd_data,false);
717 return retval;
718 }
ssv_sdiobridge_have_data(struct ssv_sdiobridge_glue * glue)719 static bool ssv_sdiobridge_have_data(struct ssv_sdiobridge_glue *glue)
720 {
721 dev_err(glue->dev,"%s(): !list_empty(&glue->rxreadybuf)[%d]\n", __FUNCTION__,!list_empty(&glue->rxreadybuf));
722 return !list_empty(&glue->rxreadybuf);
723 }
ssv_sdiobridge_device_read(struct file * filp,char * buffer,size_t length,loff_t * offset)724 static ssize_t ssv_sdiobridge_device_read(struct file *filp,
725 char *buffer,
726 size_t length,
727 loff_t *offset)
728 {
729 struct ssv_sdiobridge_glue *glue =filp->private_data;
730 struct ssv_rxbuf *bf;
731 int copylength;
732 dev_err(glue->dev,"%s():\n", __FUNCTION__);
733 spin_lock_bh(&glue->rxbuflock);
734 if (list_empty(&glue->rxreadybuf))
735 {
736 spin_unlock_bh(&glue->rxbuflock);
737 dev_err(glue->dev,"%s():no data for read \n", __FUNCTION__);
738 #if 1
739 if ( wait_event_interruptible(glue->read_wq, ssv_sdiobridge_have_data(glue))!=0)
740 {
741 dev_err(glue->dev,"%s():not get data ?? \n", __FUNCTION__);
742 return -1;
743 }
744 #else
745 wait_event(glue->read_wq,ssv_sdiobridge_have_data(glue));
746 #endif
747 spin_lock_bh(&glue->rxbuflock);
748 if (list_empty(&glue->rxreadybuf))
749 {
750 spin_unlock_bh(&glue->rxbuflock);
751 dev_err(glue->dev,"%s():stop ?? \n", __FUNCTION__);
752 return -1;
753 }
754 }
755 bf = list_first_entry(&glue->rxreadybuf, struct ssv_rxbuf, list);
756 list_del(&bf->list);
757 spin_unlock_bh(&glue->rxbuflock);
758 copylength = min(bf->rxsize,(u32)length);
759 CHECK_RET(copy_to_user((int __user *)buffer,bf->rxdata,copylength));
760 dev_err(glue->dev,"%s():get rx data : data len:[%d], user read len:[%d],real read len:[%d] \n", __FUNCTION__,bf->rxsize,(u32)length,copylength);
761 spin_lock_bh(&glue->rxbuflock);
762 list_add_tail(&bf->list, &glue->rxbuf);
763 spin_unlock_bh(&glue->rxbuflock);
764 return copylength;
765 }
ssv_sdiobridge_device_write(struct file * filp,const char * buff,size_t len,loff_t * off)766 static ssize_t ssv_sdiobridge_device_write(struct file *filp,
767 const char *buff,
768 size_t len,
769 loff_t *off)
770 {
771 struct ssv_sdiobridge_glue *glue =filp->private_data;
772 struct sdio_func *func = dev_to_sdio_func(glue->dev);
773 u8 *tmpdata;
774 int ret;
775 dev_err(glue->dev,"%s():\n", __FUNCTION__);
776 tmpdata = kzalloc(len, GFP_KERNEL);
777 if ( tmpdata == NULL )
778 {
779 dev_err(glue->dev,"%s: error : alloc buf error size:%d",__FUNCTION__,(u32)len);
780 return -1;
781 }
782 CHECK_RET(copy_from_user(tmpdata,(int __user *)buff,len));
783 if (unlikely(glue->dump))
784 {
785 printk(KERN_DEBUG "%s: WRITE data address[%08x] len[%d] readsize[%d]\n",__FUNCTION__,glue->dataIOPort,(int)len,sdio_align_size(func,len));
786 print_hex_dump(KERN_DEBUG, "ssv_sdio: WRITE ",
787 DUMP_PREFIX_OFFSET, 16, 1,
788 tmpdata, len, false);
789 }
790 sdio_claim_host(func);
791 ret = sdio_memcpy_toio(func, glue->dataIOPort,tmpdata, sdio_align_size(func,len));
792 sdio_release_host(func);
793 kfree(tmpdata);
794 if ( ret )
795 {
796 dev_err(glue->dev,"%s: error : %d",__FUNCTION__,ret);
797 return -1;
798 }
799 return len;
800 }
801 struct file_operations fops =
802 {
803 .owner = THIS_MODULE,
804 .read = ssv_sdiobridge_device_read,
805 .write = ssv_sdiobridge_device_write,
806 .open = ssv_sdiobridge_device_open,
807 .release = ssv_sdiobridge_device_close,
808 .compat_ioctl = ssv_sdiobridge_device_compat_ioctl,
809 .unlocked_ioctl = ssv_sdiobridge_device_ioctl
810 };
ssv_sdiobridge_irq_process(struct sdio_func * func,struct ssv_sdiobridge_glue * glue)811 static void ssv_sdiobridge_irq_process(struct sdio_func *func,
812 struct ssv_sdiobridge_glue *glue)
813 {
814 int err_ret;
815 u8 status;
816 sdio_claim_host(func);
817 status = sdio_readb(func, REG_INT_STATUS, &err_ret);
818 if ( status & SSVCABRIO_INT_RX )
819 {
820 struct ssv_rxbuf *bf;
821 int readsize;
822 spin_lock_bh(&glue->rxbuflock);
823 if (list_empty(&glue->rxbuf))
824 {
825 spin_unlock_bh(&glue->rxbuflock);
826 sdio_release_host(func);
827 dev_err(glue->dev, "ssv_sdiobridge_irq_process no avaible rx buf list??\n");
828 return;
829 }
830 else
831 {
832 bf = list_first_entry(&glue->rxbuf, struct ssv_rxbuf, list);
833 list_del(&bf->list);
834 }
835 spin_unlock_bh(&glue->rxbuflock);
836 bf->rxsize = (int)(sdio_readb(func, REG_CARD_PKT_LEN_0, &err_ret)&0xff);
837 dev_err(glue->dev, "sdio read rx size[%08x] 0x10[%02x]\n",bf->rxsize, sdio_readb(func, REG_CARD_PKT_LEN_0, &err_ret)&0xff);
838 bf->rxsize = bf->rxsize | ((sdio_readb(func, REG_CARD_PKT_LEN_1, &err_ret)&0xff)<<0x8);
839 readsize = sdio_align_size(func,bf->rxsize);
840 dev_err(glue->dev, "sdio read rx size[%08x] 0x11[%02x] readsize[%d]\n",bf->rxsize, sdio_readb(func, REG_CARD_PKT_LEN_1, &err_ret)&0xff,readsize);
841 err_ret = sdio_memcpy_fromio(func, bf->rxdata, glue->dataIOPort, readsize);
842 sdio_release_host(func);
843 dev_err(glue->dev, "ssv_sdiobridge_irq_process read 53, %d bytes ret:[%d]\n", readsize,err_ret );
844 if (unlikely(glue->dump))
845 {
846 printk(KERN_DEBUG "ssv_sdiobridge_irq_process: READ data address[%08x] len[%d] readsize[%d]\n",glue->dataIOPort,(int)bf->rxsize,readsize);
847 print_hex_dump(KERN_DEBUG, "ssv_sdio: READ ",
848 DUMP_PREFIX_OFFSET, 16, 1,
849 bf->rxdata, bf->rxsize, false);
850 }
851 if (WARN_ON(err_ret))
852 {
853 dev_err(glue->dev, "ssv_sdiobridge_irq_process read failed (%d)\n", err_ret);
854 spin_lock_bh(&glue->rxbuflock);
855 list_add_tail(&bf->list, &glue->rxbuf);
856 spin_unlock_bh(&glue->rxbuflock);
857 }
858 else
859 {
860 spin_lock_bh(&glue->rxbuflock);
861 list_add_tail(&bf->list, &glue->rxreadybuf);
862 wake_up(&glue->read_wq);
863 spin_unlock_bh(&glue->rxbuflock);
864 }
865 }
866 else
867 {
868 sdio_release_host(func);
869 }
870 }
ssv_sdiobridge_irq_handler(struct sdio_func * func)871 static void ssv_sdiobridge_irq_handler(struct sdio_func *func)
872 {
873 struct ssv_sdiobridge_glue *glue = sdio_get_drvdata(func);
874 dev_err(&func->dev, "ssv_sdiobridge_irq_handler\n");
875 WARN_ON(glue == NULL);
876 if ( glue != NULL )
877 {
878 atomic_set(&glue->irq_handling, 1);
879 ssv_sdiobridge_irq_process(func,glue);
880 atomic_set(&glue->irq_handling, 0);
881 wake_up(&glue->irq_wq);
882 }
883 }
ssv_sdiobridge_irq_enable(struct sdio_func * func,struct ssv_sdiobridge_glue * glue)884 static void ssv_sdiobridge_irq_enable(struct sdio_func *func,
885 struct ssv_sdiobridge_glue *glue)
886 {
887 int ret;
888 func = dev_to_sdio_func(glue->dev);
889 sdio_claim_host(func);
890 dev_err(glue->dev, "ssv_sdiobridge_irq_enable\n");
891 ret = sdio_claim_irq(func, ssv_sdiobridge_irq_handler);
892 if (ret)
893 dev_err(glue->dev, "Failed to claim sdio irq: %d\n", ret);
894 sdio_release_host(func);
895 }
ssv_sdiobridge_is_on_irq(struct ssv_sdiobridge_glue * glue)896 static bool ssv_sdiobridge_is_on_irq(struct ssv_sdiobridge_glue *glue)
897 {
898 return !atomic_read(&glue->irq_handling);
899 }
ssv_sdiobridge_irq_disable(struct ssv_sdiobridge_glue * glue,bool iswaitirq)900 static void ssv_sdiobridge_irq_disable(struct ssv_sdiobridge_glue *glue,bool iswaitirq)
901 {
902 struct sdio_func *func;
903 int ret;
904 dev_err(glue->dev, "ssv_sdiobridge_irq_disable1\n");
905 if ( glue != NULL )
906 {
907 func = dev_to_sdio_func(glue->dev);
908 sdio_claim_host(func);
909 dev_err(glue->dev, "ssv_sdiobridge_irq_disable2 [%d]\n",atomic_read(&glue->irq_handling));
910 if (atomic_read(&glue->irq_handling)&&iswaitirq)
911 {
912 dev_err(glue->dev, "ssv_sdiobridge_irq_disable3\n");
913 sdio_release_host(func);
914 ret = wait_event_interruptible(glue->irq_wq,
915 ssv_sdiobridge_is_on_irq(glue));
916 dev_err(glue->dev, "ssv_sdiobridge_irq_disable4 ret[%d]\n",ret);
917 if (ret)
918 return;
919 sdio_claim_host(func);
920 }
921 dev_err(glue->dev, "ssv_sdiobridge_irq_disable5\n");
922 ret = sdio_release_irq(func);
923 if (ret)
924 dev_err(glue->dev, "Failed to release sdio irq: %d\n", ret);
925 dev_err(glue->dev, "ssv_sdiobridge_irq_disable6\n");
926 sdio_release_host(func);
927 }
928 }
929 #if 0
930 static void ssv_sdiobridge_irq_sync(struct device *child)
931 {
932 struct ssv_sdiobridge_glue *glue = dev_get_drvdata(child->parent);
933 struct sdio_func *func;
934 int ret;
935 if ( glue != NULL )
936 {
937 func = dev_to_sdio_func(glue->dev);
938 sdio_claim_host(func);
939 if (atomic_read(&glue->irq_handling))
940 {
941 sdio_release_host(func);
942 ret = wait_event_interruptible(glue->irq_wq,
943 ssv_sdiobridge_is_on_irq(glue));
944 if (ret)
945 return;
946 sdio_claim_host(func);
947 }
948 sdio_release_host(func);
949 }
950 }
951 #endif
ssv_sdiobridge_read_parameter(struct sdio_func * func,struct ssv_sdiobridge_glue * glue)952 static void ssv_sdiobridge_read_parameter(struct sdio_func *func,
953 struct ssv_sdiobridge_glue *glue)
954 {
955 int err_ret;
956 sdio_claim_host(func);
957 glue->dataIOPort = 0;
958 glue->dataIOPort = glue->dataIOPort | (sdio_readb(func, REG_DATA_IO_PORT_0, &err_ret) << ( 8*0 ));
959 glue->dataIOPort = glue->dataIOPort | (sdio_readb(func, REG_DATA_IO_PORT_1, &err_ret) << ( 8*1 ));
960 glue->dataIOPort = glue->dataIOPort | (sdio_readb(func, REG_DATA_IO_PORT_2, &err_ret) << ( 8*2 ));
961 glue->regIOPort = 0;
962 glue->regIOPort = glue->regIOPort | (sdio_readb(func, REG_REG_IO_PORT_0, &err_ret) << ( 8*0 ));
963 glue->regIOPort = glue->regIOPort | (sdio_readb(func, REG_REG_IO_PORT_1, &err_ret) << ( 8*1 ));
964 glue->regIOPort = glue->regIOPort | (sdio_readb(func, REG_REG_IO_PORT_2, &err_ret) << ( 8*2 ));
965 dev_err(&func->dev, "dataIOPort 0x%x regIOPort 0x%x [%lx]\n",
966 glue->dataIOPort,glue->regIOPort,(long unsigned int)IOCTL_SSVSDIO_GET_BLOCKLEN);
967 sdio_set_block_size(func,glue->blockSize);
968 sdio_release_host(func);
969 }
ssv_sdiobridge_init_buf(struct ssv_sdiobridge_glue * glue)970 static int ssv_sdiobridge_init_buf(struct ssv_sdiobridge_glue *glue)
971 {
972 u32 bsize,i,error;
973 struct ssv_rxbuf *bf;
974 init_waitqueue_head(&glue->read_wq);
975 spin_lock_init(&glue->rxbuflock);
976 INIT_LIST_HEAD(&glue->rxbuf);
977 INIT_LIST_HEAD(&glue->rxreadybuf);
978 bsize = sizeof(struct ssv_rxbuf) * RXBUFSIZE;
979 glue->bufaddr = kzalloc(bsize, GFP_KERNEL);
980 if (glue->bufaddr == NULL)
981 {
982 error = -ENOMEM;
983 goto fail;
984 }
985 bf = glue->bufaddr;
986 for (i = 0; i < RXBUFSIZE; i++, bf++)
987 {
988 list_add_tail(&bf->list, &glue->rxbuf);
989 }
990 return 0;
991 fail:
992 return error;
993 }
994 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
ssv_sdiobridge_devnode(struct device * dev,umode_t * mode)995 static char *ssv_sdiobridge_devnode(struct device *dev, umode_t *mode)
996 #else
997 static char *ssv_sdiobridge_devnode(struct device *dev, mode_t *mode)
998 #endif
999 {
1000 if (!mode)
1001 return NULL;
1002 *mode = 0666;
1003 return NULL;
1004 }
1005 extern int ssv_devicetype;
ssv_sdiobridge_probe(struct sdio_func * func,const struct sdio_device_id * id)1006 static int __devinit ssv_sdiobridge_probe(struct sdio_func *func,
1007 const struct sdio_device_id *id)
1008 {
1009 mmc_pm_flag_t mmcflags;
1010 int ret = -ENOMEM;
1011 dev_t dev;
1012 int alloc_ret = 0;
1013 int cdev_ret = 0;
1014 int err_ret;
1015 if (ssv_devicetype != 1) {
1016 printk(KERN_INFO "Not using SSV6200 bridge SDIO driver.\n");
1017 return -ENODEV;
1018 }
1019 printk(KERN_INFO "=======================================\n");
1020 printk(KERN_INFO "== RUN SDIO BRIDGE ==\n");
1021 printk(KERN_INFO "=======================================\n");
1022 printk(KERN_INFO "ssv_sdiobridge_probe func->num:%d",func->num);
1023 if (func->num != 0x01)
1024 return -ENODEV;
1025 glue = kzalloc(sizeof(*glue), GFP_KERNEL);
1026 if (!glue)
1027 {
1028 dev_err(&func->dev, "can't allocate glue\n");
1029 goto out;
1030 }
1031 glue->blockMode = false;
1032 glue->blockSize = BLOCKSIZE;
1033 glue->autoAckInt = true;
1034 glue->dump = false;
1035 glue->funcFocus = 1;
1036 ssv_sdiobridge_init_buf(glue);
1037 glue->dev = &func->dev;
1038 func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
1039 func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
1040 mmcflags = sdio_get_host_pm_caps(func);
1041 dev_err(glue->dev, "sdio PM caps = 0x%x\n", mmcflags);
1042 sdio_set_drvdata(func, glue);
1043 pm_runtime_put_noidle(&func->dev);
1044 ssv_sdiobridge_read_parameter(func,glue);
1045 dev = MKDEV(ssv_sdiobridge_ioctl_major, 0);
1046 alloc_ret = alloc_chrdev_region(&dev, 0, num_of_dev, FILE_DEVICE_SSVSDIO_NAME);
1047 if (alloc_ret)
1048 goto error;
1049 ssv_sdiobridge_ioctl_major = MAJOR(dev);
1050 cdev_init(&ssv_sdiobridge_ioctl_cdev, &fops);
1051 cdev_ret = cdev_add(&ssv_sdiobridge_ioctl_cdev, dev, num_of_dev);
1052 if (cdev_ret)
1053 goto error;
1054 fc=class_create(THIS_MODULE, FILE_DEVICE_SSVSDIO_NAME);
1055 fc->devnode = ssv_sdiobridge_devnode;
1056 device_create(fc, NULL, dev, NULL, "%s", FILE_DEVICE_SSVSDIO_NAME);
1057 dev_err(glue->dev, "%s driver(major: %d) installed.\n", FILE_DEVICE_SSVSDIO_NAME, ssv_sdiobridge_ioctl_major);
1058 init_waitqueue_head(&glue->irq_wq);
1059 ssv_sdiobridge_irq_enable(func,glue);
1060 sdio_claim_host(func);
1061 #ifdef CONFIG_SSV_SDIO_EXT_INT
1062 sdio_writeb(func,(~(SSVCABRIO_INT_RX)|SSVCABRIO_INT_GPIO)&0x7, 0x04, &err_ret);
1063 #else
1064 sdio_writeb(func,(~(SSVCABRIO_INT_RX|SSVCABRIO_INT_GPIO))&0x7, 0x04, &err_ret);
1065 #endif
1066 sdio_release_host(func);
1067 return 0;
1068 error:
1069 if (cdev_ret == 0)
1070 cdev_del(&ssv_sdiobridge_ioctl_cdev);
1071 if (alloc_ret == 0)
1072 unregister_chrdev_region(dev, num_of_dev);
1073 kfree(glue);
1074 out:
1075 return ret;
1076 }
ssv_sdiobridge_remove(struct sdio_func * func)1077 static void __devexit ssv_sdiobridge_remove(struct sdio_func *func)
1078 {
1079 struct ssv_sdiobridge_glue *glue = sdio_get_drvdata(func);
1080 dev_t dev;
1081 int err_ret;
1082 sdio_claim_host(func);
1083 #ifdef CONFIG_SSV_SDIO_EXT_INT
1084 sdio_writeb(func,0, 0x04, &err_ret);
1085 #else
1086 sdio_writeb(func,SSVCABRIO_INT_GPIO, 0x04, &err_ret);
1087 #endif
1088 sdio_release_host(func);
1089 ssv_sdiobridge_irq_disable(glue,false);
1090 dev = MKDEV(ssv_sdiobridge_ioctl_major, 0);
1091 device_destroy(fc,dev);
1092 class_destroy(fc);
1093 cdev_del(&ssv_sdiobridge_ioctl_cdev);
1094 unregister_chrdev_region(dev, num_of_dev);
1095 pm_runtime_get_noresume(&func->dev);
1096 if ( glue )
1097 {
1098 dev_err(glue->dev, "ssv_sdiobridge_remove");
1099 if (glue->bufaddr)
1100 {
1101 kfree(glue->bufaddr);
1102 }
1103 kfree(glue);
1104 glue = NULL;
1105 }
1106 sdio_set_drvdata(func, NULL);
1107 }
1108 #ifdef CONFIG_PM
ssv_sdiobridge_suspend(struct device * dev)1109 static int ssv_sdiobridge_suspend(struct device *dev)
1110 {
1111 int ret = 0;
1112 return ret;
1113 }
ssv_sdiobridge_resume(struct device * dev)1114 static int ssv_sdiobridge_resume(struct device *dev)
1115 {
1116 dev_dbg(dev, "ssvcabrio resume\n");
1117 return 0;
1118 }
1119 static const struct dev_pm_ops ssv_sdiobridge_pm_ops =
1120 {
1121 .suspend = ssv_sdiobridge_suspend,
1122 .resume = ssv_sdiobridge_resume,
1123 };
1124 #endif
1125 static struct sdio_driver ssv_sdio_bridge_driver =
1126 {
1127 .name = "ssv_sdio_bridge",
1128 .id_table = ssv_sdiobridge_devices,
1129 .probe = ssv_sdiobridge_probe,
1130 .remove = __devexit_p(ssv_sdiobridge_remove),
1131 #ifdef CONFIG_PM
1132 .drv = {
1133 .pm = &ssv_sdiobridge_pm_ops,
1134 },
1135 #endif
1136 };
1137 EXPORT_SYMBOL(ssv_sdio_bridge_driver);
1138 #if 1
ssv_sdiobridge_init(void)1139 static int __init ssv_sdiobridge_init(void)
1140 {
1141 printk(KERN_INFO "ssv_sdiobridge_init\n");
1142 return sdio_register_driver(&ssv_sdio_bridge_driver);
1143 }
ssv_sdiobridge_exit(void)1144 static void __exit ssv_sdiobridge_exit(void)
1145 {
1146 printk(KERN_INFO "ssv_sdiobridge_exit\n");
1147 sdio_unregister_driver(&ssv_sdio_bridge_driver);
1148 }
1149 module_init(ssv_sdiobridge_init);
1150 module_exit(ssv_sdiobridge_exit);
1151 #endif
1152 MODULE_LICENSE("GPL");
1153 MODULE_AUTHOR("iComm Semiconductor Co., Ltd");
1154