LZ你好!我今天也在看全志A20 的gpio驱动。
【linux-3.4-cb2】
目录: driver/gpio/gpio-sunxi.c
------------------------
在这个驱动中,我看它使用的是platform平台设备相关编程。
-------------------------
由于是新手,其中有个疑点,还希望LZ能帮忙解答下。
--------------------------
首先,贴下代码:- static int __init sunxi_gpio_init(void)
- {
- int err = 0;
- err = platform_device_register(&sunxi_gpio_device);
- if (err)
- goto exit;
- return platform_driver_register(&sunxi_gpio_driver);
- exit:
- return err;
- }
- subsys_initcall(sunxi_gpio_init);
复制代码 ------------------------- static int __devinit sunxi_gpio_probe(struct platform_device *pdev)
- {
- int i;
- int err = 0;
- int names_size = 0;
- int gpio_used = 0;
- int gpio_num = 0;
- struct sunxi_gpio_data *gpio_i = NULL;
- struct sunxi_gpio_data *gpio_data = NULL;
- struct sunxi_gpio_chip *sunxi_chip = NULL;
- char **pnames = NULL;
- /* parse script.bin for [gpio_para] section
- gpio_used/gpio_num/gpio_pin_x */
- pr_info("sunxi_gpio driver init ver %s\n", SUNXI_GPIO_VER);
-
- err = script_parser_fetch("gpio_para", "gpio_used", &gpio_used,
- sizeof(gpio_used)/sizeof(int));
- if (err) {
- /* Not error - just info */
- pr_info("%s can't find script.bin '[gpio_para]' 'gpio_used'\n",
- __func__);
- return err;
- }
- if (!gpio_used) {
- pr_info("%s gpio_used is false. Skip gpio initialization\n",
- __func__);
- err = 0;
- return err;
- }
- err = script_parser_fetch("gpio_para", "gpio_num", &gpio_num,
- sizeof(gpio_num)/sizeof(int));
- if (err) {
- pr_err("%s script_parser_fetch '[gpio_para]' 'gpio_num' err\n",
- __func__);
- return err;
- }
- if (!gpio_num) {
- pr_info("%s gpio_num is none. Skip gpio initialization\n",
- __func__);
- err = 0;
- return err;
- }
-
- /* Allocate memory for sunxi_gpio_chip + data/names array */
- sunxi_chip = kzalloc(sizeof(struct sunxi_gpio_chip) +
- sizeof(struct sunxi_gpio_data) * gpio_num,
- GFP_KERNEL);
-
- gpio_data = (void *)sunxi_chip + sizeof(struct sunxi_gpio_chip);
-
- /* Allocate memory for variable array of fixed size strings */
- /* in one chunk. This is to avoid 1+gpio_num kzalloc calls */
- names_size = sizeof(*pnames) * gpio_num +
- sizeof(char) * MAX_GPIO_NAMELEN * gpio_num;
- pnames = kzalloc(names_size, GFP_KERNEL);
-
- for (i = 0; i < gpio_num; i++) {
- pnames[i] = (void *)pnames + sizeof(*pnames) * gpio_num +
- i * MAX_GPIO_NAMELEN;
- }
- if ((!pnames) || (!sunxi_chip)) {
- pr_err("%s kzalloc failed\n", __func__);
- err = -ENOMEM;
- goto exit;
- }
- /* Parse gpio_para/pin script data */
- gpio_i = gpio_data;
-
- for (i = 0; i < gpio_num; i++) {
- sprintf(gpio_i->pin_name, "gpio_pin_%d", i+1);
- err = script_parser_fetch("gpio_para", gpio_i->pin_name,
- (int *)&gpio_i->info,
- sizeof(script_gpio_set_t));
- if (err) {
- pr_err("%s script_parser_fetch '[gpio_para]' '%s' err\n",
- __func__, gpio_i->pin_name);
- break;
- }
- gpio_i++;
- }
-
- /* i/o的物理地址映射到核心虚拟地址空间内 */
- sunxi_chip->gaddr = ioremap(PIO_BASE_ADDRESS, PIO_RANGE_SIZE);
-
- if (!sunxi_chip->gaddr) {
- pr_err("Can't request gpio registers memory\n");
- err = -EIO;
- goto unmap;
- }
- sunxi_chip->dev = &pdev->dev;
- sunxi_chip->data = gpio_data;
- sunxi_chip->chip = template_chip;
- sunxi_chip->chip.ngpio = gpio_num;
- sunxi_chip->chip.dev = &pdev->dev;
- sunxi_chip->chip.label = "A1X_GPIO";
- sunxi_chip->chip.base = 1;
- sunxi_chip->chip.names = (const char *const *)pnames;
- sunxi_chip->irq_base = -1;
- /* configure EINTs for the detected SoC */
- sunxi_gpio_eint_probe();
- /* This needs additional system irq numbers (NR_IRQ=NR_IRQ+EINT_NUM) */
- if (EINT_NUM > 0) {
- sunxi_chip->irq_base = irq_alloc_descs(-1, 0, EINT_NUM, 0);
- if (sunxi_chip->irq_base < 0) {
- pr_err("Couldn't allocate virq numbers. GPIO irq support disabled\n");
- err = sunxi_chip->irq_base;
- }
- } else
- pr_info("GPIO irq support disabled in this platform\n");
- /*自旋锁初始化*/
- spin_lock_init(&sunxi_chip->irq_lock);
- /*irq init*/
- sunxi_gpio_irq_init(sunxi_chip);
- /*request irq*/
- if (sunxi_chip->irq_base >= 0) {
- err = request_irq(GPIO_IRQ_NO, sunxi_gpio_irq_handler,
- IRQF_SHARED, "sunxi-gpio", sunxi_chip);
- if (err) {
- pr_err("Can't request irq %d\n", GPIO_IRQ_NO);
- goto irqchip;
- }
- }
- /* register a gpio_chip*/
- err = gpiochip_add(&sunxi_chip->chip);
- if (err < 0)
- goto irqhdl;
- /*save gpio private data,we cat get these data like this : platform_get_drvdata()*/
- platform_set_drvdata(pdev, sunxi_chip);
- return 0;
- irqhdl:
- if (sunxi_chip->irq_base >= 0)
- free_irq(GPIO_IRQ_NO, sunxi_chip);
- irqchip:
- sunxi_gpio_irq_remove(sunxi_chip);
- if (sunxi_chip->irq_base >= 0)
- irq_free_descs(sunxi_chip->irq_base, EINT_NUM);
- unmap:
- iounmap(sunxi_chip->gaddr);
- exit:
- kfree(sunxi_chip);
- kfree(pnames);
- return err;
- }
复制代码 在这里,我只是追到了一些资源的申请和注册,在 /sys/class/gpio-sw/ 目录下可以使用open() wrte() read() ioctl() 这些函数来读取和操作GPIO的数据,但是,我在该驱动中并没发现这些函数的底层实现,这是个什么缘由呢?
谢谢! |