3atv精品不卡视频,97人人超碰国产精品最新,中文字幕av一区二区三区人妻少妇,久久久精品波多野结衣,日韩一区二区三区精品

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】PowerPC + Linux2.6.25平台下的SPI驱动架构分析

發(fā)布時間:2024/9/21 linux 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】PowerPC + Linux2.6.25平台下的SPI驱动架构分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

PowerPC + Linux2.6.25平臺下的SPI驅(qū)動架構(gòu)分析

?

Sailor_forever? sailing_9806#163.com

(本原創(chuàng)文章發(fā)表于Sailor_forever 的個人blog,未經(jīng)本人許可,不得用于商業(yè)用途。任何個人、媒體、其他網(wǎng)站不得私自抄襲;網(wǎng)絡(luò)媒體轉(zhuǎn)載請注明出處,增加原文鏈接,否則屬于侵權(quán)行為。如 有任何問題,請留言或者發(fā)郵件給sailing_9806#163.com)
http://blog.csdn.net/sailor_8318/archive/2010/10/31/5977733.aspx

?

?

【摘要】本文以PowerPC+Linux 2.6.25 平臺為例,詳細(xì)分析了SPI總線的驅(qū)動架構(gòu)。首先介紹了SPI的總體架構(gòu),從用戶的角度將其分為三個層面,不同的開發(fā)者只需要關(guān)注相應(yīng)的層面即可。然后分析了主要數(shù)據(jù)結(jié)構(gòu)及其之間的相互關(guān)系,接著分析了不同層的具體實現(xiàn),最后以一款SPI接口的時鐘芯片為例講述了如何在用戶空間訪問SPI驅(qū)動。對于ARM + Linux平臺,只有平臺依賴層即總線控制器驅(qū)動有差異。

【關(guān)鍵字】PowerPC, SPI, Master, Slave, spidev

目錄
1??? SPI概述??? 3
2??? SPI總體架構(gòu)??? 3
2.1??? 硬件抽象層??? 3
2.2??? 平臺依賴層??? 3
2.3??? 用戶接口層??? 3
3??? 主要的數(shù)據(jù)結(jié)構(gòu)??? 4
3.1??? Spi_master??? 4
3.2??? SPI_driver??? 5
3.3??? Spi_device??? 6
4??? 平臺依賴層-總線控制器驅(qū)動??? 7
4.1??? platform device??? 8
4.2??? platform driver??? 11
4.3??? SPI Master??? 14
5??? 硬件抽象層-SPI core??? 14
5.1??? 總線初始化??? 14
5.2??? Master注冊??? 15
5.3??? 驅(qū)動注冊??? 19
5.4??? 數(shù)據(jù)傳輸??? 19
6??? 用戶接口層-SPI設(shè)備驅(qū)動??? 21
6.1??? 統(tǒng)一的設(shè)備模型??? 21
6.1.1??? 關(guān)鍵數(shù)據(jù)結(jié)構(gòu)??? 21
6.1.2??? 初始化??? 22
6.1.3??? Open及release??? 24
6.1.4??? 數(shù)據(jù)收發(fā)??? 25
6.2??? 特定的設(shè)備驅(qū)動??? 36
6.2.1??? 關(guān)鍵數(shù)據(jù)結(jié)構(gòu)??? 37
6.2.2??? 初始化??? 38
6.2.3??? 數(shù)據(jù)收發(fā)??? 42
7??? 驅(qū)動訪問示例??? 42
7.1.1??? 寫操作??? 43
7.1.2??? 讀操作??? 43
8??? 參考鳴謝??? 44


1??? SPI概述
SPI的通信原理很簡單,它以主從方式工作,這種模式通常有一個主設(shè)備和一個或多個從設(shè)備,需要至少4根線,事實上3根也可以(單向傳輸時或者硬件復(fù)用兩根數(shù)據(jù)線),也是所有基于SPI的設(shè)備共有的,它們是MISO、MOSI、SCK、CS。
(1)SDO – 主設(shè)備數(shù)據(jù)輸出,從設(shè)備數(shù)據(jù)輸入
(2)MISO– 主設(shè)備數(shù)據(jù)輸入,從設(shè)備數(shù)據(jù)輸出
(3)SCK – 時鐘信號,由主設(shè)備產(chǎn)生
(4)CS – 從設(shè)備使能信號,由主設(shè)備控制
其中CS是控制芯片是否被選中的,也就是說只有片選信號為預(yù)先規(guī)定的使能信號時(高電位或低電位),對此芯片的操作才有效,這就允許在同一總線上連接多個SPI設(shè)備成為可能。接下來就負(fù)責(zé)通訊的3根線了,通訊是通過數(shù)據(jù)交換完成的。SPI是串行通訊協(xié)議,也就是說數(shù)據(jù)是一位一位從MSB或者LSB開始傳輸?shù)?#xff0c;這就是SCK時鐘線存在的原因,由SCK提供時鐘脈沖,MISO、MOSI則基于此脈沖完成數(shù)據(jù)傳輸。 SPI支持4-32bits的串行數(shù)據(jù)傳輸,支持MSB和LSB,每次數(shù)據(jù)傳輸時當(dāng)從設(shè)備的大小端發(fā)生變化時需要重新設(shè)置SPI Master的大小端。

2??? SPI總體架構(gòu)
在2.6的Linux內(nèi)核中,SPI的驅(qū)動架構(gòu)分為如下三個層次:硬件抽象層、平臺依賴層和用戶接口層。
2.1??? 硬件抽象層
SPI-bitbang.c和SPI.c為其主體框架代碼,提供了核心數(shù)據(jù)結(jié)構(gòu)的定義、SPI控制器驅(qū)動和設(shè)備驅(qū)動的注冊、注銷管理等API。其為硬件平臺無關(guān)層,向下屏蔽了物理總線控制器的差異,定義了統(tǒng)一的訪問策略和接口;其向上提供了統(tǒng)一的接口,以便SPI設(shè)備驅(qū)動通過總線控制器進(jìn)行數(shù)據(jù)收發(fā)。
2.2??? 平臺依賴層
SPI總線Master就是一條SPI總線的控制器(所謂控制是相對于本CPU來說的),在物理上連接若干SPI從設(shè)備。在Linux驅(qū)動中,每種處理器平臺有自己的控制器驅(qū)動,屬于平臺移植相關(guān)層。PowerPC平臺來說,其是spi_mpc83xx.c。其按照核心層定義的接口實現(xiàn)了spi_master。
2.3??? 用戶接口層
設(shè)備驅(qū)動層為用戶接口層,其為用戶提供了通過SPI總線訪問具體設(shè)備的接口。

3??? 主要的數(shù)據(jù)結(jié)構(gòu)
3.1??? Spi_master
spi_master是對某一條SPI總線的抽象,是特定總線的相關(guān)屬性的集合。
/**
?* struct spi_master - interface to SPI master controller
?* @dev: device interface to this driver
?* @bus_num: board-specific (and often SOC-specific) identifier for a
?*??? given SPI controller.
?* @num_chipselect: chipselects are used to distinguish individual
?*??? SPI slaves, and are numbered from zero to num_chipselects.
?*??? each slave has a chipselect signal, but it's common that not
?*??? every chipselect is connected to a slave.
?* @setup: updates the device mode and clocking records used by a
?*??? device's SPI controller; protocol code may call this.? This
?*??? must fail if an unrecognized or unsupported mode is requested.
?*??? It's always safe to call this unless transfers are pending on
?*??? the device whose settings are being modified.
?* @transfer: adds a message to the controller's transfer queue.
?* @cleanup: frees controller-specific state
?*
?* Each SPI master controller can communicate with one or more @spi_device
?* children.? These make a small bus, sharing MOSI, MISO and SCK signals
?* but not chip select signals.? Each device may be configured to use a
?* different clock rate, since those shared signals are ignored unless
?* the chip is selected.
?*
?* The driver for an SPI controller manages access to those devices through
?* a queue of spi_message transactions, copying data between CPU memory and
?* an SPI slave device.? For each such message it queues, it calls the
?* message's completion function when the transaction completes.
?*/
struct spi_master {
??? struct device??? dev;

??? /* other than negative (== assign one dynamically), bus_num is fully
??? ?* board-specific.? usually that simplifies to being SOC-specific.
??? ?* example:? one SOC has three SPI controllers, numbered 0..2,
??? ?* and one board's schematics might show it using SPI-2.? software
??? ?* would normally use bus_num=2 for that controller.
??? ?*/
??? s16??? ??? ??? bus_num;

??? /* chipselects will be integral to many controllers; some others
??? ?* might use board-specific GPIOs.
??? ?*/
??? u16??? ??? ??? num_chipselect;

??? /* setup mode and clock, etc (spi driver may call many times) */
??? int??? ??? ??? (*setup)(struct spi_device *spi);

??? /* bidirectional bulk transfers
??? ?*
??? ?* + The transfer() method may not sleep; its main role is
??? ?*?? just to add the message to the queue.
??? ?* + For now there's no remove-from-queue operation, or
??? ?*?? any other request management
??? ?* + To a given spi_device, message queueing is pure fifo
??? ?*
??? ?* + The master's main job is to process its message queue,
??? ?*?? selecting a chip then transferring data
??? ?* + If there are multiple spi_device children, the i/o queue
??? ?*?? arbitration algorithm is unspecified (round robin, fifo,
??? ?*?? priority, reservations, preemption, etc)
??? ?*
??? ?* + Chipselect stays active during the entire message
??? ?*?? (unless modified by spi_transfer.cs_change != 0).
??? ?* + The message transfers use clock and SPI mode parameters
??? ?*?? previously established by setup() for this device
??? ?*/
??? int??? ??? ??? (*transfer)(struct spi_device *spi,
??? ??? ??? ??? ??? ??? struct spi_message *mesg);

??? /* called on release() to free memory provided by spi_master */
??? void??? ??? ??? (*cleanup)(struct spi_device *spi);
};

3.2??? SPI_driver
http://lxr.linux.no/#linux+v2.6.25/include/linux/SPI.h#L105
/**
?* struct spi_driver - Host side "protocol" driver
?* @probe: Binds this driver to the spi device.? Drivers can verify
?*??? that the device is actually present, and may need to configure
?*??? characteristics (such as bits_per_word) which weren't needed for
?*??? the initial configuration done during system setup.
?* @remove: Unbinds this driver from the spi device
?* @shutdown: Standard shutdown callback used during system state
?*??? transitions such as powerdown/halt and kexec
?* @suspend: Standard suspend callback used during system state transitions
?* @resume: Standard resume callback used during system state transitions
?* @driver: SPI device drivers should initialize the name and owner
?*??? field of this structure.
?*
?* This represents the kind of device driver that uses SPI messages to
?* interact with the hardware at the other end of a SPI link.? It's called
?* a "protocol" driver because it works through messages rather than talking
?* directly to SPI hardware (which is what the underlying SPI controller
?* driver does to pass those messages).? These protocols are defined in the
?* specification for the device(s) supported by the driver.
?*
?* As a rule, those device protocols represent the lowest level interface
?* supported by a driver, and it will support upper level interfaces too.
?* Examples of such upper levels include frameworks like MTD, networking,
?* MMC, RTC, filesystem character device nodes, and hardware monitoring.
?*/
struct spi_driver {
??? int??? ??? ??? (*probe)(struct spi_device *spi);
??? int??? ??? ??? (*remove)(struct spi_device *spi);
??? void??? ??? ??? (*shutdown)(struct spi_device *spi);
??? int??? ??? ??? (*suspend)(struct spi_device *spi, pm_message_t mesg);
??? int??? ??? ??? (*resume)(struct spi_device *spi);
??? struct device_driver??? driver;
};
Driver是為device服務(wù)的,SPI_driver注冊時會掃描SPI bus上的設(shè)備,進(jìn)行驅(qū)動和設(shè)備的綁定。
3.3??? Spi_device
http://lxr.linux.no/#linux+v2.6.25/include/linux/SPI.h#L168
/**
?* struct spi_device - Master side proxy for an SPI slave device
?* @dev: Driver model representation of the device.
?* @master: SPI controller used with the device.
?* @max_speed_hz: Maximum clock rate to be used with this chip
?*??? (on this board); may be changed by the device's driver.
?*??? The spi_transfer.speed_hz can override this for each transfer.
?* @chip_select: Chipselect, distinguishing chips handled by @master.
?* @mode: The spi mode defines how data is clocked out and in.
?*??? This may be changed by the device's driver.
?*??? The "active low" default for chipselect mode can be overridden
?*??? (by specifying SPI_CS_HIGH) as can the "MSB first" default for
?*??? each word in a transfer (by specifying SPI_LSB_FIRST).
?* @bits_per_word: Data transfers involve one or more words; word sizes
?*??? like eight or 12 bits are common.? In-memory wordsizes are
?*??? powers of two bytes (e.g. 20 bit samples use 32 bits).
?*??? This may be changed by the device's driver, or left at the
?*??? default (0) indicating protocol words are eight bit bytes.
?*??? The spi_transfer.bits_per_word can override this for each transfer.
?* @irq: Negative, or the number passed to request_irq() to receive
?*??? interrupts from this device.
?* @controller_state: Controller's runtime state
?* @controller_data: Board-specific definitions for controller, such as
?*??? FIFO initialization parameters; from board_info.controller_data
*
?* A @spi_device is used to interchange data between an SPI slave
?* (usually a discrete chip) and CPU memory.
?*
?* In @dev, the platform_data is used to hold information about this
?* device that's meaningful to the device's protocol driver, but not
?* to its controller.? One example might be an identifier for a chip
?* variant with slightly different functionality; another might be
?* information about how this particular board wires the chip's pins.
?*/
struct spi_device {
??? struct device??? ??? dev;
??? struct spi_master??? *master;
??? u32??? ??? ??? max_speed_hz;
??? u8??? ??? ??? chip_select;
??? u8??? ??? ??? mode;
#define??? SPI_CPHA??? 0x01??? ??? ??? /* clock phase */
#define??? SPI_CPOL??? 0x02??? ??? ??? /* clock polarity */
#define??? SPI_MODE_0??? (0|0)??? ??? ??? /* (original MicroWire) */
#define??? SPI_MODE_1??? (0|SPI_CPHA)
#define??? SPI_MODE_2??? (SPI_CPOL|0)
#define??? SPI_MODE_3??? (SPI_CPOL|SPI_CPHA)
#define??? SPI_CS_HIGH??? 0x04??? ??? ??? /* chipselect active high? */
#define??? SPI_LSB_FIRST??? 0x08??? ??? ??? /* per-word bits-on-wire */
#define??? SPI_3WIRE??? 0x10??? ??? ??? /* SI/SO signals shared */
#define??? SPI_LOOP??? 0x20??? ??? ??? /* loopback mode */
??? u8??? ??? ??? bits_per_word;
??? int??? ??? ??? irq;
??? void??? ??? ??? *controller_state;
??? void??? ??? ??? *controller_data;
。。。
};

spi_device對應(yīng)著SPI總線上某個特定的slave。每個slave都有特定的大小端、速率及傳輸位寬,各個slave相互之間無干擾。


4??? 平臺依賴層-總線控制器驅(qū)動
總線控制器驅(qū)動,本質(zhì)上就是實現(xiàn)了具體的總線傳輸算法并向核心層注冊了控制器。主要分為三個層面,platform device,platform driver及與SPI core的接口層。

Linux內(nèi)核的所有SPI控制器驅(qū)動程序都在driver/SPI/下面,MPC8xxx驅(qū)動是spi_mpc83xx.c。
4.1??? platform device
2.6內(nèi)核中硬件資源的注冊都采用了platform device的機制。對于PowerPC來說,其硬件資源是通過DTS來描述的。
spi@7000 {
??? cell-index = <0>;
??? compatible = "fsl,spi";
??? reg = <0x7000 0x1000>;
??? interrupts = <16 0x8>;
??? interrupt-parent = <&ipic>;
??? mode = "cpu";
};
中斷號、中斷觸發(fā)電平、寄存器的基地址及范圍等信息會在設(shè)備樹中描述了,此后只需利用platform_get_resource等標(biāo)準(zhǔn)接口自動獲取即可,實現(xiàn)了驅(qū)動和資源的分離。Cell-index標(biāo)識了總線編號,也就是SPI master的編號。

隨后在系統(tǒng)啟動階段會解析DTB文件,將相關(guān)資源注冊到Platform bus上。
http://lxr.linux.no/#linux+v2.6.25/arch/powerpc/sysdev/fsl_soc.c#L454

int __init fsl_spi_init(struct spi_board_info *board_infos,
??? ??? ??? unsigned int num_board_infos,
??? ??? ??? void (*activate_cs)(u8 cs, u8 polarity),
??? ??? ??? void (*deactivate_cs)(u8 cs, u8 polarity))
{
??? u32 sysclk = -1;
??? int ret;
。。。。。
??? if (sysclk == -1) {
??? ??? struct device_node *np;
??? ??? const u32 *freq;
??? ??? int size;

??? ??? np = of_find_node_by_type(NULL, "soc"); //獲得SOC中注冊的總線頻率
??? ??? if (!np)
??? ??? ??? return -ENODEV;

??? ??? freq = of_get_property(np, "clock-frequency", &size);
??? ??? if (!freq || size != sizeof(*freq) || *freq == 0) {
??? ??? ??? freq = of_get_property(np, "bus-frequency", &size);
??? ??? ??? if (!freq || size != sizeof(*freq) || *freq == 0) {
??? ??? ??? ??? of_node_put(np);
??? ??? ??? ??? return -ENODEV;
??? ??? ??? }
??? ??? }

??? ??? sysclk = *freq;
??? ??? of_node_put(np);
??? }

??? ret = of_fsl_spi_probe(NULL, "fsl,spi", sysclk, board_infos,
??? ??? ??? ?????? num_board_infos, activate_cs, deactivate_cs);
??? if (!ret)
??? ??? of_fsl_spi_probe("spi", "fsl_spi", sysclk, board_infos,
??? ??? ??? ??? ?num_board_infos, activate_cs, deactivate_cs);

??? return spi_register_board_info(board_infos, num_board_infos);? //將SPI board info注冊進(jìn)系統(tǒng)SPI設(shè)備列表中
}


static int __init of_fsl_spi_probe(char *type, char *compatible, u32 sysclk,
??? ??? ??? ??? ?? struct spi_board_info *board_infos,
??? ??? ??? ??? ?? unsigned int num_board_infos,
??? ??? ??? ??? ?? void (*activate_cs)(u8 cs, u8 polarity),
??? ??? ??? ??? ?? void (*deactivate_cs)(u8 cs, u8 polarity))
{
??? struct device_node *np;
??? unsigned int i = 0;

??? for_each_compatible_node(np, type, compatible) { //根據(jù)compatible屬性"fsl,spi"查找相關(guān)device node節(jié)點
??? ??? int ret;
??? ??? unsigned int j;
??? ??? const void *prop;
??? ??? struct resource res[2];
??? ??? struct platform_device *pdev;
??? ??? struct fsl_spi_platform_data pdata = { //板級相關(guān)的SPI片選實現(xiàn)函數(shù)
??? ??? ??? .activate_cs = activate_cs,
??? ??? ??? .deactivate_cs = deactivate_cs,
??? ??? };

??? ??? memset(res, 0, sizeof(res));

??? ??? pdata.sysclk = sysclk;

??? ??? prop = of_get_property(np, "reg", NULL);
??? ??? if (!prop)
??? ??? ??? goto err;
??? ??? pdata.bus_num = *(u32 *)prop; //reg是寄存器的范圍,如何與總線編號掛鉤的呢?

??? ??? prop = of_get_property(np, "cell-index", NULL);
??? ??? if (prop)
??? ??? ??? i = *(u32 *)prop;

??? ??? prop = of_get_property(np, "mode", NULL);
??? ??? if (prop && !strcmp(prop, "cpu-qe"))
??? ??? ??? pdata.qe_mode = 1;

??? ??? for (j = 0; j < num_board_infos; j++) { //根據(jù)板級移植相關(guān)的board info指定的bus num進(jìn)行匹配
??? ??? ??? if (board_infos[j].bus_num == pdata.bus_num)
??? ??? ??? ??? pdata.max_chipselect++;
??? ??? }

??? ??? if (!pdata.max_chipselect)
??? ??? ??? continue;

??? ??? ret = of_address_to_resource(np, 0, &res[0]);
??? ??? if (ret)
??? ??? ??? goto err;

??? ??? ret = of_irq_to_resource(np, 0, &res[1]);
??? ??? if (ret == NO_IRQ)
??? ??? ??? goto err;

??? ??? pdev = platform_device_alloc("mpc83xx_spi", i); //以mpc83xx_spi為name申請platform device,后續(xù)的platform driver將以mpc83xx_spi為匹配因子
??? ??? if (!pdev)
??? ??? ??? goto err;

??? ??? ret = platform_device_add_data(pdev, &pdata, sizeof(pdata)); //將pdata等特定的屬性添加到platform device中,以供相應(yīng)的platform driver檢測。
??? ??? if (ret)
??? ??? ??? goto unreg;

??? ??? ret = platform_device_add_resources(pdev, res,
??? ??? ??? ??? ??? ??? ??? ARRAY_SIZE(res));
??? ??? if (ret)
??? ??? ??? goto unreg;

??? ??? ret = platform_device_add(pdev); //將SPI相關(guān)的platform device添加到platform bus上
??? ??? if (ret)
??? ??? ??? goto unreg;

??? ??? goto next;
unreg:
??? ??? platform_device_del(pdev);
err:
??? ??? pr_err("%s: registration failed/n", np->full_name);
next:
??? ??? i++;
??? }

??? return i;
}

4.2??? platform driver
static struct platform_driver mpc83xx_spi_driver = {
??? .remove = __exit_p(mpc83xx_spi_remove),
??? .driver = {
??? ??? .name = "mpc83xx_spi",
??? ??? .owner = THIS_MODULE,
??? },
};

static int __init mpc83xx_spi_init(void)
{
??? return platform_driver_probe(&mpc83xx_spi_driver, mpc83xx_spi_probe);
}

static void __exit mpc83xx_spi_exit(void)
{
??? platform_driver_unregister(&mpc83xx_spi_driver);
}
mpc83xx_spi_driver注冊時會掃描platform bus上的所有設(shè)備,匹配因子是mpc83xx_spi,匹配成功后調(diào)用mpc83xx_spi_probe將設(shè)備和驅(qū)動綁定起來,具體過程參加《詳解Linux2.6內(nèi)核中基于platform機制的驅(qū)動模型》,隨后向系統(tǒng)注冊一個adapter。
http://blog.csdn.net/sailor_8318/archive/2010/01/29/5267698.aspx

static int __init mpc83xx_spi_probe(struct platform_device *dev)
{
??? struct spi_master *master;
??? struct mpc83xx_spi *mpc83xx_spi;
??? struct fsl_spi_platform_data *pdata;
??? struct resource *r;
??? u32 regval;
??? int ret = 0;


??? /* Get resources(memory, IRQ) associated with the device */
??? master = spi_alloc_master(&dev->dev, sizeof(struct mpc83xx_spi)); // 分配一個SPI Master

??? if (master == NULL) {
??? ??? ret = -ENOMEM;
??? ??? goto err;
??? }

??? platform_set_drvdata(dev, master);
??? pdata = dev->dev.platform_data;? //獲得platform device注冊的特定資源

??? if (pdata == NULL) {
??? ??? ret = -ENODEV;
??? ??? goto free_master;
??? }


??? r = platform_get_resource(dev, IORESOURCE_MEM, 0);
??? if (r == NULL) {
??? ??? ret = -ENODEV;
??? ??? goto free_master;
??? }

??? mpc83xx_spi = spi_master_get_devdata(master);
??? mpc83xx_spi->bitbang.master = spi_master_get(master);
??? mpc83xx_spi->bitbang.chipselect = mpc83xx_spi_chipselect;
??? mpc83xx_spi->bitbang.setup_transfer = mpc83xx_spi_setup_transfer;
??? mpc83xx_spi->bitbang.txrx_bufs = mpc83xx_spi_bufs;
??? mpc83xx_spi->activate_cs = pdata->activate_cs;
??? mpc83xx_spi->deactivate_cs = pdata->deactivate_cs; // 將特定的片選實現(xiàn)函數(shù)保存到mpc83xx_spi中
??? mpc83xx_spi->qe_mode = pdata->qe_mode;
??? mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8;
??? mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8;
??? mpc83xx_spi->spibrg = pdata->sysclk;

??? mpc83xx_spi->rx_shift = 0;
??? mpc83xx_spi->tx_shift = 0;
??? if (mpc83xx_spi->qe_mode) {
??? ??? mpc83xx_spi->rx_shift = 16;
??? ??? mpc83xx_spi->tx_shift = 24;
??? }

??? mpc83xx_spi->bitbang.master->setup = mpc83xx_spi_setup;
??? init_completion(&mpc83xx_spi->done);

??? mpc83xx_spi->base = ioremap(r->start, r->end - r->start + 1);
??? if (mpc83xx_spi->base == NULL) {
??? ??? ret = -ENOMEM;
??? ??? goto put_master;
??? }

??? mpc83xx_spi->irq = platform_get_irq(dev, 0); //從platform device中獲得相應(yīng)的寄存器和中斷等信息

??? if (mpc83xx_spi->irq < 0) {
??? ??? ret = -ENXIO;
??? ??? goto unmap_io;
??? }

??? /* Register for SPI Interrupt */
??? ret = request_irq(mpc83xx_spi->irq, mpc83xx_spi_irq,
??? ??? ??? ? 0, "mpc83xx_spi", mpc83xx_spi);

??? if (ret != 0)
??? ??? goto unmap_io;

??? master->bus_num = pdata->bus_num;
??? master->num_chipselect = pdata->max_chipselect;

??? /* SPI controller initializations */
??? mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, 0);
??? mpc83xx_spi_write_reg(&mpc83xx_spi->base->mask, 0);
??? mpc83xx_spi_write_reg(&mpc83xx_spi->base->command, 0);
??? mpc83xx_spi_write_reg(&mpc83xx_spi->base->event, 0xffffffff);

??? /* Enable SPI interface */
??? regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
??? if (pdata->qe_mode)
??? ??? regval |= SPMODE_OP;

??? mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval);

??? ret = spi_bitbang_start(&mpc83xx_spi->bitbang);? //MPC83xx系列將在spi_bitbang_start中注冊SPI master

??? if (ret != 0)
??? ??? goto free_irq;

??? printk(KERN_INFO
??? ?????? "%s: MPC83xx SPI Controller driver at 0x%p (irq = %d)/n",
??? ?????? dev->dev.bus_id, mpc83xx_spi->base, mpc83xx_spi->irq);

??? return ret;

free_irq:
??? free_irq(mpc83xx_spi->irq, mpc83xx_spi);
unmap_io:
??? iounmap(mpc83xx_spi->base);
put_master:
??? spi_master_put(master);
free_master:
??? kfree(master);
err:
??? return ret;
}

4.3??? SPI Master
每一個SPI master都要實現(xiàn)setup、transfer及cleanup等。
static int mpc83xx_spi_setup(struct spi_device *spi)
static int mpc83xx_spi_bufs(struct spi_device *spi, struct spi_transfer *t)

mpc83xx_spi->bitbang.txrx_bufs = mpc83xx_spi_bufs;

MPC837x SPI Master的具體實現(xiàn)待續(xù)。
5??? 硬件抽象層-SPI core
5.1??? 總線初始化?
static int __init spi_init(void)
{
??? int??? status;

??? buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
??? if (!buf) {
??? ??? status = -ENOMEM;
??? ??? goto err0;
??? }

??? status = bus_register(&spi_bus_type);
??? if (status < 0)
??? ??? goto err1;

??? status = class_register(&spi_master_class);
??? if (status < 0)
??? ??? goto err2;
??? return 0;

err2:
??? bus_unregister(&spi_bus_type);
err1:
??? kfree(buf);
??? buf = NULL;
err0:
??? return status;
}

/* board_info is normally registered in arch_initcall(),
?* but even essential drivers wait till later
?*
?* REVISIT only boardinfo really needs static linking. the rest (device and
?* driver registration) _could_ be dynamically linked (modular) ... costs
?* include needing to have boardinfo data structures be much more public.
?*/
subsys_initcall(spi_init);

關(guān)于被subsys_initcall修飾的spi_init何時初始化,請參考下文《詳解Linux2.6內(nèi)核中基于platform機制的驅(qū)動模型》
http://blog.csdn.net/sailor_8318/archive/2010/01/29/5267698.aspx
此時platform bus及platform device已經(jīng)注冊完畢,因此SPI控制器的相關(guān)資源已經(jīng)就緒。

5.2??? Master注冊
/**
?* spi_register_master - register SPI master controller
?* @master: initialized master, originally from spi_alloc_master()
?* Context: can sleep
?*
?* SPI master controllers connect to their drivers using some non-SPI bus,
?* such as the platform bus.? The final stage of probe() in that code
?* includes calling spi_register_master() to hook up to this SPI bus glue.
?*
?* SPI controllers use board specific (often SOC specific) bus numbers,
?* and board-specific addressing for SPI devices combines those numbers
?* with chip select numbers.? Since SPI does not directly support dynamic
?* device identification, boards need configuration tables telling which
?* chip is at which address.
?*/
int spi_register_master(struct spi_master *master)
{
??? static atomic_t??? ??? dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
??? struct device??? ??? *dev = master->dev.parent;
??? int??? ??? ??? status = -ENODEV;
??? int??? ??? ??? dynamic = 0;

??? if (!dev)
??? ??? return -ENODEV;

??? /* even if it's just one always-selected device, there must
??? ?* be at least one chipselect
??? ?*/
??? if (master->num_chipselect == 0)
??? ??? return -EINVAL;

??? /* convention:? dynamically assigned bus IDs count down from the max */
??? if (master->bus_num < 0) {
??? ??? /* FIXME switch to an IDR based scheme, something like
??? ??? ?* I2C now uses, so we can't run out of "dynamic" IDs
??? ??? ?*/
??? ??? master->bus_num = atomic_dec_return(&dyn_bus_id);
??? ??? dynamic = 1;
??? }

??? /* register the device, then userspace will see it.
??? ?* registration fails if the bus ID is in use.
??? ?*/
??? snprintf(master->dev.bus_id, sizeof master->dev.bus_id,
??? ??? "spi%u", master->bus_num);
??? status = device_add(&master->dev);
??? if (status < 0)
??? ??? goto done;
??? dev_dbg(dev, "registered master %s%s/n", master->dev.bus_id,
??? ??? ??? dynamic ? " (dynamic)" : "");

??? /* populate children from any spi device tables */
??? scan_boardinfo(master);
??? status = 0;
done:
??? return status;
}
EXPORT_SYMBOL_GPL(spi_register_master);

static void scan_boardinfo(struct spi_master *master)
{
??? struct boardinfo??? *bi;

??? mutex_lock(&board_lock);
??? list_for_each_entry(bi, &board_list, list) {//board list已經(jīng)在platform device注冊時初始化
??? ??? struct spi_board_info??? *chip = bi->board_info;
??? ??? unsigned??? ??? n;

??? ??? for (n = bi->n_board_info; n > 0; n--, chip++) {
??? ??? ??? if (chip->bus_num != master->bus_num)? //Master的總線號和相應(yīng)slave所在的總線號匹配
??? ??? ??? ??? continue;
??? ??? ??? /* NOTE: this relies on spi_new_device to
??? ??? ??? ?* issue diagnostics when given bogus inputs
??? ??? ??? ?*/
??? ??? ??? (void) spi_new_device(master, chip);
??? ??? }
??? }
??? mutex_unlock(&board_lock);
}

/**
?* spi_new_device - instantiate one new SPI device
?* @master: Controller to which device is connected
?* @chip: Describes the SPI device
?* Context: can sleep
* Returns the new device, or NULL.
?*/
struct spi_device *spi_new_device(struct spi_master *master,
??? ??? ??? ??? ? struct spi_board_info *chip)
{
??? struct spi_device??? *proxy;
??? struct device??? ??? *dev = master->dev.parent;
??? int??? ??? ??? status;

??? /* NOTE:? caller did any chip->bus_num checks necessary.
??? ?*/

??? /* Chipselects are numbered 0..max; validate. */
??? if (chip->chip_select >= master->num_chipselect) {
??? ??? dev_err(dev, "cs%d > max %d/n",
??? ??? ??? chip->chip_select,
??? ??? ??? master->num_chipselect);
??? ??? return NULL;
??? }

??? if (!spi_master_get(master))
??? ??? return NULL;

??? proxy = kzalloc(sizeof *proxy, GFP_KERNEL);? //分配一個SPI device
??? if (!proxy) {
??? ??? dev_err(dev, "can't alloc dev for cs%d/n",
??? ??? ??? chip->chip_select);
??? ??? goto fail;
??? }

??? proxy->master = master;? // SPI slave所依附的SPI Master
??? proxy->chip_select = chip->chip_select;? // 保存board info中特定的屬性,板級移植需要關(guān)注
??? proxy->max_speed_hz = chip->max_speed_hz;
??? proxy->mode = chip->mode;
??? proxy->irq = chip->irq;
??? proxy->modalias = chip->modalias;

??? snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id,
??? ??? ??? "%s.%u", master->dev.bus_id,
??? ??? ??? chip->chip_select);
??? proxy->dev.parent = dev;
??? proxy->dev.bus = &spi_bus_type;?? //此設(shè)備所依附的總線為SPI
??? proxy->dev.platform_data = (void *) chip->platform_data;
??? proxy->controller_data = chip->controller_data;
??? proxy->controller_state = NULL;
??? proxy->dev.release = spidev_release;

??? /* drivers may modify this initial i/o setup */
??? status = master->setup(proxy);
??? if (status < 0) {
??? ??? dev_err(dev, "can't %s %s, status %d/n",
??? ??? ??? ??? "setup", proxy->dev.bus_id, status);
??? ??? goto fail;
??? }

??? /* driver core catches callers that misbehave by defining
??? ?* devices that already exist.
??? ?*/
??? status = device_register(&proxy->dev);? // 將該SPI device掛接到SPI總線上
??? if (status < 0) {
??? ??? dev_err(dev, "can't %s %s, status %d/n",
??? ??? ??? ??? "add", proxy->dev.bus_id, status);
??? ??? goto fail;
??? }
??? dev_dbg(dev, "registered child %s/n", proxy->dev.bus_id);
??? return proxy;

fail:
??? spi_master_put(master);
??? kfree(proxy);
??? return NULL;
}
EXPORT_SYMBOL_GPL(spi_new_device);

5.3??? 驅(qū)動注冊
/**
?* spi_register_driver - register a SPI driver
?* @sdrv: the driver to register
?* Context: can sleep
?*/
int spi_register_driver(struct spi_driver *sdrv)
{
??? sdrv->driver.bus = &spi_bus_type;
??? if (sdrv->probe)
??? ??? sdrv->driver.probe = spi_drv_probe;
??? if (sdrv->remove)
??? ??? sdrv->driver.remove = spi_drv_remove;
??? if (sdrv->shutdown)
??? ??? sdrv->driver.shutdown = spi_drv_shutdown;
??? return driver_register(&sdrv->driver);
}
EXPORT_SYMBOL_GPL(spi_register_driver);

SPI driver采用內(nèi)核通用的驅(qū)動模型,其流程和platform driver的注冊過程類似,請請參考下文《詳解Linux2.6內(nèi)核中基于platform機制的驅(qū)動模型》
http://blog.csdn.net/sailor_8318/archive/2010/01/29/5267698.aspx
5.4??? 數(shù)據(jù)傳輸
/**
?* spi_sync - blocking/synchronous SPI data transfers
?* @spi: device with which data will be exchanged
?* @message: describes the data transfers
?* Context: can sleep
?*
?* This call may only be used from a context that may sleep.? The sleep
?* is non-interruptible, and has no timeout.? Low-overhead controller
?* drivers may DMA directly into and out of the message buffers.
?*
?* Note that the SPI device's chip select is active during the message,
?* and then is normally disabled between messages.? Drivers for some
?* frequently-used devices may want to minimize costs of selecting a chip,
?* by leaving it selected in anticipation that the next message will go
?* to the same chip.? (That may increase power usage.)
?*
?* Also, the caller is guaranteeing that the memory associated with the
?* message will not be freed before this call returns.
?*
?* It returns zero on success, else a negative error code.
?*/
int spi_sync(struct spi_device *spi, struct spi_message *message)
{
??? DECLARE_COMPLETION_ONSTACK(done);
??? int status;

??? message->complete = spi_complete;
??? message->context = &done;
??? status = spi_async(spi, message);
??? if (status == 0) {
??? ??? wait_for_completion(&done);
??? ??? status = message->status;
??? }
??? message->context = NULL;
??? return status;
}
EXPORT_SYMBOL_GPL(spi_sync);
同步接口,待數(shù)據(jù)收發(fā)完畢后才返回,只能在非中斷上下文中使用。

/**
?* spi_async - asynchronous SPI transfer
?* @spi: device with which data will be exchanged
?* @message: describes the data transfers, including completion callback
?* Context: any (irqs may be blocked, etc)
?*
?* This call may be used in_irq and other contexts which can't sleep,
?* as well as from task contexts which can sleep.
?*
?* The completion callback is invoked in a context which can't sleep.
?* Before that invocation, the value of message->status is undefined.
?* When the callback is issued, message->status holds either zero (to
?* indicate complete success) or a negative error code.? After that
?* callback returns, the driver which issued the transfer request may
?* deallocate the associated memory; it's no longer in use by any SPI
?* core or controller driver code.
?*
?* Note that although all messages to a spi_device are handled in
?* FIFO order, messages may go to different devices in other orders.
?* Some device might be higher priority, or have various "hard" access
?* time requirements, for example.
?*
?* On detection of any fault during the transfer, processing of
?* the entire message is aborted, and the device is deselected.
?* Until returning from the associated message completion callback,
?* no other spi_message queued to that device will be processed.
?* (This rule applies equally to all the synchronous transfer calls,
?* which are wrappers around this core asynchronous primitive.)
?*/
static inline int spi_async(struct spi_device *spi, struct spi_message *message)
{
??? message->spi = spi;
??? return spi->master->transfer(spi, message);
}
異步接口,根據(jù)spi device找到其所在的spi master,用master所特定的transfer函數(shù)實現(xiàn)數(shù)據(jù)收發(fā)。

核心層提供的通用數(shù)據(jù)收發(fā)接口,屏蔽了底層差異。

6??? 用戶接口層-SPI設(shè)備驅(qū)動
6.1??? 統(tǒng)一的設(shè)備模型
此驅(qū)動模型是針對SPI Slave的,只有注冊board info時modalias是spidev的才能由此驅(qū)動訪問。訪問各個slave的基本框架是一致的,具體的差異將由從設(shè)備號來體現(xiàn)。
6.1.1??? 關(guān)鍵數(shù)據(jù)結(jié)構(gòu)
static struct spi_driver spidev_spi = {
??? .driver = {
??? ??? .name =??? ??? "spidev",
??? ??? .owner =??? THIS_MODULE,
??? },
??? .probe =??? spidev_probe,
??? .remove =??? __devexit_p(spidev_remove),
};
定義了一個標(biāo)準(zhǔn)的SPI_driver。

struct spidev_data {
??? struct device??? ??? dev;
??? struct spi_device??? *spi;
??? struct list_head??? device_entry;

??? struct mutex??? ??? buf_lock;
??? unsigned??? ??? users;
??? u8??? ??? ??? *buffer;
};

static LIST_HEAD(device_list);
static DEFINE_MUTEX(device_list_lock);
定義了一個SPI dev列表,每個slave對應(yīng)一個struct spidev_data, 以device_entry為節(jié)點連接在device_list上。

static struct file_operations spidev_fops = {
??? .owner =??? THIS_MODULE,
??? .write =??? spidev_write,
??? .read =??? ??? spidev_read,
??? .ioctl =??? spidev_ioctl,
??? .open =??? ??? spidev_open,
??? .release =??? spidev_release,
};
任意一個需要和用戶空間通信的驅(qū)動必備的數(shù)據(jù)結(jié)構(gòu),其定義了具體的讀寫操作方法。

6.1.2??? 初始化
http://lxr.linux.no/#linux+v2.6.25/drivers/SPI/SPI-dev.c#L607

static int __init spidev_init(void)
{
??? int status;

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

??? status = class_register(&spidev_class);
??? if (status < 0) {
??? ??? unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);
??? ??? return status;
??? }

??? status = spi_register_driver(&spidev_spi);
??? if (status < 0) {
??? ??? class_unregister(&spidev_class);
??? ??? unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);
??? }
??? return status;
}
module_init(spidev_init);

首先注冊了一個字符型設(shè)備驅(qū)動,然后注冊spi_driver,其將在SPI總線上查找對應(yīng)的設(shè)備,根據(jù)關(guān)鍵字spidev進(jìn)行匹配,匹配成功后將調(diào)用spi_driver的probe方法,即spidev_probe,將驅(qū)動和每一個salve綁定起來,并建立對應(yīng)的dev設(shè)備節(jié)點,同時維護了一個spidev_data鏈表。

static int spidev_probe(struct spi_device *spi)
{
??? struct spidev_data??? *spidev;
??? int??? ??? ??? status;
??? unsigned long??? ??? minor;

??? /* Allocate driver data */
??? spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);
??? if (!spidev)
??? ??? return -ENOMEM;

??? /* Initialize the driver data */
??? spidev->spi = spi;
??? mutex_init(&spidev->buf_lock);

??? INIT_LIST_HEAD(&spidev->device_entry);

??? /* If we can allocate a minor number, hook up this device.
??? ?* Reusing minors is fine so long as udev or mdev is working.
??? ?*/
??? mutex_lock(&device_list_lock);
??? minor = find_first_zero_bit(minors, N_SPI_MINORS);
??? if (minor < N_SPI_MINORS) {
??? ??? spidev->dev.parent = &spi->dev;
??? ??? spidev->dev.class = &spidev_class;
??? ??? spidev->dev.devt = MKDEV(SPIDEV_MAJOR, minor);? //各個slave的從設(shè)備號是從0依次遞增的
??? ??? snprintf(spidev->dev.bus_id, sizeof spidev->dev.bus_id,
??? ??? ??? ??? "spidev%d.%d",
??? ??? ??? ??? spi->master->bus_num, spi->chip_select);
??? ??? status = device_register(&spidev->dev);
??? } else {
??? ??? dev_dbg(&spi->dev, "no minor number available!/n");
??? ??? status = -ENODEV;
??? }
??? if (status == 0) {
??? ??? set_bit(minor, minors);
??? ??? dev_set_drvdata(&spi->dev, spidev);
??? ??? list_add(&spidev->device_entry, &device_list);? // 將該SPI dev添加到SPI device列表中
??? }
??? mutex_unlock(&device_list_lock);

??? if (status != 0)
??? ??? kfree(spidev);

??? return status;
}
以SPI_MAJOR和動態(tài)從設(shè)備號為主從設(shè)備號注冊設(shè)備節(jié)點,如果系統(tǒng)有udev或者是hotplug,那么就會在/dev下自動創(chuàng)建相關(guān)的設(shè)備節(jié)點了,其名稱命名方式為spidevB.C,B為總線編號,C為片選序號。

6.1.3??? Open及release
static int spidev_open(struct inode *inode, struct file *filp)
{
??? struct spidev_data??? *spidev;
??? int??? ??? ??? status = -ENXIO;

??? mutex_lock(&device_list_lock);

??? list_for_each_entry(spidev, &device_list, device_entry) {
??? ??? if (spidev->dev.devt == inode->i_rdev) {? // 根據(jù)設(shè)備節(jié)點號進(jìn)行匹配查找對應(yīng)的spidev_data節(jié)點從而找到相應(yīng)的從設(shè)備
??? ??? ??? status = 0;
??? ??? ??? break;
??? ??? }
??? }
??? if (status == 0) {
??? ??? if (!spidev->buffer) {
??? ??? ??? spidev->buffer = kmalloc(bufsiz, GFP_KERNEL);? // 為每個slave分配了一段緩沖區(qū)
??? ??? ??? if (!spidev->buffer) {
??? ??? ??? ??? dev_dbg(&spidev->spi->dev, "open/ENOMEM/n");
??? ??? ??? ??? status = -ENOMEM;
??? ??? ??? }
??? ??? }
??? ??? if (status == 0) {
??? ??? ??? spidev->users++;? // 訪問該SPI slave的user加1
??? ??? ??? filp->private_data = spidev;?? //面向?qū)ο蟮牡湫蛻?yīng)用,將特定數(shù)據(jù)保存在filp->private_data中,其他函數(shù)可以直接從filp->private_data中取出需要的東西,避免過多的使用全局變量來傳遞信息
??? ??? ??? nonseekable_open(inode, filp);
??? ??? }
??? } else
??? ??? pr_debug("spidev: nothing for minor %d/n", iminor(inode));

??? mutex_unlock(&device_list_lock);
??? return status;
}?


static int spidev_release(struct inode *inode, struct file *filp)
{
??? struct spidev_data??? *spidev;
??? int??? ??? ??? status = 0;

??? mutex_lock(&device_list_lock);
??? spidev = filp->private_data;
??? filp->private_data = NULL;
??? spidev->users--;
??? if (!spidev->users) {? // 無用戶再訪問該slave時才釋放其buffer
??? ??? kfree(spidev->buffer);
??? ??? spidev->buffer = NULL;
??? }
??? mutex_unlock(&device_list_lock);

??? return status;
}

Open操作是用戶空間程序和內(nèi)核驅(qū)動交換的第一步,最終返回給用戶空間的就是struct file結(jié)構(gòu)體。對于SPI 驅(qū)動來說,用戶空間所獲得的就是spidev這個關(guān)鍵信息。
6.1.4??? 數(shù)據(jù)收發(fā)
對于SPI驅(qū)動來說,數(shù)據(jù)收發(fā)有兩種途徑,read/write或者ioctl方式。但無論哪種方式,最終都是構(gòu)造一個spi_message。

/**
?* struct spi_message - one multi-segment SPI transaction
?* @transfers: list of transfer segments in this transaction
?* @spi: SPI device to which the transaction is queued
?* @is_dma_mapped: if true, the caller provided both dma and cpu virtual
?*??? addresses for each transfer buffer
?* @complete: called to report transaction completions
?* @context: the argument to complete() when it's called
?* @actual_length: the total number of bytes that were transferred in all
?*??? successful segments
?* @status: zero for success, else negative errno
?* @queue: for use by whichever driver currently owns the message
?* @state: for use by whichever driver currently owns the message
?*
?* A @spi_message is used to execute an atomic sequence of data transfers,
?* each represented by a struct spi_transfer.? The sequence is "atomic"
?* in the sense that no other spi_message may use that SPI bus until that
?* sequence completes.? On some systems, many such sequences can execute
?* as single programmed DMA transfer.? On all systems, these messages are
?* queued, and might complete after transactions to other devices.? Messages
?* sent to a given spi_device are always executed in FIFO order.
?*
*/
struct spi_message {
??? struct list_head??? transfers;? // 所包含的spi_transfer鏈表
??? struct spi_device??? *spi;? // 消息所發(fā)往的對象
??? unsigned??? ??? is_dma_mapped:1;

??? /* completion is reported through a callback */
??? void??? ??? ??? (*complete)(void *context);? //消息發(fā)送完畢后的回調(diào)函數(shù)
??? void??? ??? ??? *context;
??? unsigned??? ??? actual_length;
??? int??? ??? ??? status;

??? /* for optional use by whatever driver currently owns the
??? ?* spi_message ...? between calls to spi_async and then later
??? ?* complete(), that's the spi_master controller driver.
??? ?*/
??? struct list_head??? queue;? // spi_message會由SPI Maser驅(qū)動統(tǒng)一組織成鏈表,順序處理,以此防止各個spi slave同時訪問總線而導(dǎo)致沖突
??? void??? ??? ??? *state;
};

spi_message 包含了一系列spi_transfer,在所有的spi_transfer發(fā)送完畢前,SPI總線一直被占據(jù),其間不會出現(xiàn)總線沖突,因此一個spi_message是一個原子系列,這種特性非常利于復(fù)雜的SPI通信協(xié)議,如先發(fā)送命令字然后才能讀取數(shù)據(jù)。

/*
?* I/O INTERFACE between SPI controller and protocol drivers
?*
?* Protocol drivers use a queue of spi_messages, each transferring data
?* between the controller and memory buffers.
?*
?* The spi_messages themselves consist of a series of read+write transfer
?* segments.? Those segments always read the same number of bits as they
?* write; but one or the other is easily ignored by passing a null buffer
?* pointer.? (This is unlike most types of I/O API, because SPI hardware
?* is full duplex.)
?*
*/

/**
?* struct spi_transfer - a read/write buffer pair
?* @tx_buf: data to be written (dma-safe memory), or NULL
?* @rx_buf: data to be read (dma-safe memory), or NULL
?* @tx_dma: DMA address of tx_buf, if @spi_message.is_dma_mapped
?* @rx_dma: DMA address of rx_buf, if @spi_message.is_dma_mapped
?* @len: size of rx and tx buffers (in bytes)
?* @speed_hz: Select a speed other then the device default for this
?*????? transfer. If 0 the default (from @spi_device) is used.
?* @bits_per_word: select a bits_per_word other then the device default
?*????? for this transfer. If 0 the default (from @spi_device) is used.
?* @cs_change: affects chipselect after this transfer completes
?* @delay_usecs: microseconds to delay after this transfer before
?*??? (optionally) changing the chipselect status, then starting
?*??? the next transfer or completing this @spi_message.
?* @transfer_list: transfers are sequenced through @spi_message.transfers
?*
?* SPI transfers always write the same number of bytes as they read.
?* Protocol drivers should always provide @rx_buf and/or @tx_buf.
?*
?* If the transmit buffer is null, zeroes will be shifted out
?* while filling @rx_buf.? If the receive buffer is null, the data
?* shifted in will be discarded.? Only "len" bytes shift out (or in).
?* It's an error to try to shift out a partial word.? (For example, by
?* shifting out three bytes with word size of sixteen or twenty bits;
?* the former uses two bytes per word, the latter uses four bytes.)
?*
?* In-memory data values are always in native CPU byte order, translated
?* from the wire byte order (big-endian except with SPI_LSB_FIRST).? So
?* for example when bits_per_word is sixteen, buffers are 2N bytes long
?* (@len = 2N) and hold N sixteen bit words in CPU byte order.
?*
?* When the word size of the SPI transfer is not a power-of-two multiple
?* of eight bits, those in-memory words include extra bits.? In-memory
?* words are always seen by protocol drivers as right-justified, so the
?* undefined (rx) or unused (tx) bits are always the most significant bits.
?*
?* All SPI transfers start with the relevant chipselect active.? Normally
?* it stays selected until after the last transfer in a message.? Drivers
?* can affect the chipselect signal using cs_change.
?*
?* (i) If the transfer isn't the last one in the message, this flag is
?* used to make the chipselect briefly go inactive in the middle of the
?* message.? Toggling chipselect in this way may be needed to terminate
?* a chip command, letting a single spi_message perform all of group of
?* chip transactions together.
?*
?* (ii) When the transfer is the last one in the message, the chip may
?* stay selected until the next transfer.? On multi-device SPI busses
?* with nothing blocking messages going to other devices, this is just
?* a performance hint; starting a message to another device deselects
?* this one.? But in other cases, this can be used to ensure correctness.
?* Some devices need protocol transactions to be built from a series of
?* spi_message submissions, where the content of one message is determined
?* by the results of previous messages and where the whole transaction
?* ends when the chipselect goes intactive.
?*
?* The code that submits an spi_message (and its spi_transfers)
?* to the lower layers is responsible for managing its memory.
?* Zero-initialize every field you don't set up explicitly, to
?* insulate against future API updates.? After you submit a message
?* and its transfers, ignore them until its completion callback.
?*/
struct spi_transfer {
??? const void??? *tx_buf;
??? void??? ??? *rx_buf;
??? unsigned??? len;

??? dma_addr_t??? tx_dma;
??? dma_addr_t??? rx_dma;

??? unsigned??? cs_change:1;
??? u8??? ??? bits_per_word;
??? u16??? ??? delay_usecs;
??? u32??? ??? speed_hz;

??? struct list_head transfer_list;
};
一個spi_transfer是以某種特性如速率、延時及字長連續(xù)傳輸?shù)淖钚挝弧R驗镾PI是全雙工總線,只要總線上有數(shù)據(jù)傳輸,則MOSI和MISO上同時有數(shù)據(jù)采樣,對于SPI 控制器來說,其收發(fā)緩沖區(qū)中都有數(shù)據(jù),但是對于用戶來說,其可以靈活的選擇tx_buf和rx_buf的設(shè)置。當(dāng)發(fā)送數(shù)據(jù)時,tx_buf必須設(shè)置為待發(fā)送的數(shù)據(jù),rx_buf可以為null或者指向無用的緩沖區(qū),即不關(guān)心MISO的數(shù)據(jù)。而當(dāng)接收數(shù)據(jù)時,rx_buf必須指向接收緩沖區(qū),而tx_buf可以為Null,則MOSI上為全0,或者tx_buf指向不會引起從設(shè)備異常相應(yīng)的數(shù)據(jù)。Len為待發(fā)送或者接收的數(shù)據(jù)長度。當(dāng)一系列spi_transfer構(gòu)成一個spi_message時,cs_change的設(shè)置非常講究。當(dāng)cs_change為0即不變時,則可以連續(xù)對同一個設(shè)備進(jìn)行數(shù)據(jù)收發(fā);當(dāng)cs_change為1時通常用來停止command的傳輸而隨后進(jìn)行數(shù)據(jù)接收。因此cs_change可以利用SPI總線構(gòu)造復(fù)雜的通信協(xié)議。

對于SPI總線協(xié)議來說,傳輸單位可以是4-32之間的任意bits,但對于SPI控制器來說,bits_per_word只能是8/16/32,即需要取整,待收發(fā)的數(shù)據(jù)在內(nèi)存里都是以主機字節(jié)序右對齊存儲,SPI控制器會自動根據(jù)傳輸單位及大小端進(jìn)行轉(zhuǎn)換。

對于read/write方式來說,如果不采用board info中的默認(rèn)設(shè)置,則必須先通過ioctl方式設(shè)置該從設(shè)備特定的大小端、bits per word及速率等特性,后續(xù)數(shù)據(jù)傳輸時將一直采用此設(shè)置。

read/write與用戶空間的接口是buf和count,分別為收發(fā)的相應(yīng)數(shù)據(jù)指針和數(shù)據(jù)長度。

/* Read-only message with current device setup */
static ssize_t spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
??? struct spidev_data??? *spidev;
??? struct spi_device??? *spi;
??? ssize_t??? ??? ??? status = 0;

??? /* chipselect only toggles at start or end of operation */? // 在count個數(shù)據(jù)發(fā)送期間,該slave的片選一直有效
??? if (count > bufsiz)
??? ??? return -EMSGSIZE;

??? spidev = filp->private_data;
??? spi = spidev->spi;

??? mutex_lock(&spidev->buf_lock); // 對同一個SPI slave的互斥訪問
??? status = spi_read(spi, spidev->buffer, count);
??? if (status == 0) {
??? ??? unsigned long??? missing;

??? ??? missing = copy_to_user(buf, spidev->buffer, count);
??? ??? if (count && missing == count)
??? ??? ??? status = -EFAULT;
??? ??? else
??? ??? ??? status = count - missing;
??? }
??? mutex_unlock(&spidev->buf_lock);

??? return status;
}


/**
?* spi_read - SPI synchronous read
?* @spi: device from which data will be read
?* @buf: data buffer
?* @len: data buffer size
?* Context: can sleep
?*
?* This reads the buffer and returns zero or a negative error code.
?* Callable only from contexts that can sleep.
?*/
static inline int spi_read(struct spi_device *spi, u8 *buf, size_t len)
{
??? struct spi_transfer??? t = {
??? ??? ??? .rx_buf??? ??? = buf,
??? ??? ??? .len??? ??? = len,
??? ??? };
??? struct spi_message??? m;

??? spi_message_init(&m);
??? spi_message_add_tail(&t, &m);
??? return spi_sync(spi, &m);
}
自動構(gòu)建一個spi_message,其只包含一個spi_transfer。

/* Write-only message with current device setup */
static ssize_t spidev_write(struct file *filp, const char __user *buf,
??? ??? size_t count, loff_t *f_pos)
{
??? struct spidev_data??? *spidev;
??? struct spi_device??? *spi;
??? ssize_t??? ??? ??? status = 0;
??? unsigned long??? ??? missing;

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

??? spidev = filp->private_data;
??? spi = spidev->spi;

??? mutex_lock(&spidev->buf_lock);
??? missing = copy_from_user(spidev->buffer, buf, count); // 將待發(fā)送的數(shù)據(jù)從用戶空間拷貝至內(nèi)核空間
??? if (missing == 0) {
??? ??? status = spi_write(spi, spidev->buffer, count);
??? ??? if (status == 0)
??? ??? ??? status = count;
??? } else
??? ??? status = -EFAULT;
??? mutex_unlock(&spidev->buf_lock);

??? return status;
}

對于ioctl方式,默認(rèn)情況下就是進(jìn)行數(shù)據(jù)收發(fā)。

IO ctrl方式與用戶空間的接口為spi_ioc_transfer,其數(shù)據(jù)結(jié)構(gòu)如下:
/**
?* struct spi_ioc_transfer - describes a single SPI transfer
?* @tx_buf: Holds pointer to userspace buffer with transmit data, or null.
?*??? If no data is provided, zeroes are shifted out.
?* @rx_buf: Holds pointer to userspace buffer for receive data, or null.
?* @len: Length of tx and rx buffers, in bytes.
?* @speed_hz: Temporary override of the device's bitrate.
?* @bits_per_word: Temporary override of the device's wordsize.
?* @delay_usecs: If nonzero, how long to delay after the last bit transfer
?*??? before optionally deselecting the device before the next transfer.
?* @cs_change: True to deselect device before starting the next transfer.
?*
?* This structure is mapped directly to the kernel spi_transfer structure;
?* the fields have the same meanings, except of course that the pointers
?* are in a different address space (and may be of different sizes in some
?* cases, such as 32-bit i386 userspace over a 64-bit x86_64 kernel).
?* Zero-initialize the structure, including currently unused fields, to
?* accomodate potential future updates.
?*
?* SPI_IOC_MESSAGE gives userspace the equivalent of kernel spi_sync().
?* Pass it an array of related transfers, they'll execute together.
?* Each transfer may be half duplex (either direction) or full duplex.
?*
?*??? struct spi_ioc_transfer mesg[4];
?*??? ...
?*??? status = ioctl(fd, SPI_IOC_MESSAGE(4), mesg);
?*
?* So for example one transfer might send a nine bit command (right aligned
?* in a 16-bit word), the next could read a block of 8-bit data before
?* terminating that command by temporarily deselecting the chip; the next
?* could send a different nine bit command (re-selecting the chip), and the
?* last transfer might write some register values.
?*/
struct spi_ioc_transfer {
??? __u64??? ??? tx_buf;
??? __u64??? ??? rx_buf;

??? __u32??? ??? len;
??? __u32??? ??? speed_hz;

??? __u16??? ??? delay_usecs;
??? __u8??? ??? bits_per_word;
??? __u8??? ??? cs_change;
??? __u32??? ??? pad;

};
spi_ioc_transfer可以動態(tài)的改變各種傳輸特性,并且可以將多個spi_ioc_transfer組織成一個message連續(xù)傳輸,比read/write方式提供了更多靈活性。

static int spidev_ioctl(struct inode *inode, 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 command number */
??? 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;

??? spidev = filp->private_data;
??? spi = spidev->spi;? // 找到對應(yīng)的struct spi_device

??? switch (cmd) {
??? /* read requests */? // 讀取該slave的相關(guān)屬性
??? case SPI_IOC_RD_MODE:

??? case SPI_IOC_RD_LSB_FIRST:

??? case SPI_IOC_RD_BITS_PER_WORD:

??? 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;? //更新相關(guān)屬性
??? ??? ??? retval = spi_setup(spi);? //使相關(guān)屬性生效,在此不設(shè)置也可以,因為每次傳輸時都會重新設(shè)置SPI master
??? ??? ??? if (retval < 0)
??? ??? ??? ??? spi->mode = save;
??? ??? ??? else
??? ??? ??? ??? dev_dbg(&spi->dev, "spi mode %02x/n", tmp);
??? ??? }
??? ??? break;
??? case SPI_IOC_WR_LSB_FIRST:
??? ??? 。。。
??? case SPI_IOC_WR_BITS_PER_WORD:
。。。
??? case SPI_IOC_WR_MAX_SPEED_HZ:
。。。

??? default:
??? ??? /* segmented and/or full-duplex I/O request */
??? ??? if (_IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0))
??? ??? ??? ??? || _IOC_DIR(cmd) != _IOC_WRITE)
??? ??? ??? return -ENOTTY;

??? ??? 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;
??? }
??? return retval;
}


static int spidev_message(struct spidev_data *spidev,
??? ??? struct spi_ioc_transfer *u_xfers, unsigned n_xfers)
{
??? struct spi_message??? msg;
??? struct spi_transfer??? *k_xfers;
??? struct spi_transfer??? *k_tmp;
??? struct spi_ioc_transfer *u_tmp;
??? struct spi_device??? *spi = spidev->spi;
??? unsigned??? ??? n, total;
??? u8??? ??? ??? *buf;
??? int??? ??? ??? status = -EFAULT;

??? spi_message_init(&msg);
??? k_xfers = kcalloc(n_xfers, sizeof(*k_tmp), GFP_KERNEL);
??? if (k_xfers == NULL)
??? ??? return -ENOMEM;

??? /* Construct spi_message, copying any tx data to bounce buffer.
??? ?* We walk the array of user-provided transfers, using each one
??? ?* to initialize a kernel version of the same transfer.
??? ?*/
??? mutex_lock(&spidev->buf_lock);
??? buf = spidev->buffer;
??? total = 0;
??? for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;
??? ??? ??? n;
??? ??? ??? n--, k_tmp++, u_tmp++) {
??? ??? k_tmp->len = u_tmp->len;

??? ??? total += k_tmp->len;
??? ??? if (total > bufsiz) {
??? ??? ??? status = -EMSGSIZE;
??? ??? ??? goto done;
??? ??? }

??? ??? if (u_tmp->rx_buf) {
??? ??? ??? k_tmp->rx_buf = buf;
??? ??? ??? if (!access_ok(VERIFY_WRITE, (u8 __user *)
??? ??? ??? ??? ??? ??? (uintptr_t) u_tmp->rx_buf,
??? ??? ??? ??? ??? ??? u_tmp->len))
??? ??? ??? ??? goto done;
??? ??? }
??? ??? if (u_tmp->tx_buf) {
??? ??? ??? k_tmp->tx_buf = buf;
??? ??? ??? if (copy_from_user(buf, (const u8 __user *)
??? ??? ??? ??? ??? ??? (uintptr_t) u_tmp->tx_buf,
??? ??? ??? ??? ??? u_tmp->len))
??? ??? ??? ??? goto done;
??? ??? }
??? ??? buf += k_tmp->len;
??? ??? // 將用戶指定的傳輸屬性保存起來,構(gòu)成內(nèi)核 spi_transfer
??? ??? k_tmp->cs_change = !!u_tmp->cs_change;??
??? ??? k_tmp->bits_per_word = u_tmp->bits_per_word;
??? ??? k_tmp->delay_usecs = u_tmp->delay_usecs;
??? ??? k_tmp->speed_hz = u_tmp->speed_hz;

??? ??? spi_message_add_tail(k_tmp, &msg);? // 將多個spi_transfer組織為spi_message
??? }

??? status = spi_sync(spi, &msg);
??? if (status < 0)
??? ??? goto done;

??? /* copy any rx data out of bounce buffer */
??? buf = spidev->buffer;
??? for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) {
??? ??? if (u_tmp->rx_buf) {? //當(dāng)用戶設(shè)置了rx buf時才將數(shù)據(jù)拷貝到用戶空間
??? ??? ??? if (__copy_to_user((u8 __user *)
??? ??? ??? ??? ??? (uintptr_t) u_tmp->rx_buf, buf,
??? ??? ??? ??? ??? u_tmp->len)) {
??? ??? ??? ??? status = -EFAULT;
??? ??? ??? ??? goto done;
??? ??? ??? }
??? ??? }
??? ??? buf += u_tmp->len;
??? }
??? status = total;

done:
??? mutex_unlock(&spidev->buf_lock);
??? kfree(k_xfers);
??? return status;
}

6.2??? 特定的設(shè)備驅(qū)動
原則上所有的SPI從設(shè)備都可以通過上述統(tǒng)一的設(shè)備模型spidev來訪問,但SPI 總線上傳輸?shù)氖峭该鞯臄?shù)據(jù),而對于某些SPI從設(shè)備,其數(shù)據(jù)傳輸需要遵循一定的格式,如果用spidev來訪問,則用戶需要組織好所有的spi_transfer,對一般用戶來說可能比較復(fù)雜。為了提供更加user friendly的接口,可以對特定SPI從設(shè)備的訪問進(jìn)行再次封裝。

如SPI接口的MMC卡,其數(shù)據(jù)的轉(zhuǎn)換較為復(fù)雜,為了減少用戶空間的轉(zhuǎn)換,提供了專用的MMC驅(qū)動供用戶程序訪問,其向上屏蔽了具體MMC芯片的差異。

下面以drivers/mmc/host/mmc_spi.c為例來進(jìn)行講述。
6.2.1??? 關(guān)鍵數(shù)據(jù)結(jié)構(gòu)
struct mmc_spi_host {
??? struct mmc_host??? ??? *mmc;
??? struct spi_device??? *spi;? // MMC卡對應(yīng)的SPI 設(shè)備

??? unsigned char??? ??? power_mode;
??? u16??? ??? ??? powerup_msecs;

??? struct mmc_spi_platform_data??? *pdata;

??? /* for bulk data transfers */
??? struct spi_transfer??? token, t, crc, early_status;? //SD/MMC卡協(xié)議對應(yīng)的各種transfer
??? struct spi_message??? m;

??? /* for status readback */
??? struct spi_transfer??? status;
??? struct spi_message??? readback;

??? /* underlying DMA-aware controller, or null */
??? struct device??? ??? *dma_dev;

??? /* buffer used for commands and for message "overhead" */
??? struct scratch??? ??? *data;
??? dma_addr_t??? ??? data_dma;

??? /* Specs say to write ones most of the time, even when the card
??? ?* has no need to read its input data; and many cards won't care.
??? ?* This is our source of those ones.
??? ?*/
??? void??? ??? ??? *ones;
??? dma_addr_t??? ??? ones_dma;
};?
mmc_spi_host描述了一個基于SPI總線的MMC卡設(shè)備。

static struct spi_driver mmc_spi_driver = {
??? .driver = {
??? ??? .name =??? ??? "mmc_spi",
??? ??? .bus =??? ??? &spi_bus_type,
??? ??? .owner =??? THIS_MODULE,
??? },
??? .probe =??? mmc_spi_probe,
??? .remove =??? __devexit_p(mmc_spi_remove),
};

特定的mmc_spi_driver,但其本質(zhì)上是spi_driver,和SPI 設(shè)備匹配的關(guān)鍵字是mmc_spi。

6.2.2??? 初始化
static int __init mmc_spi_init(void)
{
??? return spi_register_driver(&mmc_spi_driver);
}
module_init(mmc_spi_init);


static void __exit mmc_spi_exit(void)
{
??? spi_unregister_driver(&mmc_spi_driver);
}

調(diào)用spi_register_driver向SPI總線上注冊mmc_spi_driver,根據(jù)mmc_spi進(jìn)行匹配,匹配成功后將自動調(diào)用mmc_spi_probe。

static int mmc_spi_probe(struct spi_device *spi)
{
??? void??? ??? ??? *ones;
??? struct mmc_host??? ??? *mmc;
??? struct mmc_spi_host??? *host;
??? int??? ??? ??? status;

??? /* MMC and SD specs only seem to care that sampling is on the
??? ?* rising edge ... meaning SPI modes 0 or 3.? So either SPI mode
??? ?* should be legit.? We'll use mode 0 since it seems to be a
??? ?* bit less troublesome on some hardware ... unclear why.
??? ?*/
??? spi->mode = SPI_MODE_0;
??? spi->bits_per_word = 8;

??? status = spi_setup(spi);
??? if (status < 0) {
??? ??? dev_dbg(&spi->dev, "needs SPI mode %02x, %d KHz; %d/n",
??? ??? ??? ??? spi->mode, spi->max_speed_hz / 1000,
??? ??? ??? ??? status);
??? ??? return status;
??? }

??? /* We can use the bus safely iff nobody else will interfere with us.
??? ?* Most commands consist of one SPI message to issue a command, then
??? ?* several more to collect its response, then possibly more for data
??? ?* transfer.? Clocking access to other devices during that period will
??? ?* corrupt the command execution.
??? ?*
??? ?*/
??? if (spi->master->num_chipselect > 1) {
??? ??? struct count_children cc;

??? ??? cc.n = 0;
??? ??? cc.bus = spi->dev.bus;
??? ??? status = device_for_each_child(spi->dev.parent, &cc,
??? ??? ??? ??? maybe_count_child);
??? ??? if (status < 0) {
??? ??? ??? dev_err(&spi->dev, "can't share SPI bus/n");
??? ??? ??? return status;
??? ??? }

??? ??? dev_warn(&spi->dev, "ASSUMING SPI bus stays unshared!/n");
??? }

??? /* We need a supply of ones to transmit.? This is the only time
??? ?* the CPU touches these, so cache coherency isn't a concern.
??? ?*
??? ?* NOTE if many systems use more than one MMC-over-SPI connector
??? ?* it'd save some memory to share this.? That's evidently rare.
??? ?*/
??? status = -ENOMEM;
??? ones = kmalloc(MMC_SPI_BLOCKSIZE, GFP_KERNEL);
??? if (!ones)
??? ??? goto nomem;
??? memset(ones, 0xff, MMC_SPI_BLOCKSIZE);

??? mmc = mmc_alloc_host(sizeof(*host), &spi->dev);
??? if (!mmc)
??? ??? goto nomem;

??? mmc->ops = &mmc_spi_ops;
??? mmc->max_blk_size = MMC_SPI_BLOCKSIZE;

??? /* As long as we keep track of the number of successfully
??? ?* transmitted blocks, we're good for multiwrite.
??? ?*/
??? mmc->caps = MMC_CAP_SPI | MMC_CAP_MULTIWRITE;

??? /* SPI doesn't need the lowspeed device identification thing for
??? ?* MMC or SD cards, since it never comes up in open drain mode.
??? ?* That's good; some SPI masters can't handle very low speeds!
??? ?*
??? ?* However, low speed SDIO cards need not handle over 400 KHz;
??? ?* that's the only reason not to use a few MHz for f_min (until
??? ?* the upper layer reads the target frequency from the CSD).
??? ?*/
??? mmc->f_min = 400000;
??? mmc->f_max = spi->max_speed_hz;

??? host = mmc_priv(mmc);
??? host->mmc = mmc;
??? host->spi = spi;

??? host->ones = ones;

??? /* Platform data is used to hook up things like card sensing
??? ?* and power switching gpios.
??? ?*/
??? host->pdata = spi->dev.platform_data;
??? if (host->pdata)
??? ??? mmc->ocr_avail = host->pdata->ocr_mask;
??? if (!mmc->ocr_avail) {
??? ??? dev_warn(&spi->dev, "ASSUMING 3.2-3.4 V slot power/n");
??? ??? mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
??? }
??? if (host->pdata && host->pdata->setpower) {
??? ??? host->powerup_msecs = host->pdata->powerup_msecs;
??? ??? if (!host->powerup_msecs || host->powerup_msecs > 250)
??? ??? ??? host->powerup_msecs = 250;
??? }

??? dev_set_drvdata(&spi->dev, mmc);

??? /* preallocate dma buffers */
??? host->data = kmalloc(sizeof(*host->data), GFP_KERNEL);
??? if (!host->data)
??? ??? goto fail_nobuf1;

??? if (spi->master->dev.parent->dma_mask) {
??? ??? struct device??? *dev = spi->master->dev.parent;

??? ??? host->dma_dev = dev;
??? ??? host->ones_dma = dma_map_single(dev, ones,
??? ??? ??? ??? MMC_SPI_BLOCKSIZE, DMA_TO_DEVICE);
??? ??? host->data_dma = dma_map_single(dev, host->data,
??? ??? ??? ??? sizeof(*host->data), DMA_BIDIRECTIONAL);

??? ??? /* REVISIT in theory those map operations can fail... */

??? ??? dma_sync_single_for_cpu(host->dma_dev,
??? ??? ??? ??? host->data_dma, sizeof(*host->data),
??? ??? ??? ??? DMA_BIDIRECTIONAL);
??? }

??? /* setup message for status/busy readback */
??? spi_message_init(&host->readback);
??? host->readback.is_dma_mapped = (host->dma_dev != NULL);

??? spi_message_add_tail(&host->status, &host->readback);
??? host->status.tx_buf = host->ones;
??? host->status.tx_dma = host->ones_dma;
??? host->status.rx_buf = &host->data->status;
??? host->status.rx_dma = host->data_dma + offsetof(struct scratch, status);
??? host->status.cs_change = 1;

??? /* register card detect irq */
??? if (host->pdata && host->pdata->init) {
??? ??? status = host->pdata->init(&spi->dev, mmc_spi_detect_irq, mmc);
??? ??? if (status != 0)
??? ??? ??? goto fail_glue_init;
??? }

??? status = mmc_add_host(mmc);
??? if (status != 0)
??? ??? goto fail_add_host;

??? dev_info(&spi->dev, "SD/MMC host %s%s%s%s/n",
??? ??? ??? mmc->class_dev.bus_id,
??? ??? ??? host->dma_dev ? "" : ", no DMA",
??? ??? ??? (host->pdata && host->pdata->get_ro)
??? ??? ??? ??? ? "" : ", no WP",
??? ??? ??? (host->pdata && host->pdata->setpower)
??? ??? ??? ??? ? "" : ", no poweroff");
??? return 0;

fail_add_host:
??? mmc_remove_host (mmc);
fail_glue_init:
??? if (host->dma_dev)
??? ??? dma_unmap_single(host->dma_dev, host->data_dma,
??? ??? ??? ??? sizeof(*host->data), DMA_BIDIRECTIONAL);
??? kfree(host->data);

fail_nobuf1:
??? mmc_free_host(mmc);
??? dev_set_drvdata(&spi->dev, NULL);

nomem:
??? kfree(ones);
??? return status;
}
其主要功能是注冊一個struct mmc_host,最終的數(shù)據(jù)訪問是由其他子系統(tǒng)發(fā)起的。
6.2.3??? 數(shù)據(jù)收發(fā)
TBD

7??? 驅(qū)動訪問示例
下面以一款TI 的SPI接口的時鐘芯片62002為例來講述用戶空間如何訪問SPI設(shè)備。

62002支持32bits、LSB訪問模式。內(nèi)部寄存器為28bits,其他4bits為地址位。
?
支持的讀寫命令如下:
?
Xxxx為待寫的數(shù)據(jù),read command中AAAA為待訪問的寄存器地址。
7.1.1??? 寫操作
62002寫操作通常比較簡單,時序如下,
?

struct spi_ioc_transfer? write? = {
??? ??? .tx_buf = (int)dout,
??? ??? .rx_buf = NULL, //寫操作時,忽略MISO
??? ??? .len = sizeof(long),
??? ??? .delay_usecs = 0,
??? ??? .speed_hz = 500000,
??? ??? .bits_per_word = 32,
??? ??? .cs_change = 1,
};

Dout = data << 4 + address;? // 待發(fā)送的數(shù)據(jù)Dout由28bits的data field和4位地址域構(gòu)成。

ret = ioctl(fd, SPI_IOC_MESSAGE(1), &write);
7.1.2??? 讀操作
62002的讀操作較復(fù)雜,需要先發(fā)送寫命令指定待讀的內(nèi)部寄存器地址,然后再發(fā)起總線的讀操作。時序如下:
?
SPI Master發(fā)送讀命令后,抬起SPI片選,62002解碼讀命令中的寄存器地址。當(dāng)SPI Master再次通過片選選中62002時,62002在MISO上發(fā)出待讀的數(shù)據(jù)。

因此需要在總線上連續(xù)進(jìn)行兩次數(shù)據(jù)傳輸,即兩個spi_ioc_transfer 。
struct spi_ioc_transfer? read[2]? = {
??? {
??? ??? ??? .tx_buf = (int)dout,
??? ??? ??? .rx_buf = NULL,? //發(fā)送讀命令時,忽略MISO
??? ??? ??? .len = sizeof(long),
??? ??? ??? .delay_usecs = 0,
??? ??? ??? .speed_hz = 500000,
??? ??? ??? .bits_per_word = 32,
??? ??? ??? .cs_change = 1,
??? },
??? {
??? ??? ??? .tx_buf = NULL,? //讀取數(shù)據(jù)時,忽略MOSI,總線上默然發(fā)送的是0
??? ??? ??? .rx_buf = (int)din,
??? ??? ??? .len = sizeof(long),
??? ??? ??? .delay_usecs = 0,
??? ??? ??? .speed_hz = 500000,
??? ??? ??? .bits_per_word = 32,
??? ??? ??? .cs_change = 1,
??? }
}

第一個spi_ioc_transfer發(fā)送讀命令,第二個spi_ioc_transfer讀取數(shù)據(jù)。

ret = ioctl(fd, SPI_IOC_MESSAGE(2), read);
兩個spi_ioc_transfer將構(gòu)成一個spi_message,其在內(nèi)核中是一個原子序列,將連續(xù)占用總線直至兩個spi_ioc_transfer發(fā)送完畢。

第一個spi_ioc_transfer的cs_change一定要置為1,即spi_transfer發(fā)送完畢后片選要發(fā)生變化,由低到高,這樣才滿足62002的時序。

8??? 參考鳴謝
http://blog.csdn.net/sailor_8318/archive/2010/09/25/5905988.aspx

與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】PowerPC + Linux2.6.25平台下的SPI驱动架构分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

亚洲国产精品久久人人爱 | 狠狠色噜噜狠狠狠狠7777米奇 | 亚洲最大成人网站 | 激情综合激情五月俺也去 | 精品乱码久久久久久久 | 国产av人人夜夜澡人人爽麻豆 | 亚洲第一网站男人都懂 | 亚洲综合精品香蕉久久网 | 免费播放一区二区三区 | 无码人妻精品一区二区三区下载 | 亚洲大尺度无码无码专区 | 国产高清不卡无码视频 | 国产激情艳情在线看视频 | 国产高清不卡无码视频 | 亚洲成av人综合在线观看 | 亚洲日韩一区二区三区 | 强伦人妻一区二区三区视频18 | 97精品国产97久久久久久免费 | 久久综合激激的五月天 | 亚洲精品综合五月久久小说 | 日本大乳高潮视频在线观看 | 无码人妻丰满熟妇区毛片18 | 国产亚洲tv在线观看 | 久久久久99精品国产片 | 国产精品99久久精品爆乳 | 秋霞特色aa大片 | 男女作爱免费网站 | 四虎影视成人永久免费观看视频 | 欧洲vodafone精品性 | 精品成人av一区二区三区 | 亚洲精品国产品国语在线观看 | 亚洲人交乣女bbw | 日本xxxx色视频在线观看免费 | 久久久中文字幕日本无吗 | 亚洲人成影院在线观看 | 久久久久久国产精品无码下载 | 熟妇人妻无码xxx视频 | 奇米影视7777久久精品 | 国产精品无码一区二区桃花视频 | 台湾无码一区二区 | 丁香花在线影院观看在线播放 | 欧美成人午夜精品久久久 | 欧美激情一区二区三区成人 | 亚洲欧美国产精品专区久久 | 小鲜肉自慰网站xnxx | 老太婆性杂交欧美肥老太 | 少妇性荡欲午夜性开放视频剧场 | 国产成人精品视频ⅴa片软件竹菊 | 国产内射爽爽大片视频社区在线 | 夜精品a片一区二区三区无码白浆 | 天堂а√在线中文在线 | 国产免费久久久久久无码 | 色五月五月丁香亚洲综合网 | 狠狠色丁香久久婷婷综合五月 | 国产熟女一区二区三区四区五区 | 欧美丰满老熟妇xxxxx性 | 兔费看少妇性l交大片免费 | 国产精品国产三级国产专播 | 久久综合网欧美色妞网 | 无遮无挡爽爽免费视频 | 国内少妇偷人精品视频免费 | 久久 国产 尿 小便 嘘嘘 | 无码av中文字幕免费放 | 国产乡下妇女做爰 | 精品一区二区三区无码免费视频 | 久久99国产综合精品 | 午夜免费福利小电影 | 国产色在线 | 国产 | 色欲久久久天天天综合网精品 | 国内少妇偷人精品视频 | 欧美精品在线观看 | 久久精品人人做人人综合 | 亚洲娇小与黑人巨大交 | 内射后入在线观看一区 | 亚洲成a人片在线观看无码3d | 国产精品二区一区二区aⅴ污介绍 | 天天爽夜夜爽夜夜爽 | 国产一区二区三区四区五区加勒比 | 亚洲欧美色中文字幕在线 | 在线а√天堂中文官网 | 波多野42部无码喷潮在线 | 精品人妻人人做人人爽夜夜爽 | 牲欲强的熟妇农村老妇女 | 亚洲娇小与黑人巨大交 | 国内综合精品午夜久久资源 | 久久国产精品精品国产色婷婷 | 99精品视频在线观看免费 | 精品无码成人片一区二区98 | 亚洲成av人影院在线观看 | 熟女体下毛毛黑森林 | 中文字幕av无码一区二区三区电影 | 97夜夜澡人人爽人人喊中国片 | 网友自拍区视频精品 | 成人试看120秒体验区 | 国内揄拍国内精品少妇国语 | 亚洲无人区一区二区三区 | 中文字幕av伊人av无码av | 欧美日本免费一区二区三区 | 久久精品人人做人人综合试看 | 麻豆蜜桃av蜜臀av色欲av | 午夜无码区在线观看 | 中文毛片无遮挡高清免费 | 夜夜躁日日躁狠狠久久av | 18禁黄网站男男禁片免费观看 | 久久精品女人天堂av免费观看 | 人妻有码中文字幕在线 | 熟妇人妻无码xxx视频 | 亚洲日本va午夜在线电影 | 玩弄少妇高潮ⅹxxxyw | 日本丰满护士爆乳xxxx | 亚洲精品无码人妻无码 | 熟妇人妻无码xxx视频 | 人妻少妇精品无码专区二区 | 一本久道久久综合婷婷五月 | 99re在线播放 | 日本精品高清一区二区 | 成人女人看片免费视频放人 | 国产成人综合色在线观看网站 | 波多野结衣av一区二区全免费观看 | 成人无码影片精品久久久 | 亚洲乱亚洲乱妇50p | 丰满人妻被黑人猛烈进入 | 日韩av无码一区二区三区 | 欧美老人巨大xxxx做受 | 国产成人精品一区二区在线小狼 | 97夜夜澡人人爽人人喊中国片 | 久久精品国产一区二区三区 | 亚洲成av人综合在线观看 | 99久久亚洲精品无码毛片 | 国产手机在线αⅴ片无码观看 | 欧美人与动性行为视频 | 狠狠色噜噜狠狠狠狠7777米奇 | 青青草原综合久久大伊人精品 | 亚洲一区二区三区四区 | 天天摸天天透天天添 | 桃花色综合影院 | 偷窥村妇洗澡毛毛多 | 国产精品人人妻人人爽 | 99久久精品无码一区二区毛片 | 两性色午夜视频免费播放 | 亚洲欧洲无卡二区视頻 | 日韩精品久久久肉伦网站 | 人妻天天爽夜夜爽一区二区 | 99视频精品全部免费免费观看 | 131美女爱做视频 | 亚洲精品国产精品乱码不卡 | 精品久久8x国产免费观看 | 无码一区二区三区在线 | 永久免费观看国产裸体美女 | 一区二区三区乱码在线 | 欧洲 | 久久综合九色综合欧美狠狠 | 国产成人综合色在线观看网站 | 免费中文字幕日韩欧美 | 男女超爽视频免费播放 | 亚洲国产精品成人久久蜜臀 | 欧美丰满熟妇xxxx性ppx人交 | 强开小婷嫩苞又嫩又紧视频 | 中文字幕乱码人妻无码久久 | 国产国产精品人在线视 | 国产亚洲美女精品久久久2020 | 亚洲成av人片在线观看无码不卡 | 久久久久国色av免费观看性色 | 无遮挡国产高潮视频免费观看 | 国产偷国产偷精品高清尤物 | 免费人成在线视频无码 | 1000部啪啪未满十八勿入下载 | 性欧美疯狂xxxxbbbb | 国产成人精品优优av | 丁香花在线影院观看在线播放 | 亚洲中文无码av永久不收费 | 一本色道久久综合亚洲精品不卡 | 东京一本一道一二三区 | 99久久精品午夜一区二区 | 欧美兽交xxxx×视频 | 成人无码影片精品久久久 | 综合人妻久久一区二区精品 | 在线а√天堂中文官网 | 亚洲无人区午夜福利码高清完整版 | 亚洲精品久久久久中文第一幕 | 久久久精品国产sm最大网站 | 亚洲精品国产a久久久久久 | v一区无码内射国产 | 国产成人无码av一区二区 | 窝窝午夜理论片影院 | 熟妇人妻激情偷爽文 | 永久黄网站色视频免费直播 | 日本欧美一区二区三区乱码 | 久9re热视频这里只有精品 | 麻豆国产人妻欲求不满 | 日本一卡二卡不卡视频查询 | 欧美日韩综合一区二区三区 | aa片在线观看视频在线播放 | 免费人成在线视频无码 | 无码国内精品人妻少妇 | 东京无码熟妇人妻av在线网址 | 国产精品久久久久无码av色戒 | 四虎永久在线精品免费网址 | 暴力强奷在线播放无码 | 人人爽人人爽人人片av亚洲 | 精品人妻人人做人人爽 | 亚洲爆乳无码专区 | 小泽玛莉亚一区二区视频在线 | 欧美黑人乱大交 | 成人综合网亚洲伊人 | 亚洲高清偷拍一区二区三区 | 青青青爽视频在线观看 | 国产真实乱对白精彩久久 | 999久久久国产精品消防器材 | 日本肉体xxxx裸交 | 欧美人与物videos另类 | 欧洲vodafone精品性 | 无码任你躁久久久久久久 | 成人无码精品1区2区3区免费看 | 十八禁真人啪啪免费网站 | 中国女人内谢69xxxxxa片 | 亚洲理论电影在线观看 | 亚洲成av人综合在线观看 | 亚洲一区二区三区偷拍女厕 | 久久综合激激的五月天 | 欧美一区二区三区 | 欧美三级不卡在线观看 | 夜夜夜高潮夜夜爽夜夜爰爰 | 丝袜足控一区二区三区 | 成人综合网亚洲伊人 | 亚无码乱人伦一区二区 | 亚洲精品国产第一综合99久久 | 久久久精品成人免费观看 | 欧美三级不卡在线观看 | 国产无套粉嫩白浆在线 | 国产卡一卡二卡三 | 人妻体内射精一区二区三四 | 欧美怡红院免费全部视频 | 亚洲va中文字幕无码久久不卡 | 亚洲精品国偷拍自产在线麻豆 | 久久综合给久久狠狠97色 | 亚洲中文字幕无码一久久区 | 成人精品视频一区二区 | 亚洲毛片av日韩av无码 | 日本一区二区三区免费高清 | 大肉大捧一进一出好爽视频 | 久久亚洲精品中文字幕无男同 | 3d动漫精品啪啪一区二区中 | 国产亚洲人成在线播放 | 免费无码午夜福利片69 | 中文字幕日韩精品一区二区三区 | 无码av免费一区二区三区试看 | 亚洲日本一区二区三区在线 | 青青草原综合久久大伊人精品 | 国产av无码专区亚洲a∨毛片 | 久久久无码中文字幕久... | 国产精品久久久av久久久 | 国产超碰人人爽人人做人人添 | 日本一区二区更新不卡 | 久久国产劲爆∧v内射 | 九月婷婷人人澡人人添人人爽 | 自拍偷自拍亚洲精品被多人伦好爽 | 免费观看的无遮挡av | 四虎永久在线精品免费网址 | 国产后入清纯学生妹 | 国产超级va在线观看视频 | 国内丰满熟女出轨videos | 成人综合网亚洲伊人 | 国产精品久久久久久无码 | 色综合视频一区二区三区 | 日韩精品一区二区av在线 | 国产激情一区二区三区 | 精品久久久无码中文字幕 | 中文字幕+乱码+中文字幕一区 | 成人一区二区免费视频 | 最近免费中文字幕中文高清百度 | 国产午夜手机精彩视频 | 无码福利日韩神码福利片 | 久久精品无码一区二区三区 | 人妻夜夜爽天天爽三区 | 亚洲成av人片天堂网无码】 | 女人被爽到呻吟gif动态图视看 | 麻豆精产国品 | 亚洲高清偷拍一区二区三区 | 一个人免费观看的www视频 | 国产亚洲精品久久久久久大师 | 亚洲欧美日韩成人高清在线一区 | 久久99久久99精品中文字幕 | 亚洲色欲色欲天天天www | 精品乱子伦一区二区三区 | 成人性做爰aaa片免费看 | 女人被爽到呻吟gif动态图视看 | 欧美日韩色另类综合 | 久久久久亚洲精品中文字幕 | 动漫av一区二区在线观看 | 女人被男人躁得好爽免费视频 | 国产又爽又猛又粗的视频a片 | 西西人体www44rt大胆高清 | 曰本女人与公拘交酡免费视频 | 日韩精品一区二区av在线 | 国产乱人偷精品人妻a片 | 国产精品无码成人午夜电影 | 精品国产成人一区二区三区 | 中文字幕日产无线码一区 | 熟妇人妻中文av无码 | 中文字幕无码av激情不卡 | 亚洲а∨天堂久久精品2021 | 久久亚洲a片com人成 | 国产一区二区三区四区五区加勒比 | 欧美自拍另类欧美综合图片区 | 成人试看120秒体验区 | 欧美亚洲日韩国产人成在线播放 | 九月婷婷人人澡人人添人人爽 | 国产精品人妻一区二区三区四 | 日日摸天天摸爽爽狠狠97 | 日日鲁鲁鲁夜夜爽爽狠狠 | 久久久精品成人免费观看 | 精品久久久无码中文字幕 | 国产成人无码av片在线观看不卡 | 国产精品亚洲lv粉色 | 荫蒂被男人添的好舒服爽免费视频 | 国产av无码专区亚洲a∨毛片 | 亚洲欧美综合区丁香五月小说 | 又大又黄又粗又爽的免费视频 | 国产真人无遮挡作爱免费视频 | 国产欧美亚洲精品a | 男人的天堂2018无码 | 国产午夜无码精品免费看 | 国产极品美女高潮无套在线观看 | 国内揄拍国内精品人妻 | 精品无人区无码乱码毛片国产 | 成人免费无码大片a毛片 | 色诱久久久久综合网ywww | 精品久久久久久亚洲精品 | 无套内谢的新婚少妇国语播放 | 国产在线精品一区二区三区直播 | 成人欧美一区二区三区黑人 | 中文字幕无码热在线视频 | 亚洲成a人片在线观看日本 | 激情国产av做激情国产爱 | 精品国产精品久久一区免费式 | 亚洲精品午夜无码电影网 | 人妻尝试又大又粗久久 | 久久久久久亚洲精品a片成人 | 97久久精品无码一区二区 | 久久精品国产一区二区三区 | 亚洲va中文字幕无码久久不卡 | 97久久国产亚洲精品超碰热 | 国产超碰人人爽人人做人人添 | 欧美日韩精品 | 天堂а√在线地址中文在线 | 狠狠色色综合网站 | 成人女人看片免费视频放人 | 国精品人妻无码一区二区三区蜜柚 | 高中生自慰www网站 | 97色伦图片97综合影院 | 中文字幕精品av一区二区五区 | 成人性做爰aaa片免费看 | 成年美女黄网站色大免费视频 | 好屌草这里只有精品 | 久久精品国产日本波多野结衣 | 久久精品国产精品国产精品污 | 成熟妇人a片免费看网站 | 福利一区二区三区视频在线观看 | 亚洲狠狠色丁香婷婷综合 | 成人免费视频一区二区 | 大肉大捧一进一出好爽视频 | 久久午夜无码鲁丝片秋霞 | 国产午夜精品一区二区三区嫩草 | 国产一区二区三区精品视频 | 51国偷自产一区二区三区 | 未满成年国产在线观看 | 中文字幕无码免费久久9一区9 | 特黄特色大片免费播放器图片 | 精品人妻中文字幕有码在线 | 国产无套粉嫩白浆在线 | 日本欧美一区二区三区乱码 | 天堂在线观看www | 久久国内精品自在自线 | 国产九九九九九九九a片 | 亚洲精品中文字幕乱码 | 少女韩国电视剧在线观看完整 | 一个人看的www免费视频在线观看 | 色欲人妻aaaaaaa无码 | 成人免费无码大片a毛片 | 亚洲国产高清在线观看视频 | 性色欲情网站iwww九文堂 | 精品乱码久久久久久久 | 国产成人综合美国十次 | 丰满少妇熟乱xxxxx视频 | 亚洲狠狠婷婷综合久久 | 青青草原综合久久大伊人精品 | 亚洲大尺度无码无码专区 | 亚洲国产精品久久人人爱 | 欧美成人高清在线播放 | 波多野42部无码喷潮在线 | 青青青爽视频在线观看 | 国产肉丝袜在线观看 | 国产高潮视频在线观看 | 欧美成人免费全部网站 | 熟妇人妻无乱码中文字幕 | 野外少妇愉情中文字幕 | 少妇性荡欲午夜性开放视频剧场 | 亚洲欧洲无卡二区视頻 | www一区二区www免费 | 亚洲娇小与黑人巨大交 | 色欲av亚洲一区无码少妇 | 国产成人无码av一区二区 | 极品嫩模高潮叫床 | 狠狠亚洲超碰狼人久久 | 亚洲成av人影院在线观看 | 大胆欧美熟妇xx | 成人精品视频一区二区 | 97色伦图片97综合影院 | 沈阳熟女露脸对白视频 | 在线观看欧美一区二区三区 | 久久人人97超碰a片精品 | 青春草在线视频免费观看 | 久久精品国产一区二区三区 | 国产精品国产三级国产专播 | 成人无码影片精品久久久 | 色老头在线一区二区三区 | 久久久久久a亚洲欧洲av冫 | aa片在线观看视频在线播放 | 老子影院午夜伦不卡 | 免费人成网站视频在线观看 | 粗大的内捧猛烈进出视频 | 国产精品亚洲综合色区韩国 | 久久久国产精品无码免费专区 | 国产精品igao视频网 | 99久久人妻精品免费二区 | 国产亚洲精品久久久久久大师 | 亚洲自偷自偷在线制服 | 亚洲精品无码国产 | 天天爽夜夜爽夜夜爽 | av小次郎收藏 | 国产成人无码av在线影院 | 精品午夜福利在线观看 | 成年美女黄网站色大免费全看 | 少妇被黑人到高潮喷出白浆 | 无码福利日韩神码福利片 | 大肉大捧一进一出视频出来呀 | 精品无码国产一区二区三区av | 99re在线播放 | 国产无遮挡又黄又爽免费视频 | 亚洲国产欧美日韩精品一区二区三区 | 国产农村乱对白刺激视频 | 亚洲七七久久桃花影院 | 国产精品igao视频网 | 亚洲国产精品无码一区二区三区 | 国产成人一区二区三区别 | 人人爽人人澡人人人妻 | 国产婷婷色一区二区三区在线 | 亚洲精品无码国产 | 国产农村妇女高潮大叫 | 成 人 网 站国产免费观看 | 成人aaa片一区国产精品 | 青青草原综合久久大伊人精品 | 国产激情一区二区三区 | 精品成在人线av无码免费看 | 两性色午夜免费视频 | 最近中文2019字幕第二页 | 无遮挡国产高潮视频免费观看 | 4hu四虎永久在线观看 | 一本精品99久久精品77 | 国产高潮视频在线观看 | 激情人妻另类人妻伦 | 丝袜美腿亚洲一区二区 | 免费观看又污又黄的网站 | 福利一区二区三区视频在线观看 | 日日躁夜夜躁狠狠躁 | 欧美国产亚洲日韩在线二区 | 麻豆精品国产精华精华液好用吗 | аⅴ资源天堂资源库在线 | 亚洲成在人网站无码天堂 | 成年女人永久免费看片 | 中文字幕人妻无码一区二区三区 | 久久成人a毛片免费观看网站 | 亚洲理论电影在线观看 | 无码av免费一区二区三区试看 | 亚洲综合伊人久久大杳蕉 | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | 精品国产aⅴ无码一区二区 | 国产成人无码一二三区视频 | 国产9 9在线 | 中文 | 成人欧美一区二区三区黑人 | 一本大道久久东京热无码av | 日韩少妇内射免费播放 | 波多野结衣乳巨码无在线观看 | 中文字幕日韩精品一区二区三区 | 人妻与老人中文字幕 | 99久久99久久免费精品蜜桃 | 丰满妇女强制高潮18xxxx | 国产一区二区三区日韩精品 | 国产免费观看黄av片 | 正在播放东北夫妻内射 | 国产又粗又硬又大爽黄老大爷视 | 亚洲精品国偷拍自产在线麻豆 | 性欧美videos高清精品 | 精品无码国产一区二区三区av | 欧美三级a做爰在线观看 | 欧美35页视频在线观看 | 久久www免费人成人片 | 久久99精品国产麻豆蜜芽 | 国产成人精品一区二区在线小狼 | 最近免费中文字幕中文高清百度 | √天堂资源地址中文在线 | 扒开双腿吃奶呻吟做受视频 | 日本精品人妻无码77777 天堂一区人妻无码 | 婷婷五月综合缴情在线视频 | 一区二区三区乱码在线 | 欧洲 | 国产高潮视频在线观看 | 午夜精品久久久久久久 | 天天拍夜夜添久久精品 | 久久久精品国产sm最大网站 | 成人精品天堂一区二区三区 | 欧美日韩一区二区免费视频 | 少妇性荡欲午夜性开放视频剧场 | 国产又爽又猛又粗的视频a片 | 九九综合va免费看 | 99精品国产综合久久久久五月天 | 日韩人妻无码一区二区三区久久99 | 欧美真人作爱免费视频 | 中文字幕无码av激情不卡 | 高清无码午夜福利视频 | 少妇无码吹潮 | 久久久av男人的天堂 | 成人精品视频一区二区三区尤物 | 一本色道婷婷久久欧美 | 三上悠亚人妻中文字幕在线 | 天海翼激烈高潮到腰振不止 | 中文字幕人成乱码熟女app | 老太婆性杂交欧美肥老太 | 久久人人爽人人爽人人片av高清 | 中文字幕乱码人妻二区三区 | 性欧美疯狂xxxxbbbb | 夜夜影院未满十八勿进 | 国产av久久久久精东av | 动漫av一区二区在线观看 | 日日摸天天摸爽爽狠狠97 | 亚洲精品一区三区三区在线观看 | 成人免费视频一区二区 | 色情久久久av熟女人妻网站 | 狠狠色丁香久久婷婷综合五月 | 国产精品毛片一区二区 | 麻豆国产97在线 | 欧洲 | 中文字幕人成乱码熟女app | 97人妻精品一区二区三区 | 国产午夜手机精彩视频 | 欧美日本精品一区二区三区 | 成在人线av无码免观看麻豆 | 任你躁国产自任一区二区三区 | аⅴ资源天堂资源库在线 | 国产人妻精品一区二区三区不卡 | 性开放的女人aaa片 | 国产人妻精品一区二区三区不卡 | 帮老师解开蕾丝奶罩吸乳网站 | 亚洲色偷偷男人的天堂 | 伊人久久婷婷五月综合97色 | 麻花豆传媒剧国产免费mv在线 | 午夜精品久久久久久久 | 中文字幕 亚洲精品 第1页 | 亚洲精品美女久久久久久久 | 日本免费一区二区三区最新 | 999久久久国产精品消防器材 | 无码国产色欲xxxxx视频 | 99re在线播放 | 欧美日本日韩 | 理论片87福利理论电影 | 三上悠亚人妻中文字幕在线 | 波多野结衣高清一区二区三区 | 东京无码熟妇人妻av在线网址 | 亚洲区小说区激情区图片区 | 国产成人无码av在线影院 | 女人被男人爽到呻吟的视频 | 国产高清不卡无码视频 | 久久99精品国产麻豆蜜芽 | 在线看片无码永久免费视频 | av无码电影一区二区三区 | 久久久国产一区二区三区 | 中文无码精品a∨在线观看不卡 | 日日摸天天摸爽爽狠狠97 | 国产真实夫妇视频 | 无码福利日韩神码福利片 | 高清无码午夜福利视频 | 性欧美牲交在线视频 | 久久久久久久人妻无码中文字幕爆 | 欧美丰满老熟妇xxxxx性 | 中文字幕无码人妻少妇免费 | 国内精品人妻无码久久久影院 | 初尝人妻少妇中文字幕 | 亚洲精品一区二区三区四区五区 | 久久久精品456亚洲影院 | 亚洲精品国偷拍自产在线观看蜜桃 | 国产精品久久久一区二区三区 | 国产人成高清在线视频99最全资源 | 久久国产精品精品国产色婷婷 | 国产精品人妻一区二区三区四 | 色婷婷av一区二区三区之红樱桃 | 国产莉萝无码av在线播放 | 国产精品人人爽人人做我的可爱 | 激情内射亚州一区二区三区爱妻 | 国产福利视频一区二区 | 中文精品久久久久人妻不卡 | 亚洲国产综合无码一区 | 久久久久久a亚洲欧洲av冫 | 久久97精品久久久久久久不卡 | 在教室伦流澡到高潮hnp视频 | 7777奇米四色成人眼影 | 亚洲精品综合一区二区三区在线 | 少妇被黑人到高潮喷出白浆 | 亚洲日韩av片在线观看 | aa片在线观看视频在线播放 | 无码乱肉视频免费大全合集 | 亚洲精品中文字幕久久久久 | 久久久久免费精品国产 | 亚洲日本va午夜在线电影 | 亚洲欧美综合区丁香五月小说 | 无套内谢的新婚少妇国语播放 | 精品国产一区二区三区av 性色 | 人人妻人人澡人人爽精品欧美 | 欧美人与物videos另类 | 少妇人妻av毛片在线看 | 狠狠色噜噜狠狠狠狠7777米奇 | 国产绳艺sm调教室论坛 | 麻豆人妻少妇精品无码专区 | 亚洲狠狠色丁香婷婷综合 | 日本精品久久久久中文字幕 | 国产内射爽爽大片视频社区在线 | 四虎永久在线精品免费网址 | 精品一区二区三区波多野结衣 | 无码乱肉视频免费大全合集 | 亚洲精品一区二区三区婷婷月 | 精品成在人线av无码免费看 | 国产人妻精品午夜福利免费 | 国产精品理论片在线观看 | 精品久久久久久人妻无码中文字幕 | 精品国产青草久久久久福利 | 毛片内射-百度 | 国产三级久久久精品麻豆三级 | 亚洲中文字幕久久无码 | 强辱丰满人妻hd中文字幕 | 波多野结衣乳巨码无在线观看 | 女人和拘做爰正片视频 | 亚洲第一无码av无码专区 | 亚洲中文字幕在线观看 | 成人欧美一区二区三区黑人免费 | 日日碰狠狠丁香久燥 | 无码人妻av免费一区二区三区 | 亚洲国产精品无码久久久久高潮 | 亚洲中文字幕va福利 | 性欧美疯狂xxxxbbbb | 日本爽爽爽爽爽爽在线观看免 | 日本一区二区更新不卡 | 亚洲日韩av一区二区三区四区 | 欧美日韩亚洲国产精品 | 97色伦图片97综合影院 | 亚洲娇小与黑人巨大交 | 亚洲精品一区二区三区在线观看 | 中文字幕精品av一区二区五区 | 国产女主播喷水视频在线观看 | 国产午夜无码精品免费看 | 丰满人妻一区二区三区免费视频 | 亚洲 欧美 激情 小说 另类 | 成人aaa片一区国产精品 | 无码人妻黑人中文字幕 | 亚洲va中文字幕无码久久不卡 | 国产精品对白交换视频 | 一本大道伊人av久久综合 | av人摸人人人澡人人超碰下载 | 99久久99久久免费精品蜜桃 | 国产一精品一av一免费 | 亚洲阿v天堂在线 | 97精品人妻一区二区三区香蕉 | 亚洲国产精品毛片av不卡在线 | 丁香花在线影院观看在线播放 | 曰韩无码二三区中文字幕 | 人妻aⅴ无码一区二区三区 | 97无码免费人妻超级碰碰夜夜 | √天堂资源地址中文在线 | 99久久精品国产一区二区蜜芽 | 天天摸天天透天天添 | 中文字幕人妻无码一区二区三区 | 强伦人妻一区二区三区视频18 | 成人影院yy111111在线观看 | 亚洲人成网站在线播放942 | 亚洲阿v天堂在线 | 欧美人与禽猛交狂配 | 无码人妻精品一区二区三区不卡 | 国产亚洲精品久久久久久国模美 | 亚洲精品国产品国语在线观看 | 免费无码的av片在线观看 | 亚洲小说春色综合另类 | 久久99精品久久久久婷婷 | 亚洲欧美中文字幕5发布 | 日韩在线不卡免费视频一区 | 四十如虎的丰满熟妇啪啪 | 久久亚洲中文字幕精品一区 | 国产精品高潮呻吟av久久4虎 | 日本精品高清一区二区 | 1000部啪啪未满十八勿入下载 | 2020最新国产自产精品 | 国产精品人人妻人人爽 | 亚洲毛片av日韩av无码 | 国产精品久久久久久亚洲影视内衣 | 1000部啪啪未满十八勿入下载 | 人妻少妇精品无码专区二区 | 国产精品久久国产精品99 | 日韩精品成人一区二区三区 | 亚洲春色在线视频 | 久久亚洲精品中文字幕无男同 | 在线看片无码永久免费视频 | 狂野欧美性猛xxxx乱大交 | 免费男性肉肉影院 | 久久精品人人做人人综合 | 精品人妻人人做人人爽夜夜爽 | 国产麻豆精品精东影业av网站 | 午夜丰满少妇性开放视频 | 欧美性生交活xxxxxdddd | 久久久中文久久久无码 | 欧美老熟妇乱xxxxx | 欧美精品国产综合久久 | 国产成人综合在线女婷五月99播放 | 天天拍夜夜添久久精品 | 国产亲子乱弄免费视频 | 一本大道久久东京热无码av | 国产三级久久久精品麻豆三级 | 亚洲啪av永久无码精品放毛片 | 人妻体内射精一区二区三四 | 国产午夜亚洲精品不卡下载 | 精品偷拍一区二区三区在线看 | 女高中生第一次破苞av | 宝宝好涨水快流出来免费视频 | 性史性农村dvd毛片 | 亚洲成av人片在线观看无码不卡 | 高清无码午夜福利视频 | 好男人www社区 | 女人色极品影院 | 欧美第一黄网免费网站 | 国产精品久久久av久久久 | 亚洲国产欧美国产综合一区 | 曰本女人与公拘交酡免费视频 | 天天躁日日躁狠狠躁免费麻豆 | 四虎永久在线精品免费网址 | 国内揄拍国内精品少妇国语 | 中文字幕av伊人av无码av | 在线视频网站www色 | 亚洲中文字幕成人无码 | 熟女俱乐部五十路六十路av | 欧洲熟妇精品视频 | 天天摸天天透天天添 | 好爽又高潮了毛片免费下载 | 亚洲日韩av一区二区三区四区 | 欧美激情综合亚洲一二区 | 精品少妇爆乳无码av无码专区 | 中文字幕乱码人妻无码久久 | 中文字幕人妻无码一夲道 | 亚洲国产精品久久人人爱 | 奇米影视7777久久精品人人爽 | 国产精品亚洲五月天高清 | 日韩人妻系列无码专区 | 欧美日韩亚洲国产精品 | 欧美丰满熟妇xxxx性ppx人交 | 99精品无人区乱码1区2区3区 | 精品国产青草久久久久福利 | 东京热无码av男人的天堂 | 国产成人综合色在线观看网站 | 欧美性生交xxxxx久久久 | 狠狠色欧美亚洲狠狠色www | 久久久www成人免费毛片 | 欧美人与禽zoz0性伦交 | 伊人久久大香线蕉午夜 | 好屌草这里只有精品 | 久久久中文字幕日本无吗 | 最新版天堂资源中文官网 | 国产亲子乱弄免费视频 | 亚洲国产午夜精品理论片 | 无码人中文字幕 | 亚洲色欲色欲天天天www | 国产成人无码av片在线观看不卡 | 成人免费视频一区二区 | 亚洲精品美女久久久久久久 | 人妻互换免费中文字幕 | 国产美女精品一区二区三区 | 久久精品国产大片免费观看 | 国内精品久久毛片一区二区 | 亚洲欧洲日本无在线码 | 久久久久国色av免费观看性色 | 超碰97人人射妻 | 亚洲国产精品美女久久久久 | 国产在线aaa片一区二区99 | 久久国产自偷自偷免费一区调 | 国产午夜无码视频在线观看 | 小泽玛莉亚一区二区视频在线 | 图片区 小说区 区 亚洲五月 | 亚洲成av人在线观看网址 | 99视频精品全部免费免费观看 | 无码免费一区二区三区 | 又湿又紧又大又爽a视频国产 | 色婷婷av一区二区三区之红樱桃 | 日日摸夜夜摸狠狠摸婷婷 | 欧美成人高清在线播放 | 亚洲精品成人av在线 | 色老头在线一区二区三区 | 99精品无人区乱码1区2区3区 | 内射爽无广熟女亚洲 | 久久久久se色偷偷亚洲精品av | 亚洲综合色区中文字幕 | 欧美激情内射喷水高潮 | 亚洲国产精品无码久久久久高潮 | 玩弄人妻少妇500系列视频 | 在线欧美精品一区二区三区 | 真人与拘做受免费视频 | 精品偷拍一区二区三区在线看 | 老头边吃奶边弄进去呻吟 | 色综合久久中文娱乐网 | 亚洲欧美日韩国产精品一区二区 | 日本va欧美va欧美va精品 | 97人妻精品一区二区三区 | 无人区乱码一区二区三区 | 秋霞成人午夜鲁丝一区二区三区 | 欧美国产亚洲日韩在线二区 | 亚洲区小说区激情区图片区 | 欧美第一黄网免费网站 | 99视频精品全部免费免费观看 | 俄罗斯老熟妇色xxxx | 精品日本一区二区三区在线观看 | 性欧美牲交xxxxx视频 | 中文字幕精品av一区二区五区 | 76少妇精品导航 | 欧美 丝袜 自拍 制服 另类 | 精品国产国产综合精品 | 亚洲精品无码人妻无码 | 成人av无码一区二区三区 | 久久久av男人的天堂 | 精品国偷自产在线视频 | 久久国产自偷自偷免费一区调 | 国产成人无码av一区二区 | 99久久久无码国产aaa精品 | 国产在线一区二区三区四区五区 | 国产亚洲精品精品国产亚洲综合 | 精品国产乱码久久久久乱码 | 中文字幕乱码人妻无码久久 | 久久综合九色综合97网 | 2019午夜福利不卡片在线 | 窝窝午夜理论片影院 | 精品国产一区av天美传媒 | 丁香花在线影院观看在线播放 | 九九久久精品国产免费看小说 | 午夜无码区在线观看 | 国内精品一区二区三区不卡 | 无码乱肉视频免费大全合集 | 亚洲成a人一区二区三区 | 中国女人内谢69xxxxxa片 | 男女下面进入的视频免费午夜 | 日韩视频 中文字幕 视频一区 | 性欧美videos高清精品 | 久久久久免费精品国产 | 日日摸夜夜摸狠狠摸婷婷 | 最近免费中文字幕中文高清百度 | 国产在线一区二区三区四区五区 | 扒开双腿吃奶呻吟做受视频 | 国产精品第一国产精品 | 欧美成人免费全部网站 | 国产成人精品无码播放 | 亚洲一区二区三区含羞草 | 女人高潮内射99精品 | 精品国产成人一区二区三区 | 亚洲性无码av中文字幕 | 丰满人妻精品国产99aⅴ | 国产午夜精品一区二区三区嫩草 | 免费乱码人妻系列无码专区 | 双乳奶水饱满少妇呻吟 | 中国女人内谢69xxxxxa片 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 高清无码午夜福利视频 | 亚洲中文无码av永久不收费 | 精品国产一区二区三区四区在线看 | 国产综合色产在线精品 | 久久国产精品二国产精品 | 欧美成人家庭影院 | 青草视频在线播放 | 国内精品久久毛片一区二区 | 国色天香社区在线视频 | 亚洲日本va中文字幕 | 国产无套粉嫩白浆在线 | 天堂一区人妻无码 | 四虎国产精品一区二区 | 丰满护士巨好爽好大乳 | 国产精品无码一区二区桃花视频 | 国产免费无码一区二区视频 | 国精产品一品二品国精品69xx | 未满小14洗澡无码视频网站 | 欧美日韩精品 | 国产精品怡红院永久免费 | 国产成人无码一二三区视频 | 丰满护士巨好爽好大乳 | 丰满妇女强制高潮18xxxx | 高潮毛片无遮挡高清免费视频 | 免费国产成人高清在线观看网站 | 少妇一晚三次一区二区三区 | 色综合久久久久综合一本到桃花网 | 国产小呦泬泬99精品 | 欧美熟妇另类久久久久久不卡 | 国产极品视觉盛宴 | 最近的中文字幕在线看视频 | 真人与拘做受免费视频一 | 国语精品一区二区三区 | 成人精品天堂一区二区三区 | 300部国产真实乱 | 亚洲区欧美区综合区自拍区 | 久久久久免费精品国产 | 又粗又大又硬又长又爽 | 牲交欧美兽交欧美 | 中文字幕亚洲情99在线 | 日日躁夜夜躁狠狠躁 | 天堂无码人妻精品一区二区三区 | yw尤物av无码国产在线观看 | 精品国产一区二区三区四区 | 亚洲熟悉妇女xxx妇女av | 国产三级久久久精品麻豆三级 | 亚洲精品欧美二区三区中文字幕 | 精品国产麻豆免费人成网站 | 亚洲国产日韩a在线播放 | 麻花豆传媒剧国产免费mv在线 | 熟女俱乐部五十路六十路av | 5858s亚洲色大成网站www | 欧美一区二区三区视频在线观看 | 熟妇女人妻丰满少妇中文字幕 | 亚洲精品国产a久久久久久 | 欧美人与牲动交xxxx | 亚洲成av人在线观看网址 | 国产亚洲精品久久久闺蜜 | 免费看少妇作爱视频 | 思思久久99热只有频精品66 | 麻豆果冻传媒2021精品传媒一区下载 | 亚洲aⅴ无码成人网站国产app | 免费看少妇作爱视频 | 久久熟妇人妻午夜寂寞影院 | 一本大道伊人av久久综合 | 久久97精品久久久久久久不卡 | 国产xxx69麻豆国语对白 | 中文字幕色婷婷在线视频 | 亚洲成a人片在线观看无码 | 国产精品香蕉在线观看 | 亚洲精品一区三区三区在线观看 | 欧美国产日韩亚洲中文 | 久久久精品456亚洲影院 | 久久久久免费看成人影片 | 久久aⅴ免费观看 | 少妇无套内谢久久久久 | 一本色道久久综合狠狠躁 | 久久无码中文字幕免费影院蜜桃 | 欧美老妇交乱视频在线观看 | 国产在线精品一区二区高清不卡 | 亚洲va欧美va天堂v国产综合 | 中文字幕日产无线码一区 | 性做久久久久久久免费看 | 亚洲午夜无码久久 | 日本又色又爽又黄的a片18禁 | 欧美怡红院免费全部视频 | 亚洲无人区午夜福利码高清完整版 | 麻花豆传媒剧国产免费mv在线 | 色婷婷香蕉在线一区二区 | 无码av免费一区二区三区试看 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 中文字幕av伊人av无码av | 色 综合 欧美 亚洲 国产 | 99国产精品白浆在线观看免费 | 国内精品一区二区三区不卡 | 曰韩少妇内射免费播放 | 丰满妇女强制高潮18xxxx | av香港经典三级级 在线 | 性啪啪chinese东北女人 | 精品一区二区不卡无码av | 国产精品理论片在线观看 | 国产av剧情md精品麻豆 | 久久午夜无码鲁丝片午夜精品 | 日本熟妇浓毛 | 日本一卡二卡不卡视频查询 | 又色又爽又黄的美女裸体网站 | 国产无av码在线观看 | 婷婷六月久久综合丁香 | 亚洲乱亚洲乱妇50p | 亚洲国产欧美在线成人 | 狂野欧美性猛xxxx乱大交 | 女人被爽到呻吟gif动态图视看 | 欧美日韩久久久精品a片 | 亚洲人亚洲人成电影网站色 | 性做久久久久久久久 | 国产亚洲日韩欧美另类第八页 | 亚洲日韩乱码中文无码蜜桃臀网站 | 日本一卡2卡3卡四卡精品网站 | 免费无码的av片在线观看 | 日韩人妻无码一区二区三区久久99 | 亚洲小说春色综合另类 | 国产suv精品一区二区五 | 国产精品国产三级国产专播 | 国产精品国产自线拍免费软件 | 欧美 亚洲 国产 另类 | 狠狠色噜噜狠狠狠7777奇米 | 性色欲网站人妻丰满中文久久不卡 | 精品成人av一区二区三区 | 亚洲色偷偷男人的天堂 | 色五月五月丁香亚洲综合网 | 亚洲一区二区三区在线观看网站 | 国产超碰人人爽人人做人人添 | 久青草影院在线观看国产 | 久久综合激激的五月天 | 人人超人人超碰超国产 | 久久精品国产大片免费观看 | av小次郎收藏 | 久久精品视频在线看15 | 国产成人无码a区在线观看视频app | 欧美午夜特黄aaaaaa片 | 1000部啪啪未满十八勿入下载 | 曰本女人与公拘交酡免费视频 | 九九久久精品国产免费看小说 | 装睡被陌生人摸出水好爽 | 久久zyz资源站无码中文动漫 | 久久天天躁狠狠躁夜夜免费观看 | 国产午夜福利100集发布 | 88国产精品欧美一区二区三区 | 精品国产乱码久久久久乱码 | 国产精品人人妻人人爽 | 国内少妇偷人精品视频免费 | 99久久精品日本一区二区免费 | 久久无码专区国产精品s | 国内精品久久毛片一区二区 | 亚洲欧美综合区丁香五月小说 | 欧美日韩一区二区综合 | 曰本女人与公拘交酡免费视频 | 久久综合给合久久狠狠狠97色 | 老太婆性杂交欧美肥老太 | 动漫av一区二区在线观看 | 国产无套粉嫩白浆在线 | 男女性色大片免费网站 | 四十如虎的丰满熟妇啪啪 | 亚洲一区二区三区无码久久 | 97精品国产97久久久久久免费 | 国产在热线精品视频 | 亚洲а∨天堂久久精品2021 | 欧美亚洲日韩国产人成在线播放 | 亚洲一区二区三区国产精华液 | 中文字幕色婷婷在线视频 | 色五月五月丁香亚洲综合网 | 成年美女黄网站色大免费全看 | 国产三级精品三级男人的天堂 | 国产成人综合在线女婷五月99播放 | 亚洲精品一区二区三区大桥未久 | 日本免费一区二区三区最新 | 亚洲va欧美va天堂v国产综合 | 美女黄网站人色视频免费国产 | 亚洲成a人片在线观看日本 | 少妇一晚三次一区二区三区 | 亚洲国产精品无码久久久久高潮 | 精品国产一区二区三区四区在线看 | 中文字幕无码免费久久99 | 18精品久久久无码午夜福利 | 狠狠色欧美亚洲狠狠色www | 中文字幕精品av一区二区五区 | 亚洲国产精品久久人人爱 | 免费男性肉肉影院 | 亚洲自偷精品视频自拍 | 无人区乱码一区二区三区 | 99国产精品白浆在线观看免费 | 自拍偷自拍亚洲精品10p | 免费无码午夜福利片69 | 永久免费观看美女裸体的网站 | 女人被男人爽到呻吟的视频 | 人妻插b视频一区二区三区 | 欧美国产亚洲日韩在线二区 | 四虎国产精品一区二区 | 国内揄拍国内精品少妇国语 | 性欧美疯狂xxxxbbbb | 亚洲色大成网站www国产 | 激情人妻另类人妻伦 | 亚洲 a v无 码免 费 成 人 a v | 国产精品无码mv在线观看 | 欧美日韩视频无码一区二区三 | 国产av剧情md精品麻豆 | 国产真实乱对白精彩久久 | 无遮挡啪啪摇乳动态图 | 中文字幕av伊人av无码av | 乱码午夜-极国产极内射 | 国产免费无码一区二区视频 | 国産精品久久久久久久 | 久久国产自偷自偷免费一区调 | 久热国产vs视频在线观看 | 精品无码一区二区三区爱欲 | а√资源新版在线天堂 | 丰满护士巨好爽好大乳 | 欧美性生交活xxxxxdddd | 亚洲色偷偷男人的天堂 | аⅴ资源天堂资源库在线 | 亚洲 日韩 欧美 成人 在线观看 | 日日摸天天摸爽爽狠狠97 | 人人妻人人藻人人爽欧美一区 | 国产亚洲精品久久久ai换 | 久久综合给合久久狠狠狠97色 | 黑人粗大猛烈进出高潮视频 | 性开放的女人aaa片 | 特黄特色大片免费播放器图片 | 欧美色就是色 | 亚洲精品一区二区三区大桥未久 | 国内老熟妇对白xxxxhd | 色综合视频一区二区三区 | 成人性做爰aaa片免费看不忠 | 免费无码午夜福利片69 | 精品国产av色一区二区深夜久久 | 国产人妻精品一区二区三区 | 亚洲狠狠婷婷综合久久 | 3d动漫精品啪啪一区二区中 | 欧美freesex黑人又粗又大 | 欧美日韩在线亚洲综合国产人 | 国产精品无码永久免费888 | 午夜理论片yy44880影院 | 色一情一乱一伦一区二区三欧美 | 欧美日韩人成综合在线播放 | 国产精品久久精品三级 | 久久精品99久久香蕉国产色戒 | 国产精品无码永久免费888 | 日韩精品无码免费一区二区三区 | 国产偷国产偷精品高清尤物 | 日韩精品成人一区二区三区 | 无码帝国www无码专区色综合 | 色婷婷久久一区二区三区麻豆 | 精品无码一区二区三区爱欲 | 国产人成高清在线视频99最全资源 | 最近中文2019字幕第二页 | 国产亚洲美女精品久久久2020 | 女人被男人爽到呻吟的视频 | 丰满少妇人妻久久久久久 | 人妻与老人中文字幕 | 伊人久久大香线蕉av一区二区 | 两性色午夜视频免费播放 | 无码av免费一区二区三区试看 | 日本护士毛茸茸高潮 | 国产美女精品一区二区三区 | 亚洲一区二区三区在线观看网站 | 国产精品美女久久久网av | 日日夜夜撸啊撸 | 窝窝午夜理论片影院 | a国产一区二区免费入口 | 又大又黄又粗又爽的免费视频 | 欧美一区二区三区 | 日韩亚洲欧美中文高清在线 | 午夜精品久久久久久久久 | 国产激情精品一区二区三区 | 亚洲欧美日韩国产精品一区二区 | a国产一区二区免费入口 | 久久精品视频在线看15 | а√天堂www在线天堂小说 | 精品久久综合1区2区3区激情 | 国产香蕉尹人视频在线 | 精品国精品国产自在久国产87 | 国产成人精品优优av | 少妇人妻av毛片在线看 | 国产又粗又硬又大爽黄老大爷视 | 精品国偷自产在线视频 | 久久这里只有精品视频9 | 日本护士毛茸茸高潮 | 人人妻人人澡人人爽人人精品浪潮 | 牲欲强的熟妇农村老妇女视频 | 在线a亚洲视频播放在线观看 | 国产精品久久久午夜夜伦鲁鲁 | 人妻中文无码久热丝袜 | 精品成人av一区二区三区 | 一个人看的视频www在线 | 欧美 日韩 人妻 高清 中文 | 久久综合激激的五月天 | 国产av一区二区三区最新精品 | 久久97精品久久久久久久不卡 | 在线а√天堂中文官网 | 国产av一区二区精品久久凹凸 | 久久精品国产99精品亚洲 | 亚洲中文字幕av在天堂 | 草草网站影院白丝内射 | 国产午夜视频在线观看 | 99久久久无码国产aaa精品 | 撕开奶罩揉吮奶头视频 | 国产性生交xxxxx无码 | 久久99久久99精品中文字幕 | 久久久亚洲欧洲日产国码αv | 午夜精品一区二区三区在线观看 | 少妇的肉体aa片免费 | 荫蒂添的好舒服视频囗交 | 熟妇人妻无码xxx视频 | 精品偷自拍另类在线观看 | 欧美刺激性大交 | 76少妇精品导航 | 欧美日韩人成综合在线播放 | 97se亚洲精品一区 | 欧美自拍另类欧美综合图片区 | 国产国语老龄妇女a片 | 77777熟女视频在线观看 а天堂中文在线官网 | 国产艳妇av在线观看果冻传媒 | 风流少妇按摩来高潮 | 在线播放亚洲第一字幕 | 国产精品第一区揄拍无码 | 人妻少妇精品无码专区二区 | 日本丰满护士爆乳xxxx | 久久成人a毛片免费观看网站 | 澳门永久av免费网站 | 亚洲国产一区二区三区在线观看 | 亚洲精品久久久久avwww潮水 | 中文字幕乱码亚洲无线三区 | 亚洲一区二区三区 | 色婷婷久久一区二区三区麻豆 | 欧美性猛交内射兽交老熟妇 | 九九综合va免费看 | 美女张开腿让人桶 | 久久综合久久自在自线精品自 | 成人性做爰aaa片免费看不忠 | 国产精品va在线播放 | 国产成人综合美国十次 | 天天做天天爱天天爽综合网 | 一本加勒比波多野结衣 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 国产人妻人伦精品1国产丝袜 | 久久精品国产99精品亚洲 | 久久亚洲日韩精品一区二区三区 | 玩弄人妻少妇500系列视频 | 亚洲欧洲中文日韩av乱码 | 国产精品久久久久9999小说 | 久久久婷婷五月亚洲97号色 | 亚洲人成影院在线观看 | 久久无码中文字幕免费影院蜜桃 | 国产va免费精品观看 | 久久国产36精品色熟妇 | 亚洲男人av天堂午夜在 | 亚洲 激情 小说 另类 欧美 | av人摸人人人澡人人超碰下载 | 国产乱子伦视频在线播放 | 国产精品久久久久影院嫩草 | 超碰97人人射妻 | 欧美成人高清在线播放 | 亚洲综合在线一区二区三区 | 成年美女黄网站色大免费全看 | 精品久久久久久亚洲精品 | 成熟女人特级毛片www免费 | 国产精品第一区揄拍无码 | 性色av无码免费一区二区三区 | 76少妇精品导航 | 国产人妻精品一区二区三区 | 欧美日本精品一区二区三区 | 欧美 亚洲 国产 另类 | 国产一精品一av一免费 | 人妻互换免费中文字幕 | 亚洲欧美精品伊人久久 | 中文字幕无码免费久久99 | 久久精品一区二区三区四区 | 午夜福利试看120秒体验区 | 国产女主播喷水视频在线观看 | 一本一道久久综合久久 | 亚洲国产精品久久久久久 | 女人高潮内射99精品 | 国产av一区二区精品久久凹凸 | 亚洲无人区午夜福利码高清完整版 | 日韩亚洲欧美中文高清在线 | 亚洲午夜福利在线观看 | 国内揄拍国内精品人妻 | 国内精品久久毛片一区二区 | √8天堂资源地址中文在线 | 久久久久免费精品国产 | 99久久精品无码一区二区毛片 | 国产艳妇av在线观看果冻传媒 | 久久天天躁狠狠躁夜夜免费观看 | 天天躁夜夜躁狠狠是什么心态 | 国产成人综合色在线观看网站 | 丰满少妇熟乱xxxxx视频 | 夜夜躁日日躁狠狠久久av | 免费中文字幕日韩欧美 | 性色欲网站人妻丰满中文久久不卡 | 成人欧美一区二区三区黑人 | 蜜桃视频插满18在线观看 | 俺去俺来也www色官网 | 国产三级精品三级男人的天堂 | 日本一区二区三区免费高清 | 国产三级久久久精品麻豆三级 | 国产精品久久国产精品99 | 波多野结衣一区二区三区av免费 | 亚洲欧洲中文日韩av乱码 | 好爽又高潮了毛片免费下载 | 中文字幕人妻无码一夲道 | 人妻天天爽夜夜爽一区二区 | 久久精品无码一区二区三区 | 精品国产av色一区二区深夜久久 | 欧美35页视频在线观看 | 日本高清一区免费中文视频 | 黑人粗大猛烈进出高潮视频 | 国产人成高清在线视频99最全资源 | 领导边摸边吃奶边做爽在线观看 | 图片区 小说区 区 亚洲五月 | 国产免费观看黄av片 | 1000部夫妻午夜免费 | 日韩精品一区二区av在线 | 呦交小u女精品视频 | 国产精品久久国产精品99 | 久久国产精品萌白酱免费 | 久久久精品国产sm最大网站 | 欧美自拍另类欧美综合图片区 | 免费国产黄网站在线观看 | 国产两女互慰高潮视频在线观看 | 国产片av国语在线观看 | 亚洲色欲色欲欲www在线 | 国产亚洲人成a在线v网站 | 国产97在线 | 亚洲 | 性史性农村dvd毛片 | 无码帝国www无码专区色综合 | 国产精品国产三级国产专播 | 国产99久久精品一区二区 | 久久99久久99精品中文字幕 | 丝袜足控一区二区三区 | 天下第一社区视频www日本 | 国产成人无码av在线影院 | 亚洲 a v无 码免 费 成 人 a v | 国产精品久久久午夜夜伦鲁鲁 | 日日碰狠狠丁香久燥 | aⅴ在线视频男人的天堂 | 综合网日日天干夜夜久久 | 精品偷拍一区二区三区在线看 | 亚洲天堂2017无码中文 | 在线a亚洲视频播放在线观看 | 亚洲中文字幕av在天堂 | 狠狠色色综合网站 | 久久精品国产一区二区三区肥胖 | 国产真实夫妇视频 | 久久无码中文字幕免费影院蜜桃 | 国产一区二区三区四区五区加勒比 | 国产口爆吞精在线视频 | 亚洲国产精品无码久久久久高潮 | 无码精品国产va在线观看dvd | 久久综合给合久久狠狠狠97色 | 人妻体内射精一区二区三四 | 欧美日韩一区二区免费视频 | 人人妻在人人 | 国产真实乱对白精彩久久 | 免费播放一区二区三区 | 女人被男人爽到呻吟的视频 | 少妇高潮一区二区三区99 | 欧美 亚洲 国产 另类 | 2020久久超碰国产精品最新 | 久久综合给久久狠狠97色 | 日本一区二区三区免费高清 | 国产精品久免费的黄网站 | 伊人久久婷婷五月综合97色 | 永久免费精品精品永久-夜色 | 免费国产黄网站在线观看 | 无套内射视频囯产 | 亚洲国产精品毛片av不卡在线 | 婷婷五月综合激情中文字幕 | 国产电影无码午夜在线播放 | 98国产精品综合一区二区三区 | 久久午夜夜伦鲁鲁片无码免费 | 国产色视频一区二区三区 | 人人妻人人澡人人爽欧美一区九九 | 2020久久超碰国产精品最新 | 亚洲精品中文字幕 | 亚洲伊人久久精品影院 | 亲嘴扒胸摸屁股激烈网站 | 男女爱爱好爽视频免费看 | 亚洲成a人片在线观看无码3d | 曰韩无码二三区中文字幕 | 少妇邻居内射在线 | 人妻少妇精品视频专区 | 久久精品人人做人人综合试看 | 88国产精品欧美一区二区三区 | 熟妇人妻激情偷爽文 | 丰满少妇女裸体bbw | 天天综合网天天综合色 | 夜夜影院未满十八勿进 | 国产精品永久免费视频 | 日本熟妇大屁股人妻 | 日日躁夜夜躁狠狠躁 | 荫蒂被男人添的好舒服爽免费视频 | 日韩人妻系列无码专区 | 成人av无码一区二区三区 | 久激情内射婷内射蜜桃人妖 | 国产亚洲美女精品久久久2020 | 中文字幕人妻无码一夲道 | 高中生自慰www网站 | 亚洲精品鲁一鲁一区二区三区 | 国产电影无码午夜在线播放 | 久久午夜无码鲁丝片秋霞 | 国产片av国语在线观看 | 日本丰满护士爆乳xxxx | 国产精品亚洲а∨无码播放麻豆 | 女人被男人躁得好爽免费视频 | 成人女人看片免费视频放人 | 小泽玛莉亚一区二区视频在线 | 天干天干啦夜天干天2017 | 狂野欧美激情性xxxx | 亚洲乱码中文字幕在线 | 天堂а√在线地址中文在线 | 国产在线精品一区二区高清不卡 | 激情综合激情五月俺也去 | 77777熟女视频在线观看 а天堂中文在线官网 | 国产一区二区三区日韩精品 | 久久99精品久久久久久 | 强开小婷嫩苞又嫩又紧视频 | 青草视频在线播放 | 日产精品99久久久久久 | 狠狠综合久久久久综合网 | 在线а√天堂中文官网 | 人人爽人人澡人人人妻 | 美女黄网站人色视频免费国产 | 日韩精品无码一区二区中文字幕 | 久久99久久99精品中文字幕 | 一本久久伊人热热精品中文字幕 | 亚洲一区二区三区播放 | 国产成人人人97超碰超爽8 | 日韩视频 中文字幕 视频一区 | 荫蒂被男人添的好舒服爽免费视频 | 国产亚洲精品久久久久久久 | 成人无码视频在线观看网站 | 激情内射亚州一区二区三区爱妻 | 中文字幕+乱码+中文字幕一区 | 久久综合九色综合欧美狠狠 | 亚洲成a人片在线观看无码 | 国产av人人夜夜澡人人爽麻豆 | 精品欧洲av无码一区二区三区 | 精品久久8x国产免费观看 | 成熟女人特级毛片www免费 | 国产日产欧产精品精品app | 中文字幕乱妇无码av在线 | 少妇性荡欲午夜性开放视频剧场 | 亚洲色大成网站www国产 | 在线 国产 欧美 亚洲 天堂 | 国产亚洲视频中文字幕97精品 | 国产午夜精品一区二区三区嫩草 | 国产av无码专区亚洲a∨毛片 | 2020最新国产自产精品 | 99视频精品全部免费免费观看 | 国产成人久久精品流白浆 | 天堂久久天堂av色综合 | 亚洲国产日韩a在线播放 | 国产另类ts人妖一区二区 | 色婷婷久久一区二区三区麻豆 | 日日碰狠狠躁久久躁蜜桃 | 伊在人天堂亚洲香蕉精品区 | 欧美肥老太牲交大战 | 在线观看免费人成视频 | 7777奇米四色成人眼影 | 亚洲男人av天堂午夜在 | 免费人成在线观看网站 | 日本www一道久久久免费榴莲 | 久久精品女人天堂av免费观看 | 国产艳妇av在线观看果冻传媒 | 伊人久久大香线蕉亚洲 | 国产成人久久精品流白浆 | 欧美自拍另类欧美综合图片区 | 欧美xxxxx精品 | 午夜免费福利小电影 | 日日橹狠狠爱欧美视频 | 国产做国产爱免费视频 | 天天燥日日燥 | 2019午夜福利不卡片在线 | 97无码免费人妻超级碰碰夜夜 | 久久久av男人的天堂 | 成 人 免费观看网站 | 国产精品久久福利网站 | 国产精品久久久久无码av色戒 | 精品一二三区久久aaa片 | 中文字幕久久久久人妻 | 天堂亚洲2017在线观看 | 日本www一道久久久免费榴莲 | аⅴ资源天堂资源库在线 | 日韩视频 中文字幕 视频一区 | 久久精品99久久香蕉国产色戒 | 国精产品一品二品国精品69xx | 国产suv精品一区二区五 | 久久久婷婷五月亚洲97号色 | 三上悠亚人妻中文字幕在线 | 377p欧洲日本亚洲大胆 | 女人色极品影院 | 国产午夜精品一区二区三区嫩草 | 国产精品久久久久9999小说 | 日本免费一区二区三区最新 | 国产一区二区三区精品视频 | 国产人妻大战黑人第1集 | 久久久久免费精品国产 | 亚洲日韩乱码中文无码蜜桃臀网站 | 九月婷婷人人澡人人添人人爽 | 清纯唯美经典一区二区 | 无码一区二区三区在线观看 | 亚洲爆乳大丰满无码专区 | 一二三四社区在线中文视频 | 东京一本一道一二三区 | 99国产精品白浆在线观看免费 | 美女黄网站人色视频免费国产 | 日产精品高潮呻吟av久久 | 沈阳熟女露脸对白视频 | 丝袜美腿亚洲一区二区 | 国产精品永久免费视频 | 熟妇人妻无码xxx视频 | 最新国产麻豆aⅴ精品无码 | 久久成人a毛片免费观看网站 | 狠狠综合久久久久综合网 | 99国产欧美久久久精品 | 欧美日韩色另类综合 | 国产午夜视频在线观看 | 国产精品内射视频免费 | 亚洲欧美色中文字幕在线 | 呦交小u女精品视频 | 精品乱子伦一区二区三区 | 啦啦啦www在线观看免费视频 | 18精品久久久无码午夜福利 | 超碰97人人射妻 | 青青青爽视频在线观看 | 色诱久久久久综合网ywww | 国产av久久久久精东av | 亚洲成熟女人毛毛耸耸多 | 3d动漫精品啪啪一区二区中 | 国产农村妇女高潮大叫 | 日韩欧美群交p片內射中文 | 性色欲网站人妻丰满中文久久不卡 | 人人澡人人妻人人爽人人蜜桃 | 俺去俺来也www色官网 | 55夜色66夜色国产精品视频 | 熟妇人妻中文av无码 | 欧美日韩视频无码一区二区三 | 国产成人精品必看 | 欧美 日韩 亚洲 在线 | 国产成人无码a区在线观看视频app | 麻豆国产人妻欲求不满谁演的 | 成人毛片一区二区 | aⅴ在线视频男人的天堂 | 中文无码精品a∨在线观看不卡 | 亚洲欧洲日本综合aⅴ在线 | 久久99精品久久久久久 | 色婷婷久久一区二区三区麻豆 | 欧美日韩久久久精品a片 | 亚洲日韩av一区二区三区四区 | 亚洲精品久久久久久一区二区 | 久久成人a毛片免费观看网站 | 国产深夜福利视频在线 | 国产三级久久久精品麻豆三级 | 久久亚洲精品成人无码 | 老头边吃奶边弄进去呻吟 | 亚洲综合久久一区二区 | 在线成人www免费观看视频 | 久久综合香蕉国产蜜臀av | 日本护士xxxxhd少妇 | 婷婷综合久久中文字幕蜜桃三电影 | 亚洲中文字幕无码中文字在线 | 国产特级毛片aaaaaaa高清 | 亚洲一区二区三区香蕉 | 亚洲欧洲无卡二区视頻 | 东京热一精品无码av | 免费人成网站视频在线观看 | 国产成人人人97超碰超爽8 | 国产午夜亚洲精品不卡 | 色综合久久网 | 熟女少妇人妻中文字幕 | 无码一区二区三区在线观看 | 亚洲天堂2017无码 | 99久久久国产精品无码免费 | 乌克兰少妇xxxx做受 | 国产福利视频一区二区 | 日本www一道久久久免费榴莲 | 樱花草在线社区www | 国产综合色产在线精品 | 亚洲精品一区二区三区在线观看 | 奇米影视888欧美在线观看 | 久久国产精品_国产精品 | 内射巨臀欧美在线视频 | 少妇人妻大乳在线视频 | 偷窥村妇洗澡毛毛多 | 精品 日韩 国产 欧美 视频 | 久久亚洲日韩精品一区二区三区 | 精品国偷自产在线视频 | 97夜夜澡人人爽人人喊中国片 | 色诱久久久久综合网ywww | 中文字幕无码av激情不卡 | 秋霞成人午夜鲁丝一区二区三区 | 兔费看少妇性l交大片免费 | 久久天天躁夜夜躁狠狠 | 久久亚洲a片com人成 | 人妻少妇精品无码专区动漫 | 日韩av无码中文无码电影 | 久久99精品久久久久婷婷 | 精品亚洲成av人在线观看 | 欧美日韩综合一区二区三区 | 人人妻人人澡人人爽欧美精品 | 国产人妻大战黑人第1集 | 澳门永久av免费网站 | 国产黄在线观看免费观看不卡 | 精品成人av一区二区三区 | 国产绳艺sm调教室论坛 | 亚洲春色在线视频 | 在线精品国产一区二区三区 | 性开放的女人aaa片 | 扒开双腿疯狂进出爽爽爽视频 | 夫妻免费无码v看片 | 国产乱人伦偷精品视频 | 亚洲国产成人a精品不卡在线 | 亚洲国产精品美女久久久久 | 中文字幕无码av波多野吉衣 | 骚片av蜜桃精品一区 | 免费男性肉肉影院 | 九九久久精品国产免费看小说 | 亚洲午夜久久久影院 | 野狼第一精品社区 | 天天做天天爱天天爽综合网 | 国产高清不卡无码视频 | 99视频精品全部免费免费观看 | 欧美性生交xxxxx久久久 | 国产人妻久久精品二区三区老狼 | 波多野结衣一区二区三区av免费 | 久久伊人色av天堂九九小黄鸭 | 色婷婷av一区二区三区之红樱桃 | 窝窝午夜理论片影院 | 日日摸日日碰夜夜爽av | 欧美 日韩 人妻 高清 中文 | 国产高潮视频在线观看 | 99久久婷婷国产综合精品青草免费 | 亚洲精品国产第一综合99久久 | 欧美成人高清在线播放 | 青青久在线视频免费观看 | 久久久国产一区二区三区 | 亚洲精品午夜国产va久久成人 | 野外少妇愉情中文字幕 | 嫩b人妻精品一区二区三区 | 日本肉体xxxx裸交 | ass日本丰满熟妇pics | 性欧美大战久久久久久久 | 国产成人综合美国十次 | 无套内谢的新婚少妇国语播放 | 蜜桃视频韩日免费播放 | 国产亚av手机在线观看 | 少妇被黑人到高潮喷出白浆 | 亚洲精品无码国产 | 最近的中文字幕在线看视频 | aⅴ在线视频男人的天堂 | 久久久无码中文字幕久... | 377p欧洲日本亚洲大胆 | 18禁止看的免费污网站 | 日韩精品a片一区二区三区妖精 | 中文字幕乱码人妻无码久久 | 久久久久成人片免费观看蜜芽 | 久久久精品欧美一区二区免费 | 午夜丰满少妇性开放视频 | 给我免费的视频在线观看 | 精品国偷自产在线 | 色妞www精品免费视频 | 亚洲人成人无码网www国产 | 午夜福利一区二区三区在线观看 | 亚洲精品鲁一鲁一区二区三区 | 强奷人妻日本中文字幕 | 日韩欧美群交p片內射中文 | 久久久久免费精品国产 | 2020久久香蕉国产线看观看 | 性做久久久久久久免费看 | 嫩b人妻精品一区二区三区 | 亚洲欧美综合区丁香五月小说 | 国产av一区二区精品久久凹凸 | 色一情一乱一伦一区二区三欧美 | 熟女体下毛毛黑森林 | 熟妇人妻无码xxx视频 | 丰满人妻翻云覆雨呻吟视频 | 任你躁国产自任一区二区三区 | 天干天干啦夜天干天2017 | 人妻aⅴ无码一区二区三区 | 一本大道伊人av久久综合 | 亚洲成av人片在线观看无码不卡 | 国产乱子伦视频在线播放 | 丰满肥臀大屁股熟妇激情视频 | 精品久久久无码中文字幕 | 国产精品人人爽人人做我的可爱 | 色欲久久久天天天综合网精品 | 欧美zoozzooz性欧美 | 国产日产欧产精品精品app | 爱做久久久久久 | 无码毛片视频一区二区本码 | 国产精品第一区揄拍无码 | 国产日产欧产精品精品app | 人妻体内射精一区二区三四 | 亚洲狠狠婷婷综合久久 | 大色综合色综合网站 | 中文字幕乱码亚洲无线三区 | 国产欧美熟妇另类久久久 |