Linux spi驅動分析(三)----spiddev分析
- static long
- spidev_ioctl(struct file
*filp, unsigned
int cmd, unsigned long arg)
- {
- int err
= 0;
- int retval
= 0;
- struct spidev_data *spidev;
- struct spi_device *spi;
- u32 tmp;
- unsigned n_ioc;
- struct spi_ioc_transfer *ioc;
- /* Check type
and
- if (_IOC_TYPE(cmd)
!= SPI_IOC_MAGIC)
- return -ENOTTY;
- /* Check access direction once here; don't repeat below.
- * IOC_DIR
is from the user perspective,
while access_ok is
- * from the kernel perspective; so they look reversed.
- */
- if (_IOC_DIR(cmd)
& _IOC_READ)
- err =
!access_ok(VERIFY_WRITE,
- (void __user
*)arg, _IOC_SIZE(cmd));
- if (err
== 0
&& _IOC_DIR(cmd)
& _IOC_WRITE)
- err =
!access_ok(VERIFY_READ,
- (void __user
*)arg, _IOC_SIZE(cmd));
- if (err)
- return -EFAULT;
- /* guard against device removal before,
- * we issue this ioctl.
- */
- spidev = filp->private_data;
- spin_lock_irq(&spidev->spi_lock);
- spi = spi_dev_get(spidev->spi);
- spin_unlock_irq(&spidev->spi_lock);
- if (spi
==
NULL)
- return -ESHUTDOWN;
- /* use the buffer lock here
for triple duty:
- * - prevent I/O
(from us) so calling spi_setup()
is safe;
- * - prevent concurrent SPI_IOC_WR_* from morphing
- * data fields
while SPI_IOC_RD_* reads them;
- * - SPI_IOC_MESSAGE needs the buffer locked
"normally".
- */
- mutex_lock(&spidev->buf_lock);
- switch (cmd)
{
- /* read requests
*/
- case SPI_IOC_RD_MODE:
- retval = __put_user(spi->mode
& SPI_MODE_MASK,
- (__u8 __user
*)arg);
- break;
- case SPI_IOC_RD_LSB_FIRST:
- retval = __put_user((spi->mode
& SPI_LSB_FIRST)
? 1 : 0,
- (__u8 __user
*)arg);
- break;
- case SPI_IOC_RD_BITS_PER_WORD:
- retval = __put_user(spi->bits_per_word,
(__u8 __user *)arg);
- break;
- case SPI_IOC_RD_MAX_SPEED_HZ:
- retval = __put_user(spi->max_speed_hz,
(__u32 __user *)arg);
- break;
- /* write requests
*/
- case SPI_IOC_WR_MODE:
- retval = __get_user(tmp,
(u8 __user *)arg);
- if (retval
== 0)
{
- u8 save = spi->mode;
- if
(tmp & ~SPI_MODE_MASK)
{
- retval =
-EINVAL;
- break;
- }
- tmp |= spi->mode
& ~SPI_MODE_MASK;
- spi->mode
= (u8)tmp;
- retval = spi_setup(spi);
- if
(retval < 0)
- spi->mode
= save;
- else
- dev_dbg(&spi->dev,
"spi mode %02x\n", tmp);
- }
- break;
- case SPI_IOC_WR_LSB_FIRST:
- retval = __get_user(tmp,
(__u8 __user *)arg);
- if (retval
== 0)
{
- u8 save = spi->mode;
- if
(tmp)
- spi->mode
|= SPI_LSB_FIRST;
- else
- spi->mode
&=
~SPI_LSB_FIRST;
- retval = spi_setup(spi);
- if
(retval < 0)
- spi->mode
= save;
- else
- dev_dbg(&spi->dev,
"%csb first\n",
- tmp ?
'l' :
'm');
- }
- break;
- case SPI_IOC_WR_BITS_PER_WORD:
- retval = __get_user(tmp,
(__u8 __user *)arg);
- if (retval
== 0)
{
- u8 save = spi->bits_per_word;
- spi->bits_per_word
= tmp;
- retval = spi_setup(spi);
- if
(retval < 0)
- spi->bits_per_word
= save;
- else
- dev_dbg(&spi->dev,
"%d bits per word\n", tmp);
- }
- break;
- case SPI_IOC_WR_MAX_SPEED_HZ:
- retval = __get_user(tmp,
(__u32 __user *)arg);
- if (retval
== 0)
{
- u32 save = spi->max_speed_hz;
- spi->max_speed_hz
= tmp;
- retval = spi_setup(spi);
- if
(retval < 0)
- spi->max_speed_hz
= save;
- else
- dev_dbg(&spi->dev,
"%d Hz (max)\n", tmp);
- }
- break;
- default:
- /* segmented
and/or full-duplex I/O request
*/
- if (_IOC_NR(cmd)
!= _IOC_NR(SPI_IOC_MESSAGE(0))
- || _IOC_DIR(cmd)
!= _IOC_WRITE)
{
- retval =
-ENOTTY;
- break;
- }
- tmp = _IOC_SIZE(cmd);
- if ((tmp
% sizeof(struct spi_ioc_transfer))
!= 0)
{
- retval =
-EINVAL;
- break;
- }
- n_ioc = tmp
/ sizeof(struct spi_ioc_transfer);
- if (n_ioc
== 0)
- break;
- /* copy into scratch area
*/
- ioc = kmalloc(tmp, GFP_KERNEL);
- if (!ioc)
{
- retval =
-ENOMEM;
- break;
- }
- if (__copy_from_user(ioc,
(void __user *)arg, tmp))
{
- kfree(ioc);
- retval =
-EFAULT;
- break;
- }
- /* translate
to spi_message, execute
*/
- retval = spidev_message(spidev, ioc, n_ioc);
- kfree(ioc);
- break;
- }
- mutex_unlock(&spidev->buf_lock);
- spi_dev_put(spi);
- return retval;
- }
相關推薦
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新增到核心,這