Firefly开源社区

前一段时间购买了AIO-RK3288J主板,编写驱动模块遇到如下问题

35

积分

0

威望

0

贡献

技术小白

积分
35
发表于 2020-12-2 14:13:18     
1.编译好AIO-RK3288J板的SDK,并下载到板子上,板子可以正常启动。
2.创建mydriver目录,编写Makefile代码如下:
CROSS_COMPLE:=arm-linux-gnueabihf-
ARCH:=arm
CC:=$(CROSS_COMPILE)gcc
LD:=$(CROSS_COMPILE)ld

obj-m := spi-nfc-fm175xx.o
module-objs = spi-nfc-fm175xx.o leds-aw2013.o

KDIR := /home/xk/firefly-rk3288-linux/kernel
PWD := $(shell pwd)
defaule:
        make -C $(KDIR) M=$(PWD) modules ARCH=arm


clean:
        rm -f *.ko *.o *.mod.c *.symvers
3.编写模块代码如下:
#include <linux/init.h>
#include <linux/module.h>

static int __init spi_fm175xx_init(void)
{
        printk("insmod success!\n");
        return 0;
}
module_init(spi_fm175xx_init);

static void __exit spi_fm175xx_exit(void)
{
        printk("rmmod success!\n");
}
module_exit(spi_fm175xx_exit);

MODULE_AUTHOR("WJ Wang <wangwenjun@inmyshow.com>");
MODULE_DESCRIPTION("IMS NFC FM175XX Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("spi:fm175xx");
4.但是目前下载到板子里面,用insmod命令装载后,printk没有打印log信息。
回复

使用道具 举报

35

积分

0

威望

0

贡献

技术小白

积分
35
发表于 2020-12-2 14:17:34     
也就是说__init和__exit没有执行
回复

使用道具 举报

708

积分

0

威望

0

贡献

技术大神

Rank: 3Rank: 3

积分
708
发表于 2020-12-2 15:10:34     
dmesg 看看
回复

使用道具 举报

35

积分

0

威望

0

贡献

技术小白

积分
35
发表于 2020-12-2 18:06:17     
我查了一下,是printk打印等级不够,使用echo 7 >  /proc/sys/kernel/printk可以解决这个问题,但是probe函数里的printk也打印不出来不知道该怎么解决?
回复

使用道具 举报

35

积分

0

威望

0

贡献

技术小白

积分
35
发表于 2020-12-2 18:09:23     
[ 本帖最后由 八龄先生 于 2020-12-2 18:12 编辑 ]\n\n完全用官方的 spidev.c文件改的,只是在,__init(),     __exit,     probe函数里面添加了几条printk,怎么能看到打印信息呢?有没有更改默认printk权限的方式?

  1. /*
  2. * Simple synchronous userspace interface to SPI devices
  3. *
  4. * Copyright (C) 2006 SWAPP
  5. *        Andrea Paterniani <a.paterniani@swapp-eng.it>
  6. * Copyright (C) 2007 David Brownell (simplification, cleanup)
  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. #include <linux/init.h>
  19. #include <linux/module.h>
  20. #include <linux/ioctl.h>
  21. #include <linux/fs.h>
  22. #include <linux/device.h>
  23. #include <linux/err.h>
  24. #include <linux/list.h>
  25. #include <linux/errno.h>
  26. #include <linux/mutex.h>
  27. #include <linux/slab.h>
  28. #include <linux/compat.h>
  29. #include <linux/of.h>
  30. #include <linux/of_device.h>
  31. #include <linux/spi/spi.h>
  32. #include <linux/spi/spidev.h>
  33. #include <linux/uaccess.h>


  34. /*
  35. * This supports access to SPI devices using normal userspace I/O calls.
  36. * Note that while traditional UNIX/POSIX I/O semantics are half duplex,
  37. * and often mask message boundaries, full SPI support requires full duplex
  38. * transfers.  There are several kinds of internal message boundaries to
  39. * handle chipselect management and other protocol options.
  40. *
  41. * SPI has a character major number assigned.  We allocate minor numbers
  42. * dynamically using a bitmask.  You must use hotplug tools, such as udev
  43. * (or mdev with busybox) to create and destroy the /dev/spidevB.C device
  44. * nodes, since there is no fixed association of minor numbers with any
  45. * particular SPI bus or device.
  46. */
  47. #define SPIDEV_MAJOR                        153        /* assigned */
  48. #define N_SPI_MINORS                        32        /* ... up to 256 */

  49. static DECLARE_BITMAP(minors, N_SPI_MINORS);


  50. /* Bit masks for spi_device.mode management.  Note that incorrect
  51. * settings for some settings can cause *lots* of trouble for other
  52. * devices on a shared bus:
  53. *
  54. *  - CS_HIGH ... this device will be active when it shouldn't be
  55. *  - 3WIRE ... when active, it won't behave as it should
  56. *  - NO_CS ... there will be no explicit message boundaries; this
  57. *        is completely incompatible with the shared bus model
  58. *  - READY ... transfers may proceed when they shouldn't.
  59. *
  60. * REVISIT should changing those flags be privileged?
  61. */
  62. #define SPI_MODE_MASK                (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \
  63.                                 | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \
  64.                                 | SPI_NO_CS | SPI_READY | SPI_TX_DUAL \
  65.                                 | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)

  66. struct spidev_data {
  67.         dev_t                        devt;
  68.         spinlock_t                spi_lock;
  69.         struct spi_device        *spi;
  70.         struct list_head        device_entry;

  71.         /* TX/RX buffers are NULL unless this device is open (users > 0) */
  72.         struct mutex                buf_lock;
  73.         unsigned                users;
  74.         u8                        *tx_buffer;
  75.         u8                        *rx_buffer;
  76.         u32                        speed_hz;
  77. };

  78. static LIST_HEAD(device_list);
  79. static DEFINE_MUTEX(device_list_lock);

  80. static unsigned bufsiz = 4096;
  81. module_param(bufsiz, uint, S_IRUGO);
  82. MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message");

  83. /*-------------------------------------------------------------------------*/

  84. static ssize_t
  85. spidev_sync(struct spidev_data *spidev, struct spi_message *message)
  86. {
  87.         DECLARE_COMPLETION_ONSTACK(done);
  88.         int status;
  89.         struct spi_device *spi;

  90.         spin_lock_irq(&spidev->spi_lock);
  91.         spi = spidev->spi;
  92.         spin_unlock_irq(&spidev->spi_lock);

  93.         if (spi == NULL)
  94.                 status = -ESHUTDOWN;
  95.         else
  96.                 status = spi_sync(spi, message);

  97.         if (status == 0)
  98.                 status = message->actual_length;

  99.         return status;
  100. }

  101. static inline ssize_t
  102. spidev_sync_write(struct spidev_data *spidev, size_t len)
  103. {
  104.         struct spi_transfer        t = {
  105.                         .tx_buf                = spidev->tx_buffer,
  106.                         .len                = len,
  107.                         .speed_hz        = spidev->speed_hz,
  108.                 };
  109.         struct spi_message        m;

  110.         spi_message_init(&m);
  111.         spi_message_add_tail(&t, &m);
  112.         return spidev_sync(spidev, &m);
  113. }

  114. static inline ssize_t
  115. spidev_sync_read(struct spidev_data *spidev, size_t len)
  116. {
  117.         struct spi_transfer        t = {
  118.                         .rx_buf                = spidev->rx_buffer,
  119.                         .len                = len,
  120.                         .speed_hz        = spidev->speed_hz,
  121.                 };
  122.         struct spi_message        m;

  123.         spi_message_init(&m);
  124.         spi_message_add_tail(&t, &m);
  125.         return spidev_sync(spidev, &m);
  126. }

  127. /*-------------------------------------------------------------------------*/

  128. /* Read-only message with current device setup */
  129. static ssize_t
  130. spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
  131. {
  132.         struct spidev_data        *spidev;
  133.         ssize_t                        status = 0;

  134.         /* chipselect only toggles at start or end of operation */
  135.         if (count > bufsiz)
  136.                 return -EMSGSIZE;

  137.         spidev = filp->private_data;

  138.         mutex_lock(&spidev->buf_lock);
  139.         status = spidev_sync_read(spidev, count);
  140.         if (status > 0) {
  141.                 unsigned long        missing;

  142.                 missing = copy_to_user(buf, spidev->rx_buffer, status);
  143.                 if (missing == status)
  144.                         status = -EFAULT;
  145.                 else
  146.                         status = status - missing;
  147.         }
  148.         mutex_unlock(&spidev->buf_lock);

  149.         return status;
  150. }

  151. /* Write-only message with current device setup */
  152. static ssize_t
  153. spidev_write(struct file *filp, const char __user *buf,
  154.                 size_t count, loff_t *f_pos)
  155. {
  156.         struct spidev_data        *spidev;
  157.         ssize_t                        status = 0;
  158.         unsigned long                missing;

  159.         /* chipselect only toggles at start or end of operation */
  160.         if (count > bufsiz)
  161.                 return -EMSGSIZE;

  162.         spidev = filp->private_data;

  163.         mutex_lock(&spidev->buf_lock);
  164.         missing = copy_from_user(spidev->tx_buffer, buf, count);
  165.         if (missing == 0)
  166.                 status = spidev_sync_write(spidev, count);
  167.         else
  168.                 status = -EFAULT;
  169.         mutex_unlock(&spidev->buf_lock);

  170.         return status;
  171. }

  172. static int spidev_message(struct spidev_data *spidev,
  173.                 struct spi_ioc_transfer *u_xfers, unsigned n_xfers)
  174. {
  175.         struct spi_message        msg;
  176.         struct spi_transfer        *k_xfers;
  177.         struct spi_transfer        *k_tmp;
  178.         struct spi_ioc_transfer *u_tmp;
  179.         unsigned                n, total, tx_total, rx_total;
  180.         u8                        *tx_buf, *rx_buf;
  181.         int                        status = -EFAULT;

  182.         spi_message_init(&msg);
  183.         k_xfers = kcalloc(n_xfers, sizeof(*k_tmp), GFP_KERNEL);
  184.         if (k_xfers == NULL)
  185.                 return -ENOMEM;

  186.         /* Construct spi_message, copying any tx data to bounce buffer.
  187.          * We walk the array of user-provided transfers, using each one
  188.          * to initialize a kernel version of the same transfer.
  189.          */
  190.         tx_buf = spidev->tx_buffer;
  191.         rx_buf = spidev->rx_buffer;
  192.         total = 0;
  193.         tx_total = 0;
  194.         rx_total = 0;
  195.         for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;
  196.                         n;
  197.                         n--, k_tmp++, u_tmp++) {
  198.                 k_tmp->len = u_tmp->len;

  199.                 total += k_tmp->len;
  200.                 /* Since the function returns the total length of transfers
  201.                  * on success, restrict the total to positive int values to
  202.                  * avoid the return value looking like an error.  Also check
  203.                  * each transfer length to avoid arithmetic overflow.
  204.                  */
  205.                 if (total > INT_MAX || k_tmp->len > INT_MAX) {
  206.                         status = -EMSGSIZE;
  207.                         goto done;
  208.                 }

  209.                 if (u_tmp->rx_buf) {
  210.                         /* this transfer needs space in RX bounce buffer */
  211.                         rx_total += k_tmp->len;
  212.                         if (rx_total > bufsiz) {
  213.                                 status = -EMSGSIZE;
  214.                                 goto done;
  215.                         }
  216.                         k_tmp->rx_buf = rx_buf;
  217.                         if (!access_ok(VERIFY_WRITE, (u8 __user *)
  218.                                                 (uintptr_t) u_tmp->rx_buf,
  219.                                                 u_tmp->len))
  220.                                 goto done;
  221.                         rx_buf += k_tmp->len;
  222.                 }
  223.                 if (u_tmp->tx_buf) {
  224.                         /* this transfer needs space in TX bounce buffer */
  225.                         tx_total += k_tmp->len;
  226.                         if (tx_total > bufsiz) {
  227.                                 status = -EMSGSIZE;
  228.                                 goto done;
  229.                         }
  230.                         k_tmp->tx_buf = tx_buf;
  231.                         if (copy_from_user(tx_buf, (const u8 __user *)
  232.                                                 (uintptr_t) u_tmp->tx_buf,
  233.                                         u_tmp->len))
  234.                                 goto done;
  235.                         tx_buf += k_tmp->len;
  236.                 }

  237.                 k_tmp->cs_change = !!u_tmp->cs_change;
  238.                 k_tmp->tx_nbits = u_tmp->tx_nbits;
  239.                 k_tmp->rx_nbits = u_tmp->rx_nbits;
  240.                 k_tmp->bits_per_word = u_tmp->bits_per_word;
  241.                 k_tmp->delay_usecs = u_tmp->delay_usecs;
  242.                 k_tmp->speed_hz = u_tmp->speed_hz;
  243.                 if (!k_tmp->speed_hz)
  244.                         k_tmp->speed_hz = spidev->speed_hz;
  245. #ifdef VERBOSE
  246.                 dev_dbg(&spidev->spi->dev,
  247.                         "  xfer len %zd %s%s%s%dbits %u usec %uHz\n",
  248.                         u_tmp->len,
  249.                         u_tmp->rx_buf ? "rx " : "",
  250.                         u_tmp->tx_buf ? "tx " : "",
  251.                         u_tmp->cs_change ? "cs " : "",
  252.                         u_tmp->bits_per_word ? : spidev->spi->bits_per_word,
  253.                         u_tmp->delay_usecs,
  254.                         u_tmp->speed_hz ? : spidev->spi->max_speed_hz);
  255. #endif
  256.                 spi_message_add_tail(k_tmp, &msg);
  257.         }

  258.         status = spidev_sync(spidev, &msg);
  259.         if (status < 0)
  260.                 goto done;

  261.         /* copy any rx data out of bounce buffer */
  262.         rx_buf = spidev->rx_buffer;
  263.         for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) {
  264.                 if (u_tmp->rx_buf) {
  265.                         if (__copy_to_user((u8 __user *)
  266.                                         (uintptr_t) u_tmp->rx_buf, rx_buf,
  267.                                         u_tmp->len)) {
  268.                                 status = -EFAULT;
  269.                                 goto done;
  270.                         }
  271.                         rx_buf += u_tmp->len;
  272.                 }
  273.         }
  274.         status = total;

  275. done:
  276.         kfree(k_xfers);
  277.         return status;
  278. }

  279. static struct spi_ioc_transfer *spidev_get_ioc_message(unsigned int cmd, struct spi_ioc_transfer __user *u_ioc,
  280.                 unsigned *n_ioc)
  281. {
  282.         struct spi_ioc_transfer        *ioc;
  283.         u32        tmp;

  284.         /* Check type, command number and direction */
  285.         if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC
  286.                         || _IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0))
  287.                         || _IOC_DIR(cmd) != _IOC_WRITE)
  288.                 return ERR_PTR(-ENOTTY);

  289.         tmp = _IOC_SIZE(cmd);
  290.         if ((tmp % sizeof(struct spi_ioc_transfer)) != 0)
  291.                 return ERR_PTR(-EINVAL);
  292.         *n_ioc = tmp / sizeof(struct spi_ioc_transfer);
  293.         if (*n_ioc == 0)
  294.                 return NULL;

  295.         /* copy into scratch area */
  296.         ioc = kmalloc(tmp, GFP_KERNEL);
  297.         if (!ioc)
  298.                 return ERR_PTR(-ENOMEM);
  299.         if (__copy_from_user(ioc, u_ioc, tmp)) {
  300.                 kfree(ioc);
  301.                 return ERR_PTR(-EFAULT);
  302.         }
  303.         return ioc;
  304. }

  305. static long spidev_ioctl(struct file *filp, 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.         /* Check type and command number */
  315.         if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC)
  316.                 return -ENOTTY;

  317.         /* Check access direction once here; don't repeat below.
  318.          * IOC_DIR is from the user perspective, while access_ok is
  319.          * from the kernel perspective; so they look reversed.
  320.          */
  321.         if (_IOC_DIR(cmd) & _IOC_READ)
  322.                 err = !access_ok(VERIFY_WRITE,
  323.                                 (void __user *)arg, _IOC_SIZE(cmd));
  324.         if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE)
  325.                 err = !access_ok(VERIFY_READ,
  326.                                 (void __user *)arg, _IOC_SIZE(cmd));
  327.         if (err)
  328.                 return -EFAULT;

  329.         /* guard against device removal before, or while,
  330.          * we issue this ioctl.
  331.          */
  332.         spidev = filp->private_data;
  333.         spin_lock_irq(&spidev->spi_lock);
  334.         spi = spi_dev_get(spidev->spi);
  335.         spin_unlock_irq(&spidev->spi_lock);

  336.         if (spi == NULL)
  337.                 return -ESHUTDOWN;

  338.         /* use the buffer lock here for triple duty:
  339.          *  - prevent I/O (from us) so calling spi_setup() is safe;
  340.          *  - prevent concurrent SPI_IOC_WR_* from morphing
  341.          *    data fields while SPI_IOC_RD_* reads them;
  342.          *  - SPI_IOC_MESSAGE needs the buffer locked "normally".
  343.          */
  344.         mutex_lock(&spidev->buf_lock);

  345.         switch (cmd) {
  346.         /* read requests */
  347.         case SPI_IOC_RD_MODE:
  348.                 retval = __put_user(spi->mode & SPI_MODE_MASK,
  349.                                         (__u8 __user *)arg);
  350.                 break;
  351.         case SPI_IOC_RD_MODE32:
  352.                 retval = __put_user(spi->mode & SPI_MODE_MASK,
  353.                                         (__u32 __user *)arg);
  354.                 break;
  355.         case SPI_IOC_RD_LSB_FIRST:
  356.                 retval = __put_user((spi->mode & SPI_LSB_FIRST) ?  1 : 0,
  357.                                         (__u8 __user *)arg);
  358.                 break;
  359.         case SPI_IOC_RD_BITS_PER_WORD:
  360.                 retval = __put_user(spi->bits_per_word, (__u8 __user *)arg);
  361.                 break;
  362.         case SPI_IOC_RD_MAX_SPEED_HZ:
  363.                 retval = __put_user(spidev->speed_hz, (__u32 __user *)arg);
  364.                 break;

  365.         /* write requests */
  366.         case SPI_IOC_WR_MODE:
  367.         case SPI_IOC_WR_MODE32:
  368.                 if (cmd == SPI_IOC_WR_MODE)
  369.                         retval = __get_user(tmp, (u8 __user *)arg);
  370.                 else
  371.                         retval = __get_user(tmp, (u32 __user *)arg);
  372.                 if (retval == 0) {
  373.                         u32        save = spi->mode;

  374.                         if (tmp & ~SPI_MODE_MASK) {
  375.                                 retval = -EINVAL;
  376.                                 break;
  377.                         }

  378.                         tmp |= spi->mode & ~SPI_MODE_MASK;
  379.                         spi->mode = (u16)tmp;
  380.                         retval = spi_setup(spi);
  381.                         if (retval < 0)
  382.                                 spi->mode = save;
  383.                         else
  384.                                 dev_dbg(&spi->dev, "spi mode %x\n", tmp);
  385.                 }
  386.                 break;
  387.         case SPI_IOC_WR_LSB_FIRST:
  388.                 retval = __get_user(tmp, (__u8 __user *)arg);
  389.                 if (retval == 0) {
  390.                         u32        save = spi->mode;

  391.                         if (tmp)
  392.                                 spi->mode |= SPI_LSB_FIRST;
  393.                         else
  394.                                 spi->mode &= ~SPI_LSB_FIRST;
  395.                         retval = spi_setup(spi);
  396.                         if (retval < 0)
  397.                                 spi->mode = save;
  398.                         else
  399.                                 dev_dbg(&spi->dev, "%csb first\n",
  400.                                                 tmp ? 'l' : 'm');
  401.                 }
  402.                 break;
  403.         case SPI_IOC_WR_BITS_PER_WORD:
  404.                 retval = __get_user(tmp, (__u8 __user *)arg);
  405.                 if (retval == 0) {
  406.                         u8        save = spi->bits_per_word;

  407.                         spi->bits_per_word = tmp;
  408.                         retval = spi_setup(spi);
  409.                         if (retval < 0)
  410.                                 spi->bits_per_word = save;
  411.                         else
  412.                                 dev_dbg(&spi->dev, "%d bits per word\n", tmp);
  413.                 }
  414.                 break;
  415.         case SPI_IOC_WR_MAX_SPEED_HZ:
  416.                 retval = __get_user(tmp, (__u32 __user *)arg);
  417.                 if (retval == 0) {
  418.                         u32        save = spi->max_speed_hz;

  419.                         spi->max_speed_hz = tmp;
  420.                         retval = spi_setup(spi);
  421.                         if (retval >= 0)
  422.                                 spidev->speed_hz = tmp;
  423.                         else
  424.                                 dev_dbg(&spi->dev, "%d Hz (max)\n", tmp);
  425.                         spi->max_speed_hz = save;
  426.                 }
  427.                 break;

  428.         default:
  429.                 /* segmented and/or full-duplex I/O request */
  430.                 /* Check message and copy into scratch area */
  431.                 ioc = spidev_get_ioc_message(cmd,
  432.                                 (struct spi_ioc_transfer __user *)arg, &n_ioc);
  433.                 if (IS_ERR(ioc)) {
  434.                         retval = PTR_ERR(ioc);
  435.                         break;
  436.                 }
  437.                 if (!ioc)
  438.                         break;        /* n_ioc is also 0 */

  439.                 /* translate to spi_message, execute */
  440.                 retval = spidev_message(spidev, ioc, n_ioc);
  441.                 kfree(ioc);
  442.                 break;
  443.         }

  444.         mutex_unlock(&spidev->buf_lock);
  445.         spi_dev_put(spi);
  446.         return retval;
  447. }

  448. #ifdef CONFIG_COMPAT
  449. static long
  450. spidev_compat_ioc_message(struct file *filp, unsigned int cmd,
  451.                 unsigned long arg)
  452. {
  453.         struct spi_ioc_transfer __user        *u_ioc;
  454.         int                                retval = 0;
  455.         struct spidev_data                *spidev;
  456.         struct spi_device                *spi;
  457.         unsigned                        n_ioc, n;
  458.         struct spi_ioc_transfer                *ioc;

  459.         u_ioc = (struct spi_ioc_transfer __user *) compat_ptr(arg);
  460.         if (!access_ok(VERIFY_READ, u_ioc, _IOC_SIZE(cmd)))
  461.                 return -EFAULT;

  462.         /* guard against device removal before, or while,
  463.          * we issue this ioctl.
  464.          */
  465.         spidev = filp->private_data;
  466.         spin_lock_irq(&spidev->spi_lock);
  467.         spi = spi_dev_get(spidev->spi);
  468.         spin_unlock_irq(&spidev->spi_lock);

  469.         if (spi == NULL)
  470.                 return -ESHUTDOWN;

  471.         /* SPI_IOC_MESSAGE needs the buffer locked "normally" */
  472.         mutex_lock(&spidev->buf_lock);

  473.         /* Check message and copy into scratch area */
  474.         ioc = spidev_get_ioc_message(cmd, u_ioc, &n_ioc);
  475.         if (IS_ERR(ioc)) {
  476.                 retval = PTR_ERR(ioc);
  477.                 goto done;
  478.         }
  479.         if (!ioc)
  480.                 goto done;        /* n_ioc is also 0 */

  481.         /* Convert buffer pointers */
  482.         for (n = 0; n < n_ioc; n++) {
  483.                 ioc[n].rx_buf = (uintptr_t) compat_ptr(ioc[n].rx_buf);
  484.                 ioc[n].tx_buf = (uintptr_t) compat_ptr(ioc[n].tx_buf);
  485.         }

  486.         /* translate to spi_message, execute */
  487.         retval = spidev_message(spidev, ioc, n_ioc);
  488.         kfree(ioc);

  489. done:
  490.         mutex_unlock(&spidev->buf_lock);
  491.         spi_dev_put(spi);
  492.         return retval;
  493. }

  494. static long
  495. spidev_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  496. {
  497.         if (_IOC_TYPE(cmd) == SPI_IOC_MAGIC
  498.                         && _IOC_NR(cmd) == _IOC_NR(SPI_IOC_MESSAGE(0))
  499.                         && _IOC_DIR(cmd) == _IOC_WRITE)
  500.                 return spidev_compat_ioc_message(filp, cmd, arg);

  501.         return spidev_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
  502. }
  503. #else
  504. #define spidev_compat_ioctl NULL
  505. #endif /* CONFIG_COMPAT */

  506. static int spidev_open(struct inode *inode, struct file *filp)
  507. {
  508.         struct spidev_data        *spidev;
  509.         int                        status = -ENXIO;

  510.         mutex_lock(&device_list_lock);

  511.         list_for_each_entry(spidev, &device_list, device_entry) {
  512.                 if (spidev->devt == inode->i_rdev) {
  513.                         status = 0;
  514.                         break;
  515.                 }
  516.         }

  517.         if (status) {
  518.                 pr_debug("spidev: nothing for minor %d\n", iminor(inode));
  519.                 goto err_find_dev;
  520.         }

  521.         if (!spidev->tx_buffer) {
  522.                 spidev->tx_buffer = kmalloc(bufsiz, GFP_KERNEL);
  523.                 if (!spidev->tx_buffer) {
  524.                         dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");
  525.                         status = -ENOMEM;
  526.                         goto err_find_dev;
  527.                 }
  528.         }

  529.         if (!spidev->rx_buffer) {
  530.                 spidev->rx_buffer = kmalloc(bufsiz, GFP_KERNEL);
  531.                 if (!spidev->rx_buffer) {
  532.                         dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");
  533.                         status = -ENOMEM;
  534.                         goto err_alloc_rx_buf;
  535.                 }
  536.         }

  537.         spidev->users++;
  538.         filp->private_data = spidev;
  539.         nonseekable_open(inode, filp);

  540.         mutex_unlock(&device_list_lock);
  541.         return 0;

  542. err_alloc_rx_buf:
  543.         kfree(spidev->tx_buffer);
  544.         spidev->tx_buffer = NULL;
  545. err_find_dev:
  546.         mutex_unlock(&device_list_lock);
  547.         return status;
  548. }

  549. static int spidev_release(struct inode *inode, struct file *filp)
  550. {
  551.         struct spidev_data        *spidev;

  552.         mutex_lock(&device_list_lock);
  553.         spidev = filp->private_data;
  554.         filp->private_data = NULL;

  555.         /* last close? */
  556.         spidev->users--;
  557.         if (!spidev->users) {
  558.                 int                dofree;

  559.                 kfree(spidev->tx_buffer);
  560.                 spidev->tx_buffer = NULL;

  561.                 kfree(spidev->rx_buffer);
  562.                 spidev->rx_buffer = NULL;

  563.                 spin_lock_irq(&spidev->spi_lock);
  564.                 if (spidev->spi)
  565.                         spidev->speed_hz = spidev->spi->max_speed_hz;

  566.                 /* ... after we unbound from the underlying device? */
  567.                 dofree = (spidev->spi == NULL);
  568.                 spin_unlock_irq(&spidev->spi_lock);

  569.                 if (dofree)
  570.                         kfree(spidev);
  571.         }
  572.         mutex_unlock(&device_list_lock);

  573.         return 0;
  574. }

  575. static const struct file_operations spidev_fops = {
  576.         .owner =        THIS_MODULE,
  577.         /* REVISIT switch to aio primitives, so that userspace
  578.          * gets more complete API coverage.  It'll simplify things
  579.          * too, except for the locking.
  580.          */
  581.         .write =        spidev_write,
  582.         .read =                spidev_read,
  583.         .unlocked_ioctl = spidev_ioctl,
  584.         .compat_ioctl = spidev_compat_ioctl,
  585.         .open =                spidev_open,
  586.         .release =        spidev_release,
  587.         .llseek =        no_llseek,
  588. };

  589. /*-------------------------------------------------------------------------*/

  590. /* The main reason to have this class is to make mdev/udev create the
  591. * /dev/spidevB.C character device nodes exposing our userspace API.
  592. * It also simplifies memory management.
  593. */

  594. static struct class *spidev_class;

  595. //#ifdef CONFIG_OF
  596. static const struct of_device_id fm175xx_dt_ids[] = {
  597.         { .compatible = "fdw,nfc_fm175xx" },
  598.         {},
  599. };
  600. MODULE_DEVICE_TABLE(of, fm175xx_dt_ids);
  601. //#endif

  602. /*-------------------------------------------------------------------------*/

  603. static int fm175xx_probe(struct spi_device *spi)
  604. {
  605.         struct spidev_data        *spidev;
  606.         int                        status;
  607.         unsigned long                minor;

  608.         /*
  609.          * spidev should never be referenced in DT without a specific
  610.          * compatible string, it is a Linux implementation thing
  611.          * rather than a description of the hardware.
  612.          */
  613.         if (spi->dev.of_node && !of_match_device(fm175xx_dt_ids, &spi->dev)) {
  614.                 dev_err(&spi->dev, "buggy DT: spidev listed directly in DT\n");
  615.                 WARN_ON(spi->dev.of_node &&
  616.                         !of_match_device(fm175xx_dt_ids, &spi->dev));
  617.         }

  618.         printk("probe function successful!\n");

  619.         /* Allocate driver data */
  620.         spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);
  621.         if (!spidev)
  622.                 return -ENOMEM;

  623.         /* Initialize the driver data */
  624.         spidev->spi = spi;
  625.         spin_lock_init(&spidev->spi_lock);
  626.         mutex_init(&spidev->buf_lock);

  627.         INIT_LIST_HEAD(&spidev->device_entry);

  628.         /* If we can allocate a minor number, hook up this device.
  629.          * Reusing minors is fine so long as udev or mdev is working.
  630.          */
  631.         mutex_lock(&device_list_lock);
  632.         minor = find_first_zero_bit(minors, N_SPI_MINORS);
  633.         if (minor < N_SPI_MINORS) {
  634.                 struct device *dev;

  635.                 spidev->devt = MKDEV(SPIDEV_MAJOR, minor);
  636.                 dev = device_create(spidev_class, &spi->dev, spidev->devt,
  637.                                     spidev, "spidev%d.%d",
  638.                                     spi->master->bus_num, spi->chip_select);
  639.                 status = PTR_ERR_OR_ZERO(dev);
  640.         } else {
  641.                 dev_dbg(&spi->dev, "no minor number available!\n");
  642.                 status = -ENODEV;
  643.         }
  644.         if (status == 0) {
  645.                 set_bit(minor, minors);
  646.                 list_add(&spidev->device_entry, &device_list);
  647.         }
  648.         mutex_unlock(&device_list_lock);

  649.         spidev->speed_hz = spi->max_speed_hz;

  650.         if (status == 0)
  651.                 spi_set_drvdata(spi, spidev);
  652.         else
  653.                 kfree(spidev);

  654.         return status;
  655. }

  656. static int fm175xx_remove(struct spi_device *spi)
  657. {
  658.         struct spidev_data        *spidev = spi_get_drvdata(spi);

  659.         /* make sure ops on existing fds can abort cleanly */
  660.         spin_lock_irq(&spidev->spi_lock);
  661.         spidev->spi = NULL;
  662.         spin_unlock_irq(&spidev->spi_lock);

  663.         /* prevent new opens */
  664.         mutex_lock(&device_list_lock);
  665.         list_del(&spidev->device_entry);
  666.         device_destroy(spidev_class, spidev->devt);
  667.         clear_bit(MINOR(spidev->devt), minors);
  668.         if (spidev->users == 0)
  669.                 kfree(spidev);
  670.         mutex_unlock(&device_list_lock);

  671.         return 0;
  672. }

  673. static struct spi_driver spidev_spi_driver = {
  674.         .driver = {
  675.                 .name =                "fdw,nfc_fm175xx",
  676.                 .of_match_table = of_match_ptr(fm175xx_dt_ids),
  677.         },
  678.         .probe =        fm175xx_probe,
  679.         .remove =        fm175xx_remove,

  680.         /* NOTE:  suspend/resume methods are not necessary here.
  681.          * We don't do anything except pass the requests to/from
  682.          * the underlying controller.  The refrigerator handles
  683.          * most issues; the controller driver handles the rest.
  684.          */
  685. };

  686. /*-------------------------------------------------------------------------*/

  687. static int __init spidev_init(void)
  688. {
  689.         int status;

  690.         /* Claim our 256 reserved device numbers.  Then register a class
  691.          * that will key udev/mdev to add/remove /dev nodes.  Last, register
  692.          * the driver which manages those device numbers.
  693.          */
  694.         BUILD_BUG_ON(N_SPI_MINORS > 256);
  695.         status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops);
  696.         if (status < 0)
  697.                 return status;

  698.         spidev_class = class_create(THIS_MODULE, "spidev");
  699.         if (IS_ERR(spidev_class)) {
  700.                 unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
  701.                 return PTR_ERR(spidev_class);
  702.         }

  703.         status = spi_register_driver(&spidev_spi_driver);
  704.         if (status < 0) {
  705.                 class_destroy(spidev_class);
  706.                 unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
  707.         }
  708.         printk("spi module init successful.\n");

  709.         return status;
  710. }
  711. module_init(spidev_init);

  712. static void __exit spidev_exit(void)
  713. {
  714.         spi_unregister_driver(&spidev_spi_driver);
  715.         class_destroy(spidev_class);
  716.         unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
  717.         printk("spi module exit successful.\n");
  718. }
  719. module_exit(spidev_exit);

  720. MODULE_AUTHOR("WJ wang<wangwenjun@inmyshow.com>");
  721. MODULE_DESCRIPTION("User mode nfc fm175xx interface");
  722. MODULE_LICENSE("GPL");
复制代码


回复

使用道具 举报

708

积分

0

威望

0

贡献

技术大神

Rank: 3Rank: 3

积分
708
发表于 2020-12-3 09:24:54     
- 一般 dmesg 或 cat /var/log/kern.log 就可以了
- 网上有很多说明的,https://www.cnblogs.com/slz-coder150315/p/4376398.html
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

友情链接 : 爱板网 电子发烧友论坛 云汉电子社区 粤ICP备14022046号-2
快速回复 返回顶部 返回列表