LinuxQuestions.org
Visit the LQ Articles and Editorials section
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software
User Name
Password
Linux - Software This forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.

Notices

Reply
 
Search this Thread
Old 08-28-2008, 11:37 AM   #1
Mintu123
LQ Newbie
 
Registered: Aug 2008
Posts: 1

Rep: Reputation: 0
SPIDEV implementation issues - probe not called


Hi
I am trying to implement spidev driver for the SPI interface on mpc8332 board. I compiled the spi module in the kernel and then I compiled the spidev module. The spidev.c file is shown below.
Now the issue is that the spidev_probe function is never called and hence the spidev_open finds nothing.
If anybody has any idea about this please let me know.
Thanks
Min2

/*
* spidev.c -- simple synchronous userspace interface to SPI devices
*
* Copyright (C) 2006 SWAPP
* Andrea Paterniani <a.paterniani@swapp-eng.it>
* Copyright (C) 2007 David Brownell (simplification, cleanup)

21 */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/slab.h>

#include <linux/spi/spi.h>
#include <linux/spi/spidev.h>
#include <asm/uaccess.h>

53 #define SPIDEV_MAJOR 153 /* assigned */
54 #define N_SPI_MINORS 32 /* ... up to 256 */
55
56 static unsigned long minors[N_SPI_MINORS / BITS_PER_LONG];
57
58
59 /* Bit masks for spi_device.mode management. Note that incorrect
60 * settings for CS_HIGH and 3WIRE can cause *lots* of trouble for other
61 * devices on a shared bus: CS_HIGH, because this device will be
62 * active when it shouldn't be; 3WIRE, because when active it won't
63 * behave as it should.
64 *
65 * REVISIT should changing those two modes be privileged?
66 */
67 #define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \
68 | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP)
69
70 struct spidev_data {
71 dev_t devt;
72 spinlock_t spi_lock;
73 struct spi_device *spi;
74 struct list_head device_entry;
75
76 /* buffer is NULL unless this device is open (users > 0) */
77 struct mutex buf_lock;
78 unsigned users;
79 u8 *buffer;
80 };
81
82 static LIST_HEAD(device_list);
83 static DEFINE_MUTEX(device_list_lock);
84
85 static unsigned bufsiz = 4096;
86 module_param(bufsiz, uint, S_IRUGO);
87 MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message");
88
89
95 static void spidev_complete(void *arg)
96 {
97 complete(arg);
98 }
99
100 static ssize_t
101 spidev_sync(struct spidev_data *spidev, struct spi_message *message)
102 {
103 DECLARE_COMPLETION_ONSTACK(done);
104 int status;
105
106 message->complete = spidev_complete;
107 message->context = &done;
108
109 spin_lock_irq(&spidev->spi_lock);
110 if (spidev->spi == NULL)
111 status = -ESHUTDOWN;
112 else
113 status = spi_async(spidev->spi, message);
114 spin_unlock_irq(&spidev->spi_lock);
115
116 if (status == 0) {
117 wait_for_completion(&done);
118 status = message->status;
119 if (status == 0)
120 status = message->actual_length;
121 }
122 return status;
123 }
124
125 static inline ssize_t
126 spidev_sync_write(struct spidev_data *spidev, size_t len)
127 {
128 struct spi_transfer t = {
129 .tx_buf = spidev->buffer,
130 .len = len,
131 };
132 struct spi_message m;
133
134 spi_message_init(&m);
135 spi_message_add_tail(&t, &m);
136 return spidev_sync(spidev, &m);
137 }
138
139 static inline ssize_t
140 spidev_sync_read(struct spidev_data *spidev, size_t len)
141 {
142 struct spi_transfer t = {
143 .rx_buf = spidev->buffer,
144 .len = len,
145 };
146 struct spi_message m;
147
148 spi_message_init(&m);
149 spi_message_add_tail(&t, &m);
150 return spidev_sync(spidev, &m);
151 }
152
153
156 static ssize_t
157 spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
158 {
159 struct spidev_data *spidev;
160 ssize_t status = 0;
161
162 /* chipselect only toggles at start or end of operation */
163 if (count > bufsiz)
164 return -EMSGSIZE;
165
166 spidev = filp->private_data;
167
168 mutex_lock(&spidev->buf_lock);
169 status = spidev_sync_read(spidev, count);
170 if (status > 0) {
171 unsigned long missing;
172
173 missing = copy_to_user(buf, spidev->buffer, status);
174 if (missing == status)
175 status = -EFAULT;
176 else
177 status = status - missing;
178 }
179 mutex_unlock(&spidev->buf_lock);
180
181 return status;
182 }
183
184 /* Write-only message with current device setup */
185 static ssize_t
186 spidev_write(struct file *filp, const char __user *buf,
187 size_t count, loff_t *f_pos)
188 {
189 struct spidev_data *spidev;
190 ssize_t status = 0;
191 unsigned long missing;
192
193 /* chipselect only toggles at start or end of operation */
194 if (count > bufsiz)
195 return -EMSGSIZE;
196
197 spidev = filp->private_data;
198
199 mutex_lock(&spidev->buf_lock);
200 missing = copy_from_user(spidev->buffer, buf, count);
201 if (missing == 0) {
202 status = spidev_sync_write(spidev, count);
203 } else
204 status = -EFAULT;
205 mutex_unlock(&spidev->buf_lock);
206
207 return status;
208 }
209
210 static int spidev_message(struct spidev_data *spidev,
211 struct spi_ioc_transfer *u_xfers, unsigned n_xfers)
212 {
213 struct spi_message msg;
214 struct spi_transfer *k_xfers;
215 struct spi_transfer *k_tmp;
216 struct spi_ioc_transfer *u_tmp;
217 unsigned n, total;
218 u8 *buf;
219 int status = -EFAULT;
220
221 spi_message_init(&msg);
222 k_xfers = kcalloc(n_xfers, sizeof(*k_tmp), GFP_KERNEL);
223 if (k_xfers == NULL)
224 return -ENOMEM;
225
226 /* Construct spi_message, copying any tx data to bounce buffer.
227 * We walk the array of user-provided transfers, using each one
228 * to initialize a kernel version of the same transfer.
229 */
230 mutex_lock(&spidev->buf_lock);
231 buf = spidev->buffer;
232 total = 0;
233 for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;
234 n;
235 n--, k_tmp++, u_tmp++) {
236 k_tmp->len = u_tmp->len;
237
238 total += k_tmp->len;
239 if (total > bufsiz) {
240 status = -EMSGSIZE;
241 goto done;
242 }
243
244 if (u_tmp->rx_buf) {
245 k_tmp->rx_buf = buf;
246 if (!access_ok(VERIFY_WRITE, (u8 __user *)
247 (uintptr_t) u_tmp->rx_buf,
248 u_tmp->len))
249 goto done;
250 }
251 if (u_tmp->tx_buf) {
252 k_tmp->tx_buf = buf;
253 if (copy_from_user(buf, (const u8 __user *)
254 (uintptr_t) u_tmp->tx_buf,
255 u_tmp->len))
256 goto done;
257 }
258 buf += k_tmp->len;
259
260 k_tmp->cs_change = !!u_tmp->cs_change;
261 k_tmp->bits_per_word = u_tmp->bits_per_word;
262 k_tmp->delay_usecs = u_tmp->delay_usecs;
263 k_tmp->speed_hz = u_tmp->speed_hz;
264 #ifdef VERBOSE
265 dev_dbg(&spi->dev,
266 " xfer len %zd %s%s%s%dbits %u usec %uHz\n",
267 u_tmp->len,
268 u_tmp->rx_buf ? "rx " : "",
269 u_tmp->tx_buf ? "tx " : "",
270 u_tmp->cs_change ? "cs " : "",
271 u_tmp->bits_per_word ? : spi->bits_per_word,
272 u_tmp->delay_usecs,
273 u_tmp->speed_hz ? : spi->max_speed_hz);
274 #endif
275 spi_message_add_tail(k_tmp, &msg);
276 }
277
278 status = spidev_sync(spidev, &msg);
279 if (status < 0)
280 goto done;
281
282 /* copy any rx data out of bounce buffer */
283 buf = spidev->buffer;
284 for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) {
285 if (u_tmp->rx_buf) {
286 if (__copy_to_user((u8 __user *)
287 (uintptr_t) u_tmp->rx_buf, buf,
288 u_tmp->len)) {
289 status = -EFAULT;
290 goto done;
291 }
292 }
293 buf += u_tmp->len;
294 }
295 status = total;
296
297 done:
298 mutex_unlock(&spidev->buf_lock);
299 kfree(k_xfers);
300 return status;
301 }
302
303 static int
304 spidev_ioctl(struct inode *inode, struct file *filp,
305 unsigned int cmd, unsigned long arg)
306 {
307 int err = 0;
308 int retval = 0;
309 struct spidev_data *spidev;
310 struct spi_device *spi;
311 u32 tmp;
312 unsigned n_ioc;
313 struct spi_ioc_transfer *ioc;
314
315 /* Check type and command number */
316 if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC)
317 return -ENOTTY;
318
319 /* Check access direction once here; don't repeat below.
320 * IOC_DIR is from the user perspective, while access_ok is
321 * from the kernel perspective; so they look reversed.
322 */
323 if (_IOC_DIR(cmd) & _IOC_READ)
324 err = !access_ok(VERIFY_WRITE,
325 (void __user *)arg, _IOC_SIZE(cmd));
326 if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE)
327 err = !access_ok(VERIFY_READ,
328 (void __user *)arg, _IOC_SIZE(cmd));
329 if (err)
330 return -EFAULT;
331
332 /* guard against device removal before, or while,
333 * we issue this ioctl.
334 */
335 spidev = filp->private_data;
336 spin_lock_irq(&spidev->spi_lock);
337 spi = spi_dev_get(spidev->spi);
338 spin_unlock_irq(&spidev->spi_lock);
339
340 if (spi == NULL)
341 return -ESHUTDOWN;
342
343 switch (cmd) {
344 /* read requests */
345 case SPI_IOC_RD_MODE:
346 retval = __put_user(spi->mode & SPI_MODE_MASK,
347 (__u8 __user *)arg);
348 break;
349 case SPI_IOC_RD_LSB_FIRST:
350 retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0,
351 (__u8 __user *)arg);
352 break;
353 case SPI_IOC_RD_BITS_PER_WORD:

354 retval = __put_user(spi->bits_per_word, (__u8 __user *)arg);
355 break;
356 case SPI_IOC_RD_MAX_SPEED_HZ:
357 retval = __put_user(spi->max_speed_hz, (__u32 __user *)arg);
358 break;
359
360 /* write requests */
361 case SPI_IOC_WR_MODE:
362 retval = __get_user(tmp, (u8 __user *)arg);
363 if (retval == 0) {
364 u8 save = spi->mode;
365
366 if (tmp & ~SPI_MODE_MASK) {
367 retval = -EINVAL;
368 break;
369 }
370
371 tmp |= spi->mode & ~SPI_MODE_MASK;
372 spi->mode = (u8)tmp;
373 retval = spi_setup(spi);
374 if (retval < 0)
375 spi->mode = save;
376 else
377 dev_dbg(&spi->dev, "spi mode %02x\n", tmp);
378 }
379 break;
380 case SPI_IOC_WR_LSB_FIRST:
381 retval = __get_user(tmp, (__u8 __user *)arg);
382 if (retval == 0) {
383 u8 save = spi->mode;
384
385 if (tmp)
386 spi->mode |= SPI_LSB_FIRST;
387 else
388 spi->mode &= ~SPI_LSB_FIRST;
389 retval = spi_setup(spi);
390 if (retval < 0)
391 spi->mode = save;
392 else
393 dev_dbg(&spi->dev, "%csb first\n",
394 tmp ? 'l' : 'm');
395 }
396 break;
397 case SPI_IOC_WR_BITS_PER_WORD:
398 retval = __get_user(tmp, (__u8 __user *)arg);
399 if (retval == 0) {
400 u8 save = spi->bits_per_word;
401
402 spi->bits_per_word = tmp;
403 retval = spi_setup(spi);
404 if (retval < 0)
405 spi->bits_per_word = save;
406 else
407 dev_dbg(&spi->dev, "%d bits per word\n", tmp);
408 }
409 break;
410 case SPI_IOC_WR_MAX_SPEED_HZ:
411 retval = __get_user(tmp, (__u32 __user *)arg);
412 if (retval == 0) {
413 u32 save = spi->max_speed_hz;
414
415 spi->max_speed_hz = tmp;
416 retval = spi_setup(spi);
417 if (retval < 0)
418 spi->max_speed_hz = save;
419 else
420 dev_dbg(&spi->dev, "%d Hz (max)\n", tmp);
421 }
422 break;
423
424 default:
425 /* segmented and/or full-duplex I/O request */
426 if (_IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0))
427 || _IOC_DIR(cmd) != _IOC_WRITE) {
428 retval = -ENOTTY;
429 break;
430 }
431
432 tmp = _IOC_SIZE(cmd);
433 if ((tmp % sizeof(struct spi_ioc_transfer)) != 0) {
434 retval = -EINVAL;
435 break;
436 }
437 n_ioc = tmp / sizeof(struct spi_ioc_transfer);
438 if (n_ioc == 0)
439 break;
440
441 /* copy into scratch area */
442 ioc = kmalloc(tmp, GFP_KERNEL);
443 if (!ioc) {
444 retval = -ENOMEM;
445 break;
446 }
447 if (__copy_from_user(ioc, (void __user *)arg, tmp)) {
448 kfree(ioc);
449 retval = -EFAULT;
450 break;
451 }
452
453 /* translate to spi_message, execute */
454 retval = spidev_message(spidev, ioc, n_ioc);
455 kfree(ioc);
456 break;
457 }
458 spi_dev_put(spi);
459 return retval;
460 }
461
462 static int spidev_open(struct inode *inode, struct file *filp)
463 {
464 struct spidev_data *spidev;
465 int status = -ENXIO;
466
467 mutex_lock(&device_list_lock);
468
469 list_for_each_entry(spidev, &device_list, device_entry) {
470 if (spidev->devt == inode->i_rdev) {
471 status = 0;
472 break;
473 }
474 }
475 if (status == 0) {
476 if (!spidev->buffer) {
477 spidev->buffer = kmalloc(bufsiz, GFP_KERNEL);
478 if (!spidev->buffer) {
479 dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");
480 status = -ENOMEM;
481 }
482 }
483 if (status == 0) {
484 spidev->users++;
485 filp->private_data = spidev;
486 nonseekable_open(inode, filp);
487 }
488 } else
489 pr_debug("spidev: nothing for minor %d\n", iminor(inode));
490
491 mutex_unlock(&device_list_lock);
492 return status;
493 }
494
495 static int spidev_release(struct inode *inode, struct file *filp)
496 {
497 struct spidev_data *spidev;
498 int status = 0;
499
500 mutex_lock(&device_list_lock);
501 spidev = filp->private_data;
502 filp->private_data = NULL;
503
504 /* last close? */
505 spidev->users--;
506 if (!spidev->users) {
507 int dofree;
508
509 kfree(spidev->buffer);
510 spidev->buffer = NULL;
511
512 /* ... after we unbound from the underlying device? */
513 spin_lock_irq(&spidev->spi_lock);
514 dofree = (spidev->spi == NULL);
515 spin_unlock_irq(&spidev->spi_lock);
516
517 if (dofree)
518 kfree(spidev);

519 }
520 mutex_unlock(&device_list_lock);
521
522 return status;
523 }
524
525 static struct file_operations spidev_fops = {
526 .owner = THIS_MODULE,
527 /* REVISIT switch to aio primitives, so that userspace
528 * gets more complete API coverage. It'll simplify things
529 * too, except for the locking.
530 */
531 .write = spidev_write,
532 .read = spidev_read,
533 .ioctl = spidev_ioctl,
534 .open = spidev_open,
535 .release = spidev_release,
536 };
537
538 /*-------------------------------------------------------------------------*/
539
540 /* The main reason to have this class is to make mdev/udev create the
541 * /dev/spidevB.C character device nodes exposing our userspace API.
542 * It also simplifies memory management.
543 */
544
545 static struct class *spidev_class;
546
547 /*-------------------------------------------------------------------------*/
548
549 static int spidev_probe(struct spi_device *spi)
550 {
551 struct spidev_data *spidev;
552 int status;
553 unsigned long minor;
554
555 /* Allocate driver data */
556 spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);
557 if (!spidev)
558 return -ENOMEM;
559
560 /* Initialize the driver data */
561 spidev->spi = spi;
562 spin_lock_init(&spidev->spi_lock);
563 mutex_init(&spidev->buf_lock);
564
565 INIT_LIST_HEAD(&spidev->device_entry);
566
567 /* If we can allocate a minor number, hook up this device.
568 * Reusing minors is fine so long as udev or mdev is working.
569 */
570 mutex_lock(&device_list_lock);
571 minor = find_first_zero_bit(minors, N_SPI_MINORS);
572 if (minor < N_SPI_MINORS) {
573 struct device *dev;
574
575 spidev->devt = MKDEV(SPIDEV_MAJOR, minor);
576 dev = device_create(spidev_class, &spi->dev, spidev->devt,
577 "spidev%d.%d",
578 spi->master->bus_num, spi->chip_select);
579 status = IS_ERR(dev) ? PTR_ERR(dev) : 0;
580 } else {
581 dev_dbg(&spi->dev, "no minor number available!\n");
582 status = -ENODEV;
583 }
584 if (status == 0) {
585 set_bit(minor, minors);
586 spi_set_drvdata(spi, spidev);
587 list_add(&spidev->device_entry, &device_list);
588 }
589 mutex_unlock(&device_list_lock);
590
591 if (status != 0)
592 kfree(spidev);
593
594 return status;
595 }
596
597 static int spidev_remove(struct spi_device *spi)
598 {
599 struct spidev_data *spidev = spi_get_drvdata(spi);
600
601 /* make sure ops on existing fds can abort cleanly */
602 spin_lock_irq(&spidev->spi_lock);
603 spidev->spi = NULL;
604 spi_set_drvdata(spi, NULL);
605 spin_unlock_irq(&spidev->spi_lock);
606
607 /* prevent new opens */
608 mutex_lock(&device_list_lock);
609 list_del(&spidev->device_entry);
610 device_destroy(spidev_class, spidev->devt);
611 clear_bit(MINOR(spidev->devt), minors);
612 if (spidev->users == 0)
613 kfree(spidev);
614 mutex_unlock(&device_list_lock);
615
616 return 0;
617 }
618
619 static struct spi_driver spidev_spi = {
620 .driver = {
621 .name = "spidev",
622 .owner = THIS_MODULE,
623 },
624 .probe = spidev_probe,
625 .remove = __devexit_p(spidev_remove),
626
627 /* NOTE: suspend/resume methods are not necessary here.
628 * We don't do anything except pass the requests to/from
629 * the underlying controller. The refrigerator handles
630 * most issues; the controller driver handles the rest.
631 */
632 };
633
634 /*-------------------------------------------------------------------------*/
635
636 static int __init spidev_init(void)
637 {
638 int status;
639
640 /* Claim our 256 reserved device numbers. Then register a class
641 * that will key udev/mdev to add/remove /dev nodes. Last, register
642 * the driver which manages those device numbers.
643 */
644 BUILD_BUG_ON(N_SPI_MINORS > 256);
645 status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops);
646 if (status < 0)
647 return status;
648
649 spidev_class = class_create(THIS_MODULE, "spidev");
650 if (IS_ERR(spidev_class)) {
651 unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);
652 return PTR_ERR(spidev_class);
653 }
654
655 status = spi_register_driver(&spidev_spi);
656 if (status < 0) {
657 class_destroy(spidev_class);
658 unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);
659 }
660 return status;
661 }
662 module_init(spidev_init);
663
664 static void __exit spidev_exit(void)
665 {
666 spi_unregister_driver(&spidev_spi);
667 class_destroy(spidev_class);
668 unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);
669 }
670 module_exit(spidev_exit);
671
672 MODULE_AUTHOR("Andrea Paterniani, <a.paterniani@swapp-eng.it>");
673 MODULE_DESCRIPTION("User mode SPI device interface");
674 MODULE_LICENSE("GPL");
675
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Where is a PCI module's Probe function called? jbreaka4lyfe Linux - General 2 05-18-2010 03:07 AM
Probe hardware yusufs Linux - Newbie 2 03-10-2008 02:39 AM
probe method on bus and device driver not being called kunice Linux - Hardware 0 02-24-2008 11:47 AM
USB Driver Probe function not being called xtom Fedora 0 10-28-2005 03:48 PM
Monitor re-probe? mike_loux Fedora 1 01-28-2004 11:06 AM


All times are GMT -5. The time now is 12:53 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration