linux驱动入门

2019-03-26 12:24发布

今天写AM3352的GPIO驱动,那个probe函数不知道怎么写,看了linux的GPIO源码,不知道每个操作都有什么作用,求指教啊!static int omap_gpio_probe(struct platform_device *pdev)

{
        struct device *dev = &pdev->dev;
        struct device_node *node = dev->of_node;
        const struct of_device_id *match;
        const struct omap_gpio_platform_data *pdata;
        struct resource *res;
        struct gpio_bank *bank;
        struct irq_chip *irqc;
#ifdef CONFIG_ARCH_OMAP1
        int irq_base;
#endif

        match = of_match_device(of_match_ptr(omap_gpio_match), dev);

        pdata = match ? match->data : dev_get_platdata(dev);
        if (!pdata)
                return -EINVAL;

        bank = devm_kzalloc(dev, sizeof(struct gpio_bank), GFP_KERNEL);
        if (!bank) {
                dev_err(dev, "Memory alloc failed ");
                return -ENOMEM;
        }

        irqc = devm_kzalloc(dev, sizeof(*irqc), GFP_KERNEL);
        if (!irqc)
                return -ENOMEM;

        irqc->irq_shutdown = gpio_irq_shutdown,
        irqc->irq_ack = gpio_ack_irq,
        irqc->irq_mask = gpio_mask_irq,
        irqc->irq_unmask = gpio_unmask_irq,
        irqc->irq_set_type = gpio_irq_type,
        irqc->irq_set_wake = gpio_wake_enable,
        irqc->name = dev_name(&pdev->dev);

        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (unlikely(!res)) {
                dev_err(dev, "Invalid IRQ resource ");
                return -ENODEV;
        }

        bank->irq = res->start;
        bank->dev = dev;
        bank->dbck_flag = pdata->dbck_flag;
        bank->stride = pdata->bank_stride;
        bank->width = pdata->bank_width;
        bank->is_mpuio = pdata->is_mpuio;
        bank->non_wakeup_gpios = pdata->non_wakeup_gpios;
        bank->regs = pdata->regs;
#ifdef CONFIG_OF_GPIO
        bank->chip.of_node = of_node_get(node);
#endif
        if (!node) {
                bank->get_context_loss_count =
                        pdata->get_context_loss_count;
        }

#ifdef CONFIG_ARCH_OMAP1
        /*
         * REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop
         * irq_alloc_descs() and irq_domain_add_legacy() and just use a
         * linear IRQ domain mapping for all OMAP platforms.
         */
        irq_base = irq_alloc_descs(-1, 0, bank->width, 0);
        if (irq_base < 0) {
                dev_err(dev, "Couldn't allocate IRQ numbers ");
                return -ENODEV;
        }

        bank->domain = irq_domain_add_legacy(node, bank->width, irq_base,
                                             0, &irq_domain_simple_ops, NULL);
#else
        bank->domain = irq_domain_add_linear(node, bank->width,
                                             &irq_domain_simple_ops, NULL);
#endif
        if (!bank->domain) {
                dev_err(dev, "Couldn't register an IRQ domain ");
                return -ENODEV;
        }

        if (bank->regs->set_dataout && bank->regs->clr_dataout)
                bank->set_dataout = _set_gpio_dataout_reg;
        else
                bank->set_dataout = _set_gpio_dataout_mask;

        spin_lock_init(&bank->lock);

        /* Static mapping, never released */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (unlikely(!res)) {
                dev_err(dev, "Invalid mem resource ");
                irq_domain_remove(bank->domain);
                return -ENODEV;
        }

        if (!devm_request_mem_region(dev, res->start, resource_size(res),
                                     pdev->name)) {
                dev_err(dev, "Region already claimed ");
                irq_domain_remove(bank->domain);
                return -EBUSY;
        }

        bank->base = devm_ioremap(dev, res->start, resource_size(res));
        if (!bank->base) {
                dev_err(dev, "Could not ioremap ");
                irq_domain_remove(bank->domain);
                return -ENOMEM;
        }

        platform_set_drvdata(pdev, bank);

        pm_runtime_enable(bank->dev);
        pm_runtime_irq_safe(bank->dev);
        pm_runtime_get_sync(bank->dev);

        if (bank->is_mpuio)
                mpuio_init(bank);

        omap_gpio_mod_init(bank);
        omap_gpio_chip_init(bank, irqc);
        omap_gpio_show_rev(bank);

        pm_runtime_put(bank->dev);

        list_add_tail(&bank->node, &omap_gpio_list);

        return 0;
}


此帖出自Linux与安卓论坛
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。