今天写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与安卓论坛
一周热门 更多>