diff options
Diffstat (limited to 'drivers/pinctrl/sunxi')
-rw-r--r-- | drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c | 17 | ||||
-rw-r--r-- | drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c | 2 | ||||
-rw-r--r-- | drivers/pinctrl/sunxi/pinctrl-sunxi.c | 60 |
3 files changed, 61 insertions, 18 deletions
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c b/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c index 7376a97b5..862a096c5 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c @@ -135,7 +135,14 @@ static const struct sunxi_desc_pin sun4i_a10_pins[] = { SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3), SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x1, "gpio_out"), - SUNXI_FUNCTION(0x2, "ir0")), /* TX */ + SUNXI_FUNCTION(0x2, "ir0"), /* TX */ + /* + * The SPDIF block is not referenced at all in the A10 user + * manual. However it is described in the code leaked and the + * pin descriptions are declared in the A20 user manual which + * is pin compatible with this device. + */ + SUNXI_FUNCTION(0x4, "spdif")), /* SPDIF MCLK */ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4), SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x1, "gpio_out"), @@ -176,11 +183,15 @@ static const struct sunxi_desc_pin sun4i_a10_pins[] = { SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x1, "gpio_out"), SUNXI_FUNCTION(0x2, "i2s"), /* DI */ - SUNXI_FUNCTION(0x3, "ac97")), /* DI */ + SUNXI_FUNCTION(0x3, "ac97"), /* DI */ + /* Undocumented mux function - See SPDIF MCLK above */ + SUNXI_FUNCTION(0x4, "spdif")), /* SPDIF IN */ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 13), SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x1, "gpio_out"), - SUNXI_FUNCTION(0x2, "spi2")), /* CS1 */ + SUNXI_FUNCTION(0x2, "spi2"), /* CS1 */ + /* Undocumented mux function - See SPDIF MCLK above */ + SUNXI_FUNCTION(0x4, "spdif")), /* SPDIF OUT */ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 14), SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x1, "gpio_out"), diff --git a/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c b/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c index 63676617b..f9a3f8f44 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c @@ -653,7 +653,7 @@ static const struct sunxi_desc_pin sun5i_a10s_pins[] = { SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x1, "gpio_out"), SUNXI_FUNCTION(0x2, "spi1"), /* CS1 */ - SUNXI_FUNCTION(0x3, "uart3"), /* PWM1 */ + SUNXI_FUNCTION(0x3, "pwm"), /* PWM1 */ SUNXI_FUNCTION(0x5, "uart2"), /* CTS */ SUNXI_FUNCTION_IRQ(0x6, 13)), /* EINT13 */ }; diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index f09573e13..38e0c7bdd 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -588,7 +588,6 @@ static void sunxi_pinctrl_irq_release_resources(struct irq_data *d) 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; @@ -615,16 +614,15 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type) 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); @@ -685,6 +683,7 @@ static void sunxi_pinctrl_irq_ack_unmask(struct irq_data *d) } 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, @@ -695,6 +694,7 @@ static struct irq_chip sunxi_pinctrl_edge_irq_chip = { }; 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, @@ -709,10 +709,42 @@ static struct irq_chip sunxi_pinctrl_level_irq_chip = { 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 sunxi_desc_function *desc; + int pin, base; + + if (intsize < 3) + return -EINVAL; + + base = PINS_PER_BANK * intspec[0]; + pin = base + intspec[1]; + + desc = sunxi_pinctrl_desc_find_function_by_pin(d->host_data, + 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) { - struct irq_chip *chip = irq_get_chip(irq); - struct sunxi_pinctrl *pctl = irq_get_handler_data(irq); + 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++) @@ -983,8 +1015,8 @@ int sunxi_pinctrl_init(struct platform_device *pdev, 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; |