in gpio-ixp4xx.c [189:302]
static int ixp4xx_gpio_probe(struct platform_device *pdev)
{
unsigned long flags;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct irq_domain *parent;
struct resource *res;
struct ixp4xx_gpio *g;
struct gpio_irq_chip *girq;
int ret;
g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL);
if (!g)
return -ENOMEM;
g->dev = dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
g->base = devm_ioremap_resource(dev, res);
if (IS_ERR(g->base))
return PTR_ERR(g->base);
/*
* When we convert to device tree we will simply look up the
* parent irqdomain using irq_find_host(parent) as parent comes
* from IRQCHIP_DECLARE(), then use of_node_to_fwnode() to get
* the fwnode. For now we need this boardfile style code.
*/
if (np) {
struct device_node *irq_parent;
irq_parent = of_irq_find_parent(np);
if (!irq_parent) {
dev_err(dev, "no IRQ parent node\n");
return -ENODEV;
}
parent = irq_find_host(irq_parent);
if (!parent) {
dev_err(dev, "no IRQ parent domain\n");
return -ENODEV;
}
g->fwnode = of_node_to_fwnode(np);
} else {
parent = ixp4xx_get_irq_domain();
g->fwnode = irq_domain_alloc_fwnode(&res->start);
if (!g->fwnode) {
dev_err(dev, "no domain base\n");
return -ENODEV;
}
}
/*
* Make sure GPIO 14 and 15 are NOT used as clocks but GPIO on
* specific machines.
*/
if (machine_is_dsmg600() || machine_is_nas100d())
__raw_writel(0x0, g->base + IXP4XX_REG_GPCLK);
/*
* This is a very special big-endian ARM issue: when the IXP4xx is
* run in big endian mode, all registers in the machine are switched
* around to the CPU-native endianness. As you see mostly in the
* driver we use __raw_readl()/__raw_writel() to access the registers
* in the appropriate order. With the GPIO library we need to specify
* byte order explicitly, so this flag needs to be set when compiling
* for big endian.
*/
#if defined(CONFIG_CPU_BIG_ENDIAN)
flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;
#else
flags = 0;
#endif
/* Populate and register gpio chip */
ret = bgpio_init(&g->gc, dev, 4,
g->base + IXP4XX_REG_GPIN,
g->base + IXP4XX_REG_GPOUT,
NULL,
NULL,
g->base + IXP4XX_REG_GPOE,
flags);
if (ret) {
dev_err(dev, "unable to init generic GPIO\n");
return ret;
}
g->gc.ngpio = 16;
g->gc.label = "IXP4XX_GPIO_CHIP";
/*
* TODO: when we have migrated to device tree and all GPIOs
* are fetched using phandles, set this to -1 to get rid of
* the fixed gpiochip base.
*/
g->gc.base = 0;
g->gc.parent = &pdev->dev;
g->gc.owner = THIS_MODULE;
girq = &g->gc.irq;
girq->chip = &ixp4xx_gpio_irqchip;
girq->fwnode = g->fwnode;
girq->parent_domain = parent;
girq->child_to_parent_hwirq = ixp4xx_gpio_child_to_parent_hwirq;
girq->handler = handle_bad_irq;
girq->default_type = IRQ_TYPE_NONE;
ret = devm_gpiochip_add_data(dev, &g->gc, g);
if (ret) {
dev_err(dev, "failed to add SoC gpiochip\n");
return ret;
}
platform_set_drvdata(pdev, g);
dev_info(dev, "IXP4 GPIO registered\n");
return 0;
}