#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);
static int __init gpio_pmodoled_driver_init(void){return platform_driver_register(&gpio_pmodoled_driver);}module_init(gpio_pmodoled_driver_init);static void __exit gpio_pmodoled_driver_init(void){return platform_driver_unregister(&gpio_pmodoled_driver);}module_exit(gpio_pmodoled_driver_exit);
static struct platform_driver gpio_pmodoled_driver = {.driver = {.name = DRIVER_NAME,.owner = THIS_MODULE,.of_match_table = gpio_pmodoled_of_match,},.probe = gpio_pmodoled_of_probe,.remove = __devexit_p(gpio_pmodoled_of_remove),};
static const struct of_device_id gpio_pmodoled_of_match[] __devinitconst = {{ .compatible = "dglnt,pmodoled-gpio", },{},};MODULE_DEVICE_TABLE(of, gpio_pmodoled_of_match);
zed_oled {compatible = "dglnt,pmodoled-gpio";/* GPIO Pins */vbat-gpio = <&gpiops 55 0>;vdd-gpio = <&gpiops 56 0>;res-gpio = <&gpiops 57 0>;dc-gpio = <&gpiops 58 0>;/* SPI-GPIOs */spi-bus-num = <2>;spi-speed-hz = <4000000>;spi-sclk-gpio = <&gpiops 59 0>;spi-sdin-gpio = <&gpiops 60 0>;};
static int platform_match(struct device *dev, struct device_driver *drv){struct platform_device *pdev = to_platform_device(dev);struct platform_driver *pdrv = to_platform_driver(drv);/* Attempt an OF style match first */if (of_driver_match_device(dev, drv))return 1;/* Then try to match against the id table */if (pdrv->id_table)return platform_match_id(pdrv->id_table, pdev) != NULL;/* fall-back to driver name match */return (strcmp(pdev->name, drv->name) == 0);}
/* Alloc Space for platform device structure */gpio_pmodoled_dev = (struct gpio_pmodoled_device *) kzalloc(sizeof(*gpio_pmodoled_dev), GFP_KERNEL);/* Alloc Graphic Buffer for device */gpio_pmodoled_dev->disp_buf = (uint8_t *) kmalloc(DISPLAY_BUF_SZ, GFP_KERNEL);/* Get the GPIO Pins */gpio_pmodoled_dev->iVBAT = of_get_named_gpio(np, "vbat-gpio", 0);gpio_pmodoled_dev->iVDD = of_get_named_gpio(np, "vdd-gpio", 0);gpio_pmodoled_dev->iRES = of_get_named_gpio(np, "res-gpio", 0);gpio_pmodoled_dev->iDC = of_get_named_gpio(np, "dc-gpio", 0);gpio_pmodoled_dev->iSCLK = of_get_named_gpio(np, "spi-sclk-gpio", 0);gpio_pmodoled_dev->iSDIN = of_get_named_gpio(np, "spi-sdin-gpio", 0);status = of_get_named_gpio(np, "spi-cs-gpio", 0);gpio_pmodoled_dev->iCS = (status < 0) ? SPI_GPIO_NO_CHIPSELECT : status;
/* Get SPI Related Params */tree_info = of_get_property(np, "spi-bus-num", NULL);if (tree_info) {gpio_pmodoled_dev->spi_id = be32_to_cpup((tree_info));}
/* Alloc Space for platform data structure */gpio_pmodoled_pdata = (struct spi_gpio_platform_data *) kzalloc(sizeof(*gpio_pmodoled_pdata), GFP_KERNEL);/* Fill up Platform Data Structure */gpio_pmodoled_pdata->sck = gpio_pmodoled_dev->iSCLK;gpio_pmodoled_pdata->miso = SPI_GPIO_NO_MISO;gpio_pmodoled_pdata->mosi = gpio_pmodoled_dev->iSDIN;gpio_pmodoled_pdata->num_chipselect = 1;
/* Alloc Space for platform data structure */gpio_pmodoled_pdev = (struct platform_device *) kzalloc(sizeof(*gpio_pmodoled_pdev), GFP_KERNEL);/* Fill up Platform Device Structure */gpio_pmodoled_pdev->name = "spi_gpio";gpio_pmodoled_pdev->id = gpio_pmodoled_dev->spi_id;gpio_pmodoled_pdev->dev.platform_data = gpio_pmodoled_pdata;gpio_pmodoled_dev->pdev = gpio_pmodoled_pdev;
static struct platform_driver spi_gpio_driver = {.driver.name = DRIVER_NAME,.driver.owner = THIS_MODULE,.probe = spi_gpio_probe,.remove = __devexit_p(spi_gpio_remove),};module_platform_driver(spi_gpio_driver);
/* Register spi_gpio master */status = platform_device_register(gpio_pmodoled_dev->pdev);gpio_pmodoled_dev->name = np->name;/* Fill up Board Info for SPI device */status = add_gpio_pmodoled_device_to_bus(gpio_pmodoled_dev);
spi_master = spi_busnum_to_master(dev->spi_id);
spi_device = spi_alloc_device(spi_master);
spi_device->chip_select = 0;spi_device->max_speed_hz = 4000000;spi_device->mode = SPI_MODE_0;spi_device->bits_per_word = 8;spi_device->controller_data = (void *) dev->iCS;spi_device->dev.platform_data = dev;strlcpy(spi_device->modalias, SPI_DRIVER_NAME, sizeof(SPI_DRIVER_NAME));
status = spi_add_device(spi_device);
将设备注册内核。dev->spi = spi_device;put_device(&spi_master->dev);spi_master用完了以后即使释放掉。到这里函数运行完毕,返回gpio_pmodoled_of_probe。if (gpio_pmodoled_dev_id == 0) {/* Alloc Major & Minor number for char device */status = alloc_chrdev_region(&gpio_pmodoled_dev_id, 0, MAX_PMODOLED_GPIO_DEV_NUM, DRIVER_NAME);}申请字符设备号if (gpio_pmodoled_class == NULL) {/* Create Pmodoled-gpio Device Class */gpio_pmodoled_class = class_create(THIS_MODULE, DRIVER_NAME);}在sysfs中创建class入口if (spi_drv_registered == 0) {/* Register SPI Driver for Pmodoled Device */status = spi_register_driver(&gpio_pmodoled_spi_driver);spi_drv_registered = 1;}
这里红色加粗字体是关键,之前讲到我们新注册了一个spi_device设备,与这个设备匹配的驱动正是这里注册的gpio_pmodoled_spi_driver,定义如下:
static struct spi_driver gpio_pmodoled_spi_driver = {.driver = {.name = SPI_DRIVER_NAME,.bus = &spi_bus_type,.owner = THIS_MODULE,},.probe = gpio_pmodoled_spi_probe,.remove = __devexit_p(gpio_pmodoled_spi_remove),};
static int spi_match_device(struct device *dev, struct device_driver *drv){const struct spi_device *spi = to_spi_device(dev);const struct spi_driver *sdrv = to_spi_driver(drv);/* Attempt an OF style match */if (of_driver_match_device(dev, drv))return 1;if (sdrv->id_table)return !!spi_match_id(sdrv->id_table, spi);return strcmp(spi->modalias, drv->name) == 0;}
strlcpy(spi_device->modalias, SPI_DRIVER_NAME, sizeof(SPI_DRIVER_NAME));
/* We must use SPI_MODE_0 */spi->mode = SPI_MODE_0;spi->bits_per_word = 8;status = spi_setup(spi);设置spi的工作模式。/* Get gpio_pmodoled_device structure */gpio_pmodoled_dev = (struct gpio_pmodoled_device *) spi->dev.platform_data;/* Setup char driver */status = gpio_pmodoled_setup_cdev(gpio_pmodoled_dev, &(gpio_pmodoled_dev->dev_id), spi);在这个函数里就是进行字符驱动的设置,找了好久才找到啊,真心不容易啊,代码如下,这里就不介绍了:cdev_init(&dev->cdev, &gpio_pmodoled_cdev_fops);dev->cdev.owner = THIS_MODULE;dev->cdev.ops = &gpio_pmodoled_cdev_fops;dev->spi = spi;*dev_id = MKDEV(MAJOR(gpio_pmodoled_dev_id), cur_minor++);status = cdev_add(&dev->cdev, *dev_id, 1);/* Add Device node in system */device = device_create(gpio_pmodoled_class, NULL,*dev_id, NULL,"%s", dev->name);/* Initialize Mutex */mutex_init(&gpio_pmodoled_dev->mutex);status = gpio_pmodoled_init_gpio(gpio_pmodoled_dev);
gpio_pmodoled_disp_init(gpio_pmodoled_dev);这里面也用到了很多gpiolib中的函数以及spi的内核函数,涉及的内容比较多,大家有兴趣的话自己googlememset(gpio_pmodoled_dev->disp_buf, 0x00, DISPLAY_BUF_SZ);status = screen_buf_to_display(gpio_pmodoled_dev->disp_buf, gpio_pmodoled_dev);这里面也用到了很多gpiolib中的函数以及spi的内核函数,涉及的内容比较多,大家有兴趣的话自己google
struct file_operations gpio_pmodoled_cdev_fops = {.owner = THIS_MODULE,.write = gpio_pmodoled_write,.read = gpio_pmodoled_read,.open = gpio_pmodoled_open,.release = gpio_pmodoled_close,};
联系客服