1. 程式人生 > >linux spi驅動

linux spi驅動

最近在學習Linux spi驅動,中途出現了諸多疑問,天蒼蒼野茫茫,堅持總是可以看到牛羊的,本文以新唐NUC972這顆晶片為例進行逐步分析

參考很有價值的兩篇文章:
	http://www.th7.cn/system/lin/201507/122488.shtml
	http://blog.chinaunix.net/uid-25445243-id-4026974.html
	
1、SPI 匯流排註冊
	原始碼路徑:drivers/spi/spi.c
	有興趣的可以看下這位大神的文章,很詳細http://blog.chinaunix.net/uid-25445243-id-4032371.html
	
2、spidev.c
	原始碼路徑:drivers/spi/spidev.c
	如果不想寫具體的晶片驅動,就可以用kernel自帶的驅動spidev.c(這裡是困擾我的地方,之前一直沒搞明白這裡有了
	spi驅動程式,為啥還要編寫,因為某個裝置對應的驅動必須是唯一的,而驅動卻可以對應多個裝置),在板級資訊spi_board_info
	結構體中將.modalias = "spidev"即可,因為spidev.c中已經驅動取名為“spidev”

3、SPI platform_device設備註冊 
	原始碼路徑:arch/arm/mach-nuc970/dev.c
	
	static struct nuc970_spi_info nuc970_spi0_platform_data = {
        .num_cs		= 1,
        .lsb		= 0,
        .txneg		= 1,
        .rxneg		= 0,
        .divider	= 4,
        .sleep		= 0,
        .txnum		= 0,
        .txbitlen	= 8,
        .bus_num	= 0,	//注意這個引數很重要!表示SPI控制器的編號是0,將來在spi從裝置的
							//板級資訊中有體現,意思是將來這個spi從裝置掛在編號為0的spi匯流排下面;
	};
	
	static struct resource nuc970_spi0_resource[] = {
        [0] = {
                .start = NUC970_PA_SPI0,
                .end   = NUC970_PA_SPI0 + NUC970_SZ_SPI0 - 1,
                .flags = IORESOURCE_MEM,
        },
        [1] = {
                .start = IRQ_SPI0,
                .end   = IRQ_SPI0,
                .flags = IORESOURCE_IRQ,
        }
	};
	
	struct platform_device nuc970_device_spi0 = {
        .name		  = "nuc970-spi0",	//裝置名
        .id		  = -1,
        .num_resources	  = ARRAY_SIZE(nuc970_spi0_resource),
        .resource	  = nuc970_spi0_resource,
		#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_SPI_SPIDEV)
        .dev		= {
                .platform_data = &nuc970_spi0_platform_data,
		}
		#endif
	};
	
	static struct platform_device *nuc970_public_dev[] __initdata = {
        &nuc970_device_spi0,
	}

	//註冊spi裝置
	void __init nuc970_platform_init(struct platform_device **device, int size)
	{
		platform_add_devices(device, size);
		platform_add_devices(nuc970_public_dev, ARRAY_SIZE(nuc970_public_dev));
	}

4、SPI platform_driver驅動註冊
	原始碼路徑:drivers/spi/spi-nuc970-p0.c
	
	static struct platform_driver nuc970_spi0_driver = {
		.probe		= nuc970_spi0_probe,	//由於platform_device先於platform_driver註冊,所以設
											//備.name=裝置驅動.name時將回調nuc970_spi0_probe
		.remove		= nuc970_spi0_remove,
		.driver		= {
			.name	= "nuc970-spi0",
			.owner	= THIS_MODULE,
		},
	};
	
	//註冊spi驅動
	module_platform_driver(nuc970_spi0_driver);

	
5、SPI從裝置板級資訊 以M25P80 norflash晶片為例
	原始碼路徑:arch/arm/mach-nuc970/dev.c
	
	#if defined(CONFIG_SPI_FLASH_W25Q)
	 static struct gsc3280_spi_info w25q_spi1_dev_platdata = {
		 .cs_type            = 1,
		.pin_cs            = 87,
		.num_cs            = 1,
		.cs_value            = 0,
		.lsb_flg            = 0,
		.bits_per_word    = 8,
	};
	#endif
	static struct spi_board_info gsc3280_spi_devices[] = {
	#if defined(CONFIG_SPI_FLASH_W25Q)
		{
			.modalias        = "spi-w25q",
			.bus_num        = 0,//注意這個引數很重要(參考第3點解釋)!這個從裝置將掛在編號為0的總線上,
								//這樣從裝置“spi-w25q”就與“nuc970-spi0”平臺匯流排(控制器驅動)連線起來了
			.chip_select        = 2,
			.mode            = SPI_MODE_3,
			.max_speed_hz    = 5 * 1000 * 1000,
			.controller_data    = &w25q_spi1_dev_platdata,
		},
	#endif
	};
	
	//註冊“spi-w25q”板級資訊
	static int __init gsc3280_spi_devices_init(void)
	{
		spi_register_board_info(gsc3280_spi_devices, ARRAY_SIZE(gsc3280_spi_devices));
		return 0;
	}
	device_initcall(gsc3280_spi_devices_init);
	
6、SPI 從裝置驅動程式(以字元裝置,att7022e就是通過這裡進行操作的)
	static struct spi_driver w25q_driver = {
		.driver    = {
			.name    = "spi-w25q",
			.owner    = THIS_MODULE,
		},
		//.id_table    = w25q_ids,
		.probe    = w25q_probe,
		.remove    = __devexit_p(w25q_remove),
	};


	static int __init w25q_init(void)
	{
		return spi_register_driver(&w25q_driver);
	}
	static void __exit w25q_exit(void)
	{
		spi_unregister_driver(&w25q_driver);
	}
	module_init(w25q_init);
	module_exit(w25q_exit);
	
	......
	
	花了一個三天的時間才搞明白SPI驅動的註冊原理。。。

相關推薦

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驅動分析(三)----spiddev分析

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

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 spi驅動開發學習(三)-----spi_bitbang.c詳解

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

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 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 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 spi主機控制器pl022驅動註冊以及匹配裝置過程

最近看海思的spi比較多,海思3519的spi ip使用的時ARM提供的pl022,這裡對pl022驅動註冊和匹配裝置樹中的裝置這個過程捋一下。 pl022是ARM提供的片內外設,很多廠商都用了這個ip,只在一些細小的區別。所以它的驅動也是非常通用的。pl022的手冊可以看這裡點選開啟連結

65 linux spi裝置驅動spi LCD屏驅動

SPI的控制器驅動由平臺裝置與平臺驅動來實現. 驅動後用spi_master物件來描述.在裝置驅動中就可以通過函式spi_write, spi_read, spi_w8r16, spi_w8r8等函式來呼叫控制器. "include/linux/spi/s

Linux SPI匯流排和裝置驅動架構之一:系統概述

SPI是"Serial Peripheral Interface" 的縮寫,是一種四線制的同步序列通訊介面,用來連線微控制器、感測器、儲存裝置,SPI裝置分為主裝置和從裝置兩種,用於通訊和控制的四根線分別是: CS    片選訊號SCK  時鐘訊號MISO  主裝置的資料

linux spi裝置驅動中probe函式何時被呼叫

這兩天被裝置檔案快搞瘋了,也怪自己學東西一知半解吧,弄了幾天總算能把設備註冊理清楚一點點了。就以spi子裝置的註冊為例總結一下,免得自己忘記。 首先以註冊一個spidev的裝置為例: static struct spi_board_info imx5_spi_printe

Linux SPI匯流排和裝置驅動架構之二:SPI通用介面層

通過上一篇文章的介紹,我們知道,SPI通用介面層用於把具體SPI裝置的協議驅動和SPI控制器驅動聯接在一起,通用介面層除了為協議驅動和控制器驅動提供一系列的標準介面API,同時還為這些介面API定義了相應的資料結構,這些資料結構一部分是SPI裝置、SPI協議驅動和SPI控制

Linux SPI匯流排和裝置驅動架構之四:SPI資料傳輸的佇列化

我們知道,SPI資料傳輸可以有兩種方式:同步方式和非同步方式。所謂同步方式是指資料傳輸的發起者必須等待本次傳輸的結束,期間不能做其它事情,用程式碼來解釋就是,呼叫傳輸的函式後,直到資料傳輸完成,函式才會返回。而非同步方式則正好相反,資料傳輸的發起者無需等待傳輸的結束,資料傳

Linux系統SPI驅動學習筆記(一)

  SPI是"Serial Peripheral Interface" 的縮寫,是一種四線制的同步序列通訊介面,用來連線微控制器、感測器、儲存裝置,SPI裝置分為主裝置和從裝置兩種,用於通訊和控制的四根線分別是: CS    片選訊號SCK  時鐘訊號MISO  主裝置的

二、Linux spi 控制器驅動

1、概覽 對於ARM平臺來說,大多數CPU都是SoC。spi控制器被整合在CPU內部。spi總線上的資料傳輸過程通常就是這個spi控制器來控制的。為了使spi控制器能工作在linux spi子系統中,我們就需要針對CPU內部的spi控制器編寫一個驅動。前面

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

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