.gpio_set_direction = sunxi_pmx_gpio_set_direction,
};
-static int sunxi_pinctrl_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void sunxi_pinctrl_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- pinctrl_free_gpio(chip->base + offset);
-}
-
static int sunxi_pinctrl_gpio_direction_input(struct gpio_chip *chip,
unsigned offset)
{
static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type)
{
struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
- struct irq_desc *desc = container_of(d, struct irq_desc, irq_data);
u32 reg = sunxi_irq_cfg_reg(d->hwirq);
u8 index = sunxi_irq_cfg_offset(d->hwirq);
unsigned long flags;
return -EINVAL;
}
- if (type & IRQ_TYPE_LEVEL_MASK) {
- d->chip = &sunxi_pinctrl_level_irq_chip;
- desc->handle_irq = handle_fasteoi_irq;
- } else {
- d->chip = &sunxi_pinctrl_edge_irq_chip;
- desc->handle_irq = handle_edge_irq;
- }
-
spin_lock_irqsave(&pctl->lock, flags);
+ if (type & IRQ_TYPE_LEVEL_MASK)
+ irq_set_chip_handler_name_locked(d, &sunxi_pinctrl_level_irq_chip,
+ handle_fasteoi_irq, NULL);
+ else
+ irq_set_chip_handler_name_locked(d, &sunxi_pinctrl_edge_irq_chip,
+ handle_edge_irq, NULL);
+
regval = readl(pctl->membase + reg);
regval &= ~(IRQ_CFG_IRQ_MASK << index);
writel(regval | (mode << index), pctl->membase + reg);
}
static struct irq_chip sunxi_pinctrl_edge_irq_chip = {
+ .name = "sunxi_pio_edge",
.irq_ack = sunxi_pinctrl_irq_ack,
.irq_mask = sunxi_pinctrl_irq_mask,
.irq_unmask = sunxi_pinctrl_irq_unmask,
};
static struct irq_chip sunxi_pinctrl_level_irq_chip = {
+ .name = "sunxi_pio_level",
.irq_eoi = sunxi_pinctrl_irq_ack,
.irq_mask = sunxi_pinctrl_irq_mask,
.irq_unmask = sunxi_pinctrl_irq_unmask,
IRQCHIP_EOI_IF_HANDLED,
};
-static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
+static int sunxi_pinctrl_irq_of_xlate(struct irq_domain *d,
+ struct device_node *node,
+ const u32 *intspec,
+ unsigned int intsize,
+ unsigned long *out_hwirq,
+ unsigned int *out_type)
{
- struct irq_chip *chip = irq_get_chip(irq);
- struct sunxi_pinctrl *pctl = irq_get_handler_data(irq);
+ struct sunxi_pinctrl *pctl = d->host_data;
+ struct sunxi_desc_function *desc;
+ int pin, base;
+
+ if (intsize < 3)
+ return -EINVAL;
+
+ base = PINS_PER_BANK * intspec[0];
+ pin = pctl->desc->pin_base + base + intspec[1];
+
+ desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, pin, "irq");
+ if (!desc)
+ return -EINVAL;
+
+ *out_hwirq = desc->irqbank * PINS_PER_BANK + desc->irqnum;
+ *out_type = intspec[2];
+
+ return 0;
+}
+
+static struct irq_domain_ops sunxi_pinctrl_irq_domain_ops = {
+ .xlate = sunxi_pinctrl_irq_of_xlate,
+};
+
+static void sunxi_pinctrl_irq_handler(struct irq_desc *desc)
+{
+ unsigned int irq = irq_desc_get_irq(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct sunxi_pinctrl *pctl = irq_desc_get_handler_data(desc);
unsigned long bank, reg, val;
for (bank = 0; bank < pctl->desc->irq_banks; bank++)
pctl->pctl_dev = pinctrl_register(pctrl_desc,
&pdev->dev, pctl);
- if (!pctl->pctl_dev) {
+ if (IS_ERR(pctl->pctl_dev)) {
dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
- return -EINVAL;
+ return PTR_ERR(pctl->pctl_dev);
}
pctl->chip = devm_kzalloc(&pdev->dev, sizeof(*pctl->chip), GFP_KERNEL);
last_pin = pctl->desc->pins[pctl->desc->npins - 1].pin.number;
pctl->chip->owner = THIS_MODULE;
- pctl->chip->request = sunxi_pinctrl_gpio_request,
- pctl->chip->free = sunxi_pinctrl_gpio_free,
+ pctl->chip->request = gpiochip_generic_request,
+ pctl->chip->free = gpiochip_generic_free,
pctl->chip->direction_input = sunxi_pinctrl_gpio_direction_input,
pctl->chip->direction_output = sunxi_pinctrl_gpio_direction_output,
pctl->chip->get = sunxi_pinctrl_gpio_get,
pctl->domain = irq_domain_add_linear(node,
pctl->desc->irq_banks * IRQ_PER_BANK,
- &irq_domain_simple_ops,
- NULL);
+ &sunxi_pinctrl_irq_domain_ops,
+ pctl);
if (!pctl->domain) {
dev_err(&pdev->dev, "Couldn't register IRQ domain\n");
ret = -ENOMEM;
irq_set_chip_and_handler(irqno, &sunxi_pinctrl_edge_irq_chip,
handle_edge_irq);
irq_set_chip_data(irqno, pctl);
- };
+ }
for (i = 0; i < pctl->desc->irq_banks; i++) {
/* Mask and clear all IRQs before registering a handler */
writel(0xffffffff,
pctl->membase + sunxi_irq_status_reg_from_bank(i));
- irq_set_chained_handler(pctl->irq[i],
- sunxi_pinctrl_irq_handler);
- irq_set_handler_data(pctl->irq[i], pctl);
+ irq_set_chained_handler_and_data(pctl->irq[i],
+ sunxi_pinctrl_irq_handler,
+ pctl);
}
dev_info(&pdev->dev, "initialized sunXi PIO driver\n");