整個SPI驅動架構可以分為協議驅動、通用接口層和控制器驅動三大部分。其中,控制器驅動即spi主機,負責最底層的數據收發工作,為了完成數據的收發工作,控制器驅動需要完成以下這些功能:
(1)申請必要的硬件資源,例如中斷,DMA通道,DMA內存緩沖區等等;
(2)配置SPI控制器的工作模式和參數,使之可以和相應的設備進行正確的數據交換工作;
(3)向通用接口層提供接口,使得上層的協議驅動可以通過通用接口層訪問控制器驅動;
(4)配合通用接口層,完成數據消息隊列的排隊和處理,直到消息隊列變空為止。
1 控制器設備platform_device
1.1 定義platform_device
spi控制器遵循linux的設備模型框架,所以,一個spi控制器在代碼中對應一個掛在platfrom bus下面的一個device設備。所以在板級的代碼中為SPI控制器定義一個platform_device結構即可。spi的platform_device其實就是spi_master即spi主機。下面以Samsung的SOC芯片:S32440,做為例子,看看如何定義這個platform_device。以下的代碼來自:arch\arm\mach-s3c24xx\mach-mini2440.c中:
因為會有多個platfrom device,所以定義為數組:
1 static struct platform_device *mini2440_devices[] __initdata = { 2 &s3c_device_ohci, 3 &s3c_device_wdt, 4 &s3c_device_i2c0, 5 &s3c_device_rtc, 6 &s3c_device_usbgadget, 7 &mini2440_device_eth, 8 &mini2440_led1, 9 &mini2440_led2, 10 &mini2440_led3, 11 &mini2440_led4, 12 &mini2440_button_device, 13 &s3c_device_nand, 14 &s3c_device_sdi, 15 &s3c_device_iis, 16 &uda1340_codec, 17 &mini2440_audio, 18 };
上面數組中沒有添加spi的platfrom,需要自己定義並添加。如下:
1 struct platform_device s3c2440_device_spi0 = { 2 .name = "s3c6410-spi", 3 .id = 0, 4 .num_resources = ARRAY_SIZE(s3c64xx_spi0_resource), 5 .resource = s3c2440_spi0_resource, 6 .dev = { 7 .dma_mask = &samsung_device_dma_mask, 8 .coherent_dma_mask = DMA_BIT_MASK(32), 9 }, 10 };
定義s3c2440_spi0_resource
1 static struct resource s3c2440_spi0_resource[] = { 2 [0] = DEFINE_RES_MEM(S3C_PA_SPI0, SZ_256), 3 [1] = DEFINE_RES_DMA(DMACH_SPI0_TX), 4 [2] = DEFINE_RES_DMA(DMACH_SPI0_RX), 5 [3] = DEFINE_RES_IRQ(IRQ_SPI0), 6 };
然后還要定義s3c2440_spi0_resource.
最終在kernel初始化的是會去調用。
1 static void __init mini2440_init(void) 2 { 3 struct mini2440_features_t features = { 0 }; 4 int i; 5 6 printk(KERN_INFO "MINI2440: Option string mini2440=%s\n", 7 mini2440_features_str); 8 9 /* Parse the feature string */ 10 mini2440_parse_features(&features, mini2440_features_str); 11 12 /* turn LCD on */ 13 s3c_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND); 14 15 /* Turn the backlight early on */ 16 WARN_ON(gpio_request_one(S3C2410_GPG(4), GPIOF_OUT_INIT_HIGH, NULL)); 17 gpio_free(S3C2410_GPG(4)); 18 19 /* remove pullup on optional PWM backlight -- unused on 3.5 and 7"s */ 20 gpio_request_one(S3C2410_GPB(1), GPIOF_IN, NULL); 21 s3c_gpio_setpull(S3C2410_GPB(1), S3C_GPIO_PULL_UP); 22 gpio_free(S3C2410_GPB(1)); 23 24 /* mark the key as input, without pullups (there is one on the board) */ 25 for (i = 0; i < ARRAY_SIZE(mini2440_buttons); i++) { 26 s3c_gpio_setpull(mini2440_buttons[i].gpio, S3C_GPIO_PULL_UP); 27 s3c_gpio_cfgpin(mini2440_buttons[i].gpio, S3C2410_GPIO_INPUT); 28 } 29 if (features.lcd_index != -1) { 30 int li; 31 32 mini2440_fb_info.displays = 33 &mini2440_lcd_cfg[features.lcd_index]; 34 35 printk(KERN_INFO "MINI2440: LCD"); 36 for (li = 0; li < ARRAY_SIZE(mini2440_lcd_cfg); li++) 37 if (li == features.lcd_index) 38 printk(" [%d:%dx%d]", li, 39 mini2440_lcd_cfg[li].width, 40 mini2440_lcd_cfg[li].height); 41 else 42 printk(" %d:%dx%d", li, 43 mini2440_lcd_cfg[li].width, 44 mini2440_lcd_cfg[li].height); 45 printk("\n"); 46 s3c24xx_fb_set_platdata(&mini2440_fb_info); 47 } 48 49 s3c24xx_udc_set_platdata(&mini2440_udc_cfg); 50 s3c24xx_mci_set_platdata(&mini2440_mmc_cfg); 51 s3c_nand_set_platdata(&mini2440_nand_info); 52 s3c_i2c0_set_platdata(NULL); 53 54 i2c_register_board_info(0, mini2440_i2c_devs, 55 ARRAY_SIZE(mini2440_i2c_devs)); 56 57 platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices)); 58 59 if (features.count) /* the optional features */ 60 platform_add_devices(features.optional, features.count); 61 62 }
2 spi的platform_driver
既然spi控制器是掛在platform下的device,有platform_device,肯定也要有platform_driver
定義位於:/drivers/spi/spi-s3c24xx.c
1 static struct platform_driver s3c24xx_spi_driver = { 2 .probe = s3c24xx_spi_probe, 3 .remove = s3c24xx_spi_remove, 4 .driver = { 5 .name = "s3c2410-spi", 6 .owner = THIS_MODULE, 7 .pm = S3C24XX_SPI_PMOPS, 8 }, 9 };
然后注冊spi platform_driver
module_platform_driver(s3c24xx_spi_driver);
宏展開后:
定義為於:include\linux\Platform_device.h
#define module_platform_driver(__platform_driver) \ module_driver(__platform_driver, platform_driver_register, \ platform_driver_unregister)
最終展開為驅動的入口和出口:
#define module_driver(__driver, __register, __unregister, ...) \ static int __init __driver##_init(void) \ { \ return __register(&(__driver) , ##__VA_ARGS__); \ } \ module_init(__driver##_init); \ static void __exit __driver##_exit(void) \ { \ __unregister(&(__driver) , ##__VA_ARGS__); \ } \ module_exit(__driver##_exit);
3 platform_device和platform_driver的匹配
當platform_device或者platform_driver添加到platform_bus的時候會調用platform_match()去匹配。
static int platform_match(struct device *dev, struct device_driver *drv) { .... }
匹配成功就會調用probe函數s3c24xx_spi_probe() :
除了完成必要的硬件資源初始化工作以外,最重要的工作就是通過spi_bitbang_start()完成了對控制器的注冊工作。
1 static int s3c24xx_spi_probe(struct platform_device *pdev) 2 { 3 struct s3c2410_spi_info *pdata; 4 struct s3c24xx_spi *hw; 5 struct spi_master *master; 6 struct resource *res; 7 int err = 0; 8 9 master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi)); 10 if (master == NULL) { 11 dev_err(&pdev->dev, "No memory for spi_master\n"); 12 err = -ENOMEM; 13 goto err_nomem; 14 } 15 16 hw = spi_master_get_devdata(master); 17 memset(hw, 0, sizeof(struct s3c24xx_spi)); 18 19 hw->master = spi_master_get(master); 20 hw->pdata = pdata = pdev->dev.platform_data; 21 hw->dev = &pdev->dev; 22 23 if (pdata == NULL) { 24 dev_err(&pdev->dev, "No platform data supplied\n"); 25 err = -ENOENT; 26 goto err_no_pdata; 27 } 28 29 platform_set_drvdata(pdev, hw); 30 init_completion(&hw->done); 31 32 /* initialise fiq handler */ 33 34 s3c24xx_spi_initfiq(hw); 35 36 /* setup the master state. */ 37 38 /* the spi->mode bits understood by this driver: */ 39 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; 40 41 master->num_chipselect = hw->pdata->num_cs; 42 master->bus_num = pdata->bus_num; 43 44 /* setup the state for the bitbang driver */ 45 46 hw->bitbang.master = hw->master; 47 hw->bitbang.setup_transfer = s3c24xx_spi_setupxfer; 48 hw->bitbang.chipselect = s3c24xx_spi_chipsel; 49 hw->bitbang.txrx_bufs = s3c24xx_spi_txrx; 50 51 hw->master->setup = s3c24xx_spi_setup; 52 hw->master->cleanup = s3c24xx_spi_cleanup; 53 54 dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang); 55 56 /* find and map our resources */ 57 58 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 59 if (res == NULL) { 60 dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n"); 61 err = -ENOENT; 62 goto err_no_iores; 63 } 64 65 hw->ioarea = request_mem_region(res->start, resource_size(res), 66 pdev->name); 67 68 if (hw->ioarea == NULL) { 69 dev_err(&pdev->dev, "Cannot reserve region\n"); 70 err = -ENXIO; 71 goto err_no_iores; 72 } 73 74 hw->regs = ioremap(res->start, resource_size(res)); 75 if (hw->regs == NULL) { 76 dev_err(&pdev->dev, "Cannot map IO\n"); 77 err = -ENXIO; 78 goto err_no_iomap; 79 } 80 81 hw->irq = platform_get_irq(pdev, 0); 82 if (hw->irq < 0) { 83 dev_err(&pdev->dev, "No IRQ specified\n"); 84 err = -ENOENT; 85 goto err_no_irq; 86 } 87 88 err = request_irq(hw->irq, s3c24xx_spi_irq, 0, pdev->name, hw); 89 if (err) { 90 dev_err(&pdev->dev, "Cannot claim IRQ\n"); 91 goto err_no_irq; 92 } 93 94 hw->clk = clk_get(&pdev->dev, "spi"); 95 if (IS_ERR(hw->clk)) { 96 dev_err(&pdev->dev, "No clock for device\n"); 97 err = PTR_ERR(hw->clk); 98 goto err_no_clk; 99 } 100 101 /* setup any gpio we can */ 102 103 if (!pdata->set_cs) { 104 if (pdata->pin_cs < 0) { 105 dev_err(&pdev->dev, "No chipselect pin\n"); 106 err = -EINVAL; 107 goto err_register; 108 } 109 110 err = gpio_request(pdata->pin_cs, dev_name(&pdev->dev)); 111 if (err) { 112 dev_err(&pdev->dev, "Failed to get gpio for cs\n"); 113 goto err_register; 114 } 115 116 hw->set_cs = s3c24xx_spi_gpiocs; 117 gpio_direction_output(pdata->pin_cs, 1); 118 } else 119 hw->set_cs = pdata->set_cs; 120 121 s3c24xx_spi_initialsetup(hw); 122 123 /* register our spi controller */ 124 125 err = spi_bitbang_start(&hw->bitbang);//注冊spi控制器,即spi_master 126 if (err) { 127 dev_err(&pdev->dev, "Failed to register SPI master\n"); 128 goto err_register; 129 } 130 131 return 0; 132 133 err_register: 134 if (hw->set_cs == s3c24xx_spi_gpiocs) 135 gpio_free(pdata->pin_cs); 136 137 clk_disable(hw->clk); 138 clk_put(hw->clk); 139 140 err_no_clk: 141 free_irq(hw->irq, hw); 142 143 err_no_irq: 144 iounmap(hw->regs); 145 146 err_no_iomap: 147 release_resource(hw->ioarea); 148 kfree(hw->ioarea); 149 150 err_no_iores: 151 err_no_pdata: 152 spi_master_put(hw->master); 153 154 err_nomem: 155 return err; 156 }
4 注冊spi控制器
1 int spi_bitbang_start(struct spi_bitbang *bitbang) 2 { 3 struct spi_master *master = bitbang->master; 4 int status; 5 6 if (!master || !bitbang->chipselect) 7 return -EINVAL; 8 9 INIT_WORK(&bitbang->work, bitbang_work); 10 spin_lock_init(&bitbang->lock); 11 INIT_LIST_HEAD(&bitbang->queue); 12 13 if (!master->mode_bits) 14 master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags; 15 16 if (!master->transfer) 17 master->transfer = spi_bitbang_transfer; 18 if (!bitbang->txrx_bufs) { 19 bitbang->use_dma = 0; 20 bitbang->txrx_bufs = spi_bitbang_bufs; 21 if (!master->setup) { 22 if (!bitbang->setup_transfer) 23 bitbang->setup_transfer = 24 spi_bitbang_setup_transfer; 25 master->setup = spi_bitbang_setup; 26 master->cleanup = spi_bitbang_cleanup; 27 } 28 } else if (!master->setup) 29 return -EINVAL; 30 if (master->transfer == spi_bitbang_transfer && 31 !bitbang->setup_transfer) 32 return -EINVAL; 33 34 /* this task is the only thing to touch the SPI bits */ 35 bitbang->busy = 0; 36 bitbang->workqueue = create_singlethread_workqueue( 37 dev_name(master->dev.parent)); 38 if (bitbang->workqueue == NULL) { 39 status = -EBUSY; 40 goto err1; 41 } 42 43 /* driver may get busy before register() returns, especially 44 * if someone registered boardinfo for devices 45 */ 46 status = spi_register_master(master);//注冊spi控制器 47 if (status < 0) 48 goto err2; 49 50 return status; 51 52 err2: 53 destroy_workqueue(bitbang->workqueue); 54 err1: 55 return status; 56 }
4.2 spi_register_master
對應spi控制器,即spi主機,負責按照設定的物理信號格式在主控和spi設備之間交換數據,SPI控制器數據是如何被傳輸的,而不關心數據的內容。SPI通用接口層用spi_master結構來表示一個spi控制器。
1 struct spi_master { 2 struct device dev; 3 4 struct list_head list;//系統可能有多個控制器,用該鏈表鏈接在一個全局鏈表變量上 5 6 /* other than negative (== assign one dynamically), bus_num is fully 7 * board-specific. usually that simplifies to being SOC-specific. 8 * example: one SOC has three SPI controllers, numbered 0..2, 9 * and one board's schematics might show it using SPI-2. software 10 * would normally use bus_num=2 for that controller. 11 */ 12 s16 bus_num;//控制器對應的spi總線編號,從0開始,通常由板級代碼設定 13 14 /* chipselects will be integral to many controllers; some others 15 * might use board-specific GPIOs. 16 */ 17 u16 num_chipselect;//連接到該spi控制器的片選信號的個數 18 19 /* some SPI controllers pose alignment requirements on DMAable 20 * buffers; let protocol drivers know about these requirements. 21 */ 22 u16 dma_alignment; 23 24 /* spi_device.mode flags understood by this controller driver */ 25 u16 mode_bits;//工作模式,由驅動解釋該模式的意義 26 27 /* bitmask of supported bits_per_word for transfers */ 28 u32 bits_per_word_mask; 29 30 /* other constraints relevant to this driver */ 31 u16 flags; 32 #define SPI_MASTER_HALF_DUPLEX BIT(0) /* can't do full duplex */ 33 #define SPI_MASTER_NO_RX BIT(1) /* can't do buffer read */ 34 #define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */ 35 36 /* lock and mutex for SPI bus locking */ 37 spinlock_t bus_lock_spinlock; 38 struct mutex bus_lock_mutex; 39 40 /* flag indicating that the SPI bus is locked for exclusive use */ 41 bool bus_lock_flag; 42 43 /* Setup mode and clock, etc (spi driver may call many times). 44 * 45 * IMPORTANT: this may be called when transfers to another 46 * device are active. DO NOT UPDATE SHARED REGISTERS in ways 47 * which could break those transfers. 48 */ 49 int (*setup)(struct spi_device *spi);//回調函數,用於設置某個spi設備在該控制器上的工作參數 50 51 /* bidirectional bulk transfers 52 * 53 * + The transfer() method may not sleep; its main role is 54 * just to add the message to the queue. 55 * + For now there's no remove-from-queue operation, or 56 * any other request management 57 * + To a given spi_device, message queueing is pure fifo 58 * 59 * + The master's main job is to process its message queue, 60 * selecting a chip then transferring data 61 * + If there are multiple spi_device children, the i/o queue 62 * arbitration algorithm is unspecified (round robin, fifo, 63 * priority, reservations, preemption, etc) 64 * 65 * + Chipselect stays active during the entire message 66 * (unless modified by spi_transfer.cs_change != 0). 67 * + The message transfers use clock and SPI mode parameters 68 * previously established by setup() for this device 69 */ 70 int (*transfer)(struct spi_device *spi,//用於把包含數據信息的mesg結構加入控制器的消息鏈表中的回調函數 71 struct spi_message *mesg); 72 73 /* called on release() to free memory provided by spi_master */ 74 void (*cleanup)(struct spi_device *spi);//當spi_master被釋放時,該函數被調用 75 76 /* 77 * These hooks are for drivers that want to use the generic 78 * master transfer queueing mechanism. If these are used, the 79 * transfer() function above must NOT be specified by the driver. 80 * Over time we expect SPI drivers to be phased over to this API. 81 */ 82 bool queued; 83 struct kthread_worker kworker;//用於管理數據傳輸消息隊列的工作隊列線程 84 struct task_struct *kworker_task; 85 struct kthread_work pump_messages;//具體實現數據傳輸隊列的工作隊列 86 spinlock_t queue_lock; 87 struct list_head queue;//控制器的消息隊列,所有等待傳輸的消息隊列掛在該鏈表下 88 struct spi_message *cur_msg;//正帶處理的消息隊列 89 bool busy; 90 bool running; 91 bool rt; 92 93 int (*prepare_transfer_hardware)(struct spi_master *master);//回調函數,正式發起傳送前會被調用,用於准備硬件資源 94 int (*transfer_one_message)(struct spi_master *master,//單個消息的原子傳送回調函數,隊列中的每個消息都會調用一次該回調來完成傳輸工作 95 struct spi_message *mesg); 96 int (*unprepare_transfer_hardware)(struct spi_master *master);//清理回調函數 97 /* gpio chip select */ 98 int *cs_gpios;//片選信號所用到的gpio 99 }
spi_master結構通常由控制器驅動定義,然后通過以下通用接口層的API注冊到系統中:
1 int spi_register_master(struct spi_master *master) 2 { 3 static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1); 4 struct device *dev = master->dev.parent; 5 struct boardinfo *bi; 6 int status = -ENODEV; 7 int dynamic = 0; 8 9 if (!dev) 10 return -ENODEV; 11 12 status = of_spi_register_master(master); 13 if (status) 14 return status; 15 16 /* even if it's just one always-selected device, there must 17 * be at least one chipselect 18 */ 19 if (master->num_chipselect == 0) 20 return -EINVAL; 21 22 if ((master->bus_num < 0) && master->dev.of_node) 23 master->bus_num = of_alias_get_id(master->dev.of_node, "spi"); 24 25 /* convention: dynamically assigned bus IDs count down from the max */ 26 if (master->bus_num < 0) { 27 /* FIXME switch to an IDR based scheme, something like 28 * I2C now uses, so we can't run out of "dynamic" IDs 29 */ 30 master->bus_num = atomic_dec_return(&dyn_bus_id); 31 dynamic = 1; 32 } 33 34 spin_lock_init(&master->bus_lock_spinlock); 35 mutex_init(&master->bus_lock_mutex); 36 master->bus_lock_flag = 0; 37 38 /* register the device, then userspace will see it. 39 * registration fails if the bus ID is in use. 40 */ 41 dev_set_name(&master->dev, "spi%u", master->bus_num); 42 status = device_add(&master->dev);//添加spi主機設備(master->dev),spi_device是掛在這個下面,即spi_device的父設備 43 if (status < 0) 44 goto done; 45 dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev), 46 dynamic ? " (dynamic)" : ""); 47 48 /* If we're using a queued driver, start the queue */ 49 if (master->transfer) 50 dev_info(dev, "master is unqueued, this is deprecated\n"); 51 else { 52 status = spi_master_initialize_queue(master); 53 if (status) { 54 device_unregister(&master->dev); 55 goto done; 56 } 57 } 58 59 mutex_lock(&board_lock); 60 list_add_tail(&master->list, &spi_master_list); 61 list_for_each_entry(bi, &board_list, list) 62 spi_match_master_to_boardinfo(master, &bi->board_info);//匹配spi主機和spi板機設備,建立spi_device。 63 mutex_unlock(&board_lock); 64 65 /* Register devices from the device tree and ACPI */ 66 of_register_spi_devices(master);//設備樹匹配操作這個待分析??? 67 acpi_register_spi_devices(master); 68 done: 69 return status; 70 }
然后調用spi_match_master_to_boardinfo
1 static void spi_match_master_to_boardinfo(struct spi_master *master, 2 struct spi_board_info *bi) 3 { 4 struct spi_device *dev; 5 6 if (master->bus_num != bi->bus_num) 7 return; 8 9 dev = spi_new_device(master, bi);//注冊spi_device 10 if (!dev) 11 dev_err(master->dev.parent, "can't create new device for %s\n", 12 bi->modalias); 13 }
4.3 設備樹匹配操作
1 /**
2 * of_register_spi_devices() - Register child devices onto the SPI bus
3 * @master: Pointer to spi_master device
4 *
5 * Registers an spi_device for each child node of master node which has a 'reg'
6 * property.
7 */
8 static void of_register_spi_devices(struct spi_master *master)
9 { 10 struct spi_device *spi; 11 struct device_node *nc; 12 const __be32 *prop; 13 char modalias[SPI_NAME_SIZE + 4]; 14 int rc; 15 int len; 16 17 if (!master->dev.of_node) 18 return; 19 20 for_each_available_child_of_node(master->dev.of_node, nc) { 21 /* Alloc an spi_device */ 22 spi = spi_alloc_device(master); 23 if (!spi) { 24 dev_err(&master->dev, "spi_device alloc error for %s\n", 25 nc->full_name); 26 spi_dev_put(spi); 27 continue; 28 } 29 30 /* Select device driver */ 31 if (of_modalias_node(nc, spi->modalias, 32 sizeof(spi->modalias)) < 0) { 33 dev_err(&master->dev, "cannot find modalias for %s\n", 34 nc->full_name); 35 spi_dev_put(spi); 36 continue; 37 } 38 39 /* Device address */ 40 prop = of_get_property(nc, "reg", &len); 41 if (!prop || len < sizeof(*prop)) { 42 dev_err(&master->dev, "%s has no 'reg' property\n", 43 nc->full_name); 44 spi_dev_put(spi); 45 continue; 46 } 47 spi->chip_select = be32_to_cpup(prop); 48 49 /* Mode (clock phase/polarity/etc.) */ 50 if (of_find_property(nc, "spi-cpha", NULL)) 51 spi->mode |= SPI_CPHA; 52 if (of_find_property(nc, "spi-cpol", NULL)) 53 spi->mode |= SPI_CPOL; 54 if (of_find_property(nc, "spi-cs-high", NULL)) 55 spi->mode |= SPI_CS_HIGH; 56 if (of_find_property(nc, "spi-3wire", NULL)) 57 spi->mode |= SPI_3WIRE; 58 59 /* Device speed */ 60 prop = of_get_property(nc, "spi-max-frequency", &len); 61 if (!prop || len < sizeof(*prop)) { 62 dev_err(&master->dev, "%s has no 'spi-max-frequency' property\n", 63 nc->full_name); 64 spi_dev_put(spi); 65 continue; 66 } 67 spi->max_speed_hz = be32_to_cpup(prop); 68 69 /* IRQ */ 70 spi->irq = irq_of_parse_and_map(nc, 0); 71 72 /* Store a pointer to the node in the device structure */ 73 of_node_get(nc); 74 spi->dev.of_node = nc; 75 76 /* Register the new device */ 77 snprintf(modalias, sizeof(modalias), "%s%s", SPI_MODULE_PREFIX, 78 spi->modalias); 79 request_module(modalias); 80 rc = spi_add_device(spi); 81 if (rc) { 82 dev_err(&master->dev, "spi_device register error %s\n", 83 nc->full_name); 84 spi_dev_put(spi); 85 } 86 87 } 88 }
5 spi_device的注冊建立
當spi主機和spi板機設備匹配時調用spi_new_device 注冊spi設備。詳見: linux設備驅動SPI詳解2-通用接口層 , 將spi_device添加到spi_bus上。所以對於spi來說,spi控制器是掛在platform虛擬總線上,但spi同時又有自己的bus,bus下有spi_device和spi_driver。
(追尋spi_init也就是spi_bus)
6 實現spi_master中的回調函數
事實上,SPI控制器驅動程序的主要工作,就是要實現spi_master結構中的幾個回調函數,其它的工作邏輯,均由通用接口層幫我們完成,通用接口層會在適當的時機調用這幾個回調函數,各個回調函數的作用如下,具體的實現例子位於:drivers\spi\Spi-s3c24xx.c
int (*setup)(struct spi_device *spi) 當協議驅動希望修改控制器的工作模式或參數時,會調用通用接口層提供的API:spi_setup(),該API函數最后會調用setup回調函數來完成設置工作。 int (*transfer)(struct spi_device *spi, struct spi_message *mesg) 目前已經可以不用我們自己實現該回調函數,初始化時直接設為NULL即可,目前的通用接口層已經實現了消息隊列化,注冊spi_master時,通用接口層會提供實現好的通用函數。現在只有一些老的驅動還在使用該回調方式,新的驅動應該停止使用該回調函數,而是應該使用隊列化的transfer_one_message回調。需要注意的是,我們只能選擇其中一種方式,設置了transfer_one_message回調,就不能設置transfer回調,反之亦然。 void (*cleanup)(struct spi_device *spi) 當一個SPI從設備(spi_device結構)被釋放時,該回調函數會被調用,以便釋放該從設備所占用的硬件資源。 int (*prepare_transfer_hardware)(struct spi_master *master) int (*unprepare_transfer_hardware)(struct spi_master *master) 這兩個回調函數用於在發起一個數據傳送過程前和后,給控制器驅動一個機會,申請或釋放某些必要的硬件資源,例如DMA資源和內存資源等等。int (*transfer_one_message)(struct spi_master *master, struct spi_message *mesg) 當通用接口層發現master的隊列中有消息需要傳送時,會調用該回調函數,所以該函數是真正完成一個消息傳送的工作函數,當傳送工作完成時,應該調用spi_finalize_current_message函數,以便通知通用接口層,發起隊列中的下一個消息的傳送工作。
6.1 spi_master中transfer 回調函數
transfer回調函數的定義flow如下:
s3c24xx_spi_probe()
1 static int s3c24xx_spi_probe(struct platform_device *pdev) 2 { 3 ... 4 5 /* register our spi controller */ 6 7 err = spi_bitbang_start(&hw->bitbang); 8 if (err) { 9 dev_err(&pdev->dev, "Failed to register SPI master\n"); 10 goto err_register; 11 } 12 ... 13 }
函數:spi_bitbang_start,定義位於:drivers\spi\spi-bitbang.c
1 int spi_bitbang_start(struct spi_bitbang *bitbang) 2 { 3 struct spi_master *master = bitbang->master; 4 int status; 5 6 if (!master || !bitbang->chipselect) 7 return -EINVAL; 8 9 INIT_WORK(&bitbang->work, bitbang_work); 10 spin_lock_init(&bitbang->lock); 11 INIT_LIST_HEAD(&bitbang->queue); 12 13 if (!master->mode_bits) 14 master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags; 15 16 if (!master->transfer)//判斷master中transfer回調函數是否存在,s3c24xx_spi_probe函數中沒有為其賦值定義 17 master->transfer = spi_bitbang_transfer;回調函數tranfer賦值 ...
}
tranfer回調函數定義:
1 /** 2 * spi_bitbang_transfer - default submit to transfer queue 3 */ 4 int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m) 5 { 6 struct spi_bitbang *bitbang; 7 unsigned long flags; 8 int status = 0; 9 10 m->actual_length = 0; 11 m->status = -EINPROGRESS; 12 13 bitbang = spi_master_get_devdata(spi->master); 14 15 spin_lock_irqsave(&bitbang->lock, flags); 16 if (!spi->max_speed_hz) 17 status = -ENETDOWN; 18 else { 19 list_add_tail(&m->queue, &bitbang->queue); 20 queue_work(bitbang->workqueue, &bitbang->work); 21 } 22 spin_unlock_irqrestore(&bitbang->lock, flags); 23 24 return status; 25 }
參考博文:https://blog.csdn.net/DroidPhone/java/article/details/24353293