linux SPI驱动——gpio模拟spi驱动(三)
一:首先在我的平台注册platform_device,保证能让spi-gpio.c能执行到probe函数。
1: struct spi_gpio_platform_data {
2: unsigned sck; 3: unsigned mosi; 4: unsigned miso; 5: 6: u16 num_chipselect; 7: };1: //#define NCS GPIO_PB(2) //定义SS所对应的GPIO接口编号
2: //#define SCLK GPIO_PB(0) //定义SCLK所对应的GPIO接口编号
3: //#define MOSI GPIO_PB(4) //定义SCLK所对应的GPIO接口编号
4: //#define MISO GPIO_PB(1)
5: static struct spi_gpio_platform_data jz_spi_gpio_data = {
6: .sck = GPIO_PB(0), //GPIO_SPI_SCK,
7: .mosi = GPIO_PB(4), //GPIO_SPI_MOSI,
8: .miso = GPIO_PB(1), //GPIO_SPI_MISO,
9: .num_chipselect = 1, 10: }; 11: 12: struct platform_device jz_spi_gpio_device = {
13: .name = "spi_gpio",
14: .id = 0, 15: .dev = { 16: .platform_data = &jz_spi_gpio_data, 17: }, 18: };1: platform_device_register(&jz_spi_gpio_device);
二:注册platform_driver在spi_gpio.c里面注册platform driver
1: MODULE_ALIAS("platform:" DRIVER_NAME);
2: 3: static struct platform_driver spi_gpio_driver = {
4: .driver.name = DRIVER_NAME, 5: .driver.owner = THIS_MODULE, 6: .remove = __exit_p(spi_gpio_remove), 7: }; 8: 9: static int __init spi_gpio_init(void)
10: {11: return platform_driver_probe(&spi_gpio_driver, spi_gpio_probe);
12: } 13: module_init(spi_gpio_init); 14: 15: static void __exit spi_gpio_exit(void)
16: { 17: platform_driver_unregister(&spi_gpio_driver); 18: } 19: module_exit(spi_gpio_exit); 20: 21: 22: MODULE_DESCRIPTION("SPI master driver using generic bitbanged GPIO ");
23: MODULE_AUTHOR("David Brownell");
24: MODULE_LICENSE("GPL");
三:具体算法分析
1: struct spi_gpio {
2: struct spi_bitbang bitbang; /* gpio 模拟spi算法相关的结构 */
3: struct spi_gpio_platform_data pdata; /* spi platform data 对应模拟spi的四个gpio编号 */
4: struct platform_device *pdev; /* 对应注册的 platform device */
5: };
1: 2: static int __init spi_gpio_probe(struct platform_device *pdev)
3: {4: int status;
5: struct spi_master *master;
6: struct spi_gpio *spi_gpio;
7: struct spi_gpio_platform_data *pdata;
8: u16 master_flags = 0; 9: 10: pdata = pdev->dev.platform_data; /* 存放spi的四根gpio */
11: #ifdef GENERIC_BITBANG12: if (!pdata || !pdata->num_chipselect)
13: return -ENODEV;
14: #endif
15: 16: /* 申请注册四个gpio */
17: status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags);18: if (status < 0) {
19: return status;
20: } 21: 22: /* alloc a spi master ,master->dev->p->driver_data = &master[1]*/
23: master = spi_alloc_master(&pdev->dev, sizeof *spi_gpio);
24: if (!master) {
25: status = -ENOMEM;26: goto gpio_free;
27: }28: /* spi_gpio指向一块空间, 即指向mstaer[1]
29: pdev->dev->p->driver_data = spi_gpio;
30: 初始化spi_gpio
31: */
32: spi_gpio = spi_master_get_devdata(master); 33: platform_set_drvdata(pdev, spi_gpio); 34: 35: spi_gpio->pdev = pdev;36: if (pdata)
37: spi_gpio->pdata = *pdata; 38: 39: master->flags = master_flags; 40: master->bus_num = pdev->id; 41: master->num_chipselect = SPI_N_CHIPSEL;42: master->setup = spi_gpio_setup; /* setup 比如cs引脚申请 */
43: master->cleanup = spi_gpio_cleanup;44: /* spi_gpio->bitbang.master = master */
45: spi_gpio->bitbang.master = spi_master_get(master); 46: spi_gpio->bitbang.chipselect = spi_gpio_chipselect;47: /* spi_gpio->bitbang.txrx_word 数组函数四个元素指针,分别指向spi四种mode算法函数 */
48: if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) {
49: spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0; 50: spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1; 51: spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2; 52: spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3;53: } else {
54: spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0; 55: spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_spec_txrx_word_mode1; 56: spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_spec_txrx_word_mode2; 57: spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3; 58: }59: /* spi_gpio->bitbang.setup_transfer初始化传输的bits_per_word和speed */
60: spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer; 61: spi_gpio->bitbang.flags = SPI_CS_HIGH;62: /* spi_gpio->bitbang相关算法接口初始化 */
63: status = spi_bitbang_start(&spi_gpio->bitbang);64: if (status < 0) {
65: spi_master_put(spi_gpio->bitbang.master); 66: gpio_free:67: if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
68: gpio_free(SPI_MISO_GPIO);69: if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
70: gpio_free(SPI_MOSI_GPIO); 71: gpio_free(SPI_SCK_GPIO); 72: spi_master_put(master); 73: } 74: 75: return status;
76: }四:总之最终让spi_gpi0整个对象存放了整个gpio模拟spi的算法结构;而pdev->dev->p->driver_data = spi_gpio;
platform device和 platform driver两者match结果是:
root@CarRadio:/# ls /sys/bus/platform/devices/spi_gpio.0/
driver modalias power spi0.0 spi_master subsystem uevent
root@CarRadio:/# ls /sys/bus/platform/devices/spi_gpio.0/driver/
spi_gpio.0 uevent

浙公网安备 33010602011771号