1. 程式人生 > >Linux spi驅動分析(三)----spiddev分析

Linux spi驅動分析(三)----spiddev分析

  1. static long
  2. spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  3. {
  4.     int            err = 0;
  5.     int            retval = 0;
  6.     struct spidev_data    *spidev;
  7.     struct spi_device    *spi;
  8.     u32            tmp;
  9.     unsigned        n_ioc;
  10.     struct spi_ioc_transfer    *ioc;
  11.     /* Check type and
    command number */
  12.     if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC)
  13.         return -ENOTTY;
  14.     /* Check access direction once here; don't repeat below.
  15.      * IOC_DIR is from the user perspective, while access_ok is
  16.      * from the kernel perspective; so they look reversed.
  17.      */
  18.     if (_IOC_DIR(cmd) & _IOC_READ)

  19.         err = !access_ok(VERIFY_WRITE,
  20.                 (void __user *)arg, _IOC_SIZE(cmd));
  21.     if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE)
  22.         err = !access_ok(VERIFY_READ,
  23.                 (void __user *)arg, _IOC_SIZE(cmd));
  24.     if (err)
  25.         return -EFAULT;
  26.     /* guard against device removal before,
    or while,
  27.      * we issue this ioctl.
  28.      */
  29.     spidev = filp->private_data;
  30.     spin_lock_irq(&spidev->spi_lock);
  31.     spi = spi_dev_get(spidev->spi);
  32.     spin_unlock_irq(&spidev->spi_lock);
  33.     if (spi == NULL)
  34.         return -ESHUTDOWN;
  35.     /* use the buffer lock here for triple duty:
  36.      * - prevent I/O (from us) so calling spi_setup() is safe;
  37.      * - prevent concurrent SPI_IOC_WR_* from morphing
  38.      * data fields while SPI_IOC_RD_* reads them;
  39.      * - SPI_IOC_MESSAGE needs the buffer locked "normally".
  40.      */
  41.     mutex_lock(&spidev->buf_lock);
  42.     switch (cmd) {
  43.     /* read requests */
  44.     case SPI_IOC_RD_MODE:
  45.         retval = __put_user(spi->mode & SPI_MODE_MASK,
  46.                     (__u8 __user *)arg);
  47.         break;
  48.     case SPI_IOC_RD_LSB_FIRST:
  49.         retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0,
  50.                     (__u8 __user *)arg);
  51.         break;
  52.     case SPI_IOC_RD_BITS_PER_WORD:
  53.         retval = __put_user(spi->bits_per_word, (__u8 __user *)arg);
  54.         break;
  55.     case SPI_IOC_RD_MAX_SPEED_HZ:
  56.         retval = __put_user(spi->max_speed_hz, (__u32 __user *)arg);
  57.         break;
  58.     /* write requests */
  59.     case SPI_IOC_WR_MODE:
  60.         retval = __get_user(tmp, (u8 __user *)arg);
  61.         if (retval == 0) {
  62.             u8    save = spi->mode;
  63.             if (tmp & ~SPI_MODE_MASK) {
  64.                 retval = -EINVAL;
  65.                 break;
  66.             }
  67.             tmp |= spi->mode & ~SPI_MODE_MASK;
  68.             spi->mode = (u8)tmp;
  69.             retval = spi_setup(spi);
  70.             if (retval < 0)
  71.                 spi->mode = save;
  72.             else
  73.                 dev_dbg(&spi->dev, "spi mode %02x\n", tmp);
  74.         }
  75.         break;
  76.     case SPI_IOC_WR_LSB_FIRST:
  77.         retval = __get_user(tmp, (__u8 __user *)arg);
  78.         if (retval == 0) {
  79.             u8    save = spi->mode;
  80.             if (tmp)
  81.                 spi->mode |= SPI_LSB_FIRST;
  82.             else
  83.                 spi->mode &= ~SPI_LSB_FIRST;
  84.             retval = spi_setup(spi);
  85.             if (retval < 0)
  86.                 spi->mode = save;
  87.             else
  88.                 dev_dbg(&spi->dev, "%csb first\n",
  89.                         tmp ? 'l' : 'm');
  90.         }
  91.         break;
  92.     case SPI_IOC_WR_BITS_PER_WORD:
  93.         retval = __get_user(tmp, (__u8 __user *)arg);
  94.         if (retval == 0) {
  95.             u8    save = spi->bits_per_word;
  96.             spi->bits_per_word = tmp;
  97.             retval = spi_setup(spi);
  98.             if (retval < 0)
  99.                 spi->bits_per_word = save;
  100.             else
  101.                 dev_dbg(&spi->dev, "%d bits per word\n", tmp);
  102.         }
  103.         break;
  104.     case SPI_IOC_WR_MAX_SPEED_HZ:
  105.         retval = __get_user(tmp, (__u32 __user *)arg);
  106.         if (retval == 0) {
  107.             u32    save = spi->max_speed_hz;
  108.             spi->max_speed_hz = tmp;
  109.             retval = spi_setup(spi);
  110.             if (retval < 0)
  111.                 spi->max_speed_hz = save;
  112.             else
  113.                 dev_dbg(&spi->dev, "%d Hz (max)\n", tmp);
  114.         }
  115.         break;
  116.     default:
  117.         /* segmented and/or full-duplex I/O request */
  118.         if (_IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0))
  119.                 || _IOC_DIR(cmd) != _IOC_WRITE) {
  120.             retval = -ENOTTY;
  121.             break;
  122.         }
  123.         tmp = _IOC_SIZE(cmd);
  124.         if ((tmp % sizeof(struct spi_ioc_transfer)) != 0) {
  125.             retval = -EINVAL;
  126.             break;
  127.         }
  128.         n_ioc = tmp / sizeof(struct spi_ioc_transfer);
  129.         if (n_ioc == 0)
  130.             break;
  131.         /* copy into scratch area */
  132.         ioc = kmalloc(tmp, GFP_KERNEL);
  133.         if (!ioc) {
  134.             retval = -ENOMEM;
  135.             break;
  136.         }
  137.         if (__copy_from_user(ioc, (void __user *)arg, tmp)) {
  138.             kfree(ioc);
  139.             retval = -EFAULT;
  140.             break;
  141.         }
  142.         /* translate to spi_message, execute */
  143.         retval = spidev_message(spidev, ioc, n_ioc);
  144.         kfree(ioc);
  145.         break;
  146.     }
  147.     mutex_unlock(&spidev->buf_lock);
  148.     spi_dev_put(spi);
  149.     return retval;
  150. }

相關推薦

Linux spi驅動分析()----spiddev分析

static longspidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){    int            err = 0;    int            retval = 0;    struct spid

linux spi驅動開發學習(四)-----spi驅動程式完整流程分析

所有的應用程式使用dev/目錄下建立的裝置,這些字元裝置的操作函式集在檔案spidev.c中實現。 點選(此處)摺疊或開啟 static const struct file_operations spidev_fops = {     .owner =    THIS

Linux spi驅動分析(一)----匯流排驅動

一、SPI匯流排驅動介紹         SPI匯流排總共需要四根線,包括MOSI、MISO、CLK和CS。本文首先從SPI設備註冊開始來講述SPI匯流排驅動。 二、設備註冊         在系統啟動的時候,會按照順序執行一些初始化程式,比如device_initcall和module_i

Linux spi驅動分析(二)----SPI核心(bus、device_driver和device)

struct device {     struct device        *parent;     struct device_private    *p;     struct kobject kobj;     const char        *init_name; /* init

Linux網路驅動程式開發例項分析

一.Linux系統裝置驅動程式概述   1.1 Linux裝置驅動程式分類   1.2 編寫驅動程式的一些基本概念 二.Linux系統網路裝置驅動程式 2.1 網路驅動程式的結構 2.2 網路驅動程式的基本方法 2.3 網路驅動程式中用到的資料結構 2.4 常用的系統支援 

linux spi驅動開發學習()-----spi_bitbang.c詳解

SPI介面在模式0下輸出第一位資料的時刻 SPI介面有四種不同的資料傳輸時序,取決於CPOL和CPHL這兩位的組合。圖1中表現了這四種時序, 時序與CPOL、CPHL的關係也可以從圖中看出。 圖1 CPOL是用來決定SCK時鐘訊號空閒時的電平,CPOL=0,空閒電平為低

linux Nand 驅動的架構整體分析

platform device 和 platform driver 的結構,現在看來是初步理解他的用意了,首先 platform device 申請的是資源,而 platform driver 才是真正的驅動。 我一直的疑問就是,如果換個NAND flash晶片,應該怎麼辦

linux裝置驅動篇:寫一個簡單的字元裝置驅動

在linux裝置驅動第一篇:裝置驅動程式簡介中簡單介紹了字元驅動,本篇簡單介紹如何寫一個簡單的字元裝置驅動。本篇借鑑LDD中的原始碼,實現一個與硬體裝置無關的字元裝置驅動,僅僅操作從核心中分配的一些記憶體。 下面就開始學習如何寫一個簡單的字元裝置驅動。首先我們來分解一下字元

Linux SPI驅動設計

1. SPI匯流排結構 SPI序列外設介面,是一種高速的,全雙工,同步的通訊匯流排。採用主從模式架構,支援多個slave,一般僅支援單Master SPI介面共有4根訊號線,分別是: 裝置選擇線(SS)、時鐘線(SCK)、序列輸出資料線(MOSI)、序列輸入資料線(MISO

linux spi驅動

最近在學習Linux spi驅動,中途出現了諸多疑問,天蒼蒼野茫茫,堅持總是可以看到牛羊的,本文以新唐NUC972這顆晶片為例進行逐步分析 參考很有價值的兩篇文章: http://www.th7.cn/system/lin/201507/122488.shtml ht

linux裝置驅動篇:如何實現簡單的字元裝置驅動

在linux裝置驅動第一篇:裝置驅動程式簡介中簡單介紹了字元驅動,本篇簡單介紹如何寫一個簡單的字元裝置驅動。本篇借鑑LDD中的原始碼,實現一個與硬體裝置無關的字元裝置驅動,僅僅操作從核心中分配的一些記憶體。 下面就開始學習如何寫一個簡單的字元裝置驅動。首先我們來分解一下

LINUX SPI驅動筆記

static struct spi_board_info s3c_spi_devs[] __initdata = {                 {                         .modalias = "m25p10",                          .mode =

linux SPI驅動——spi協議(一)

 一:SPI簡介以及應用      SPI, Serial Perripheral Interface, 序列外圍裝置介面, 是 Motorola 公司推出的一種同步序列介面技術. SPI 匯流排在物理上是通過接在外圍裝置微控制器(PICmicro) 上面的微處理控制單元 (

linux SPI驅動框架(二) -- 裝置驅動

裝置驅動關注的結構體主要有兩個,struct spi_device描述spi從裝置,struct spi_driver是從裝置的裝置驅動。 struct spi_device { struct device dev; str

Linux裝置驅動天(字元裝置驅動、cdev)

裝置號的分配 靜態分配: 動態分配: /** * 功能:動態申請裝置號 * dev:存放返回的裝置號的結構體 * firstminor:指定次裝置號 * count:連續編號範圍 * name:編號相關聯的裝置名稱. (/proc/devices)

linux SPI驅動——spi core(四)

一:SPI核心,就是指/drivers/spi/目錄下spi.c檔案中提供給其他檔案的函式,首先看下spi核心的初始化函式spi_init(void)。1: static int __init spi_init(void)2: {3: int status;4:  5: bu

Linux字元裝置驅動註冊種方法以及核心分析

       Linux驅動是使用者訪問底層硬體的橋樑,驅動有可以簡單分成三類:字元裝置、塊裝置、網路裝置。其中最多的是字元裝置,其中字元裝置的註冊方法主要有三種:雜項設備註冊、早期字元設備註冊、標準字元設備註冊。以及詳細介紹各類方法註冊。 開發環境: PC:WMwork

從零開始之驅動發開、linux驅動十八、Linux common clock framework(3)_實現邏輯分析

1. 前言 前面兩篇clock framework的分析文章,分別從clock consumer和clock provider的角度,介紹了Linux kernel怎麼管理系統的clock資源,以及device driver怎麼使用clock資源。本文將深入到clock framework的

linux驅動由淺入深系列:塊裝置驅動(塊裝置驅動結構分析,以mmc為例)

linux驅動由淺入深系列:塊裝置驅動之一(高通eMMC分割槽例項)前一篇文章介紹了塊裝置驅動在linux框架張的位置關係,本文來分析一下驅動本身。塊裝置驅動的模型還是基本基於字元裝置驅動的,可以簡單理解為塊裝置僅僅增加了操作緩衝區,對使用者操作請求進行佇列重排。因此只在有了

Linux驅動修煉之道-SPI驅動框架原始碼分析(中-續)

然後看這裡是怎樣註冊spi主機控制器驅動的: int spi_register_master(struct spi_master *master)   {       。。。。。。。。。。。。。。。。       /*將spi新增到核心,這