aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@free-electrons.com>2013-06-08 06:05:44 -0400
committerLinus Walleij <linus.walleij@linaro.org>2013-06-16 05:57:31 -0400
commit60242db1a7292cc63ae390f12ec9d62e9e2f6935 (patch)
treee563fde69b9b305469d92fbce919ff3c96adfa73 /drivers/pinctrl
parent814d4f2e153dfb337ee894d1f23863e623add4ab (diff)
pinctrl: sunxi: Add external interrupts support
The port controller IP found in the Allwinner A10 and A13 can use few of the pins it manage as an interrupt source, called external interrupts in the datasheet. The number of these external interrupts are SoCs specific, but the current upper limit is 32. In order to work, the external interrupts' pins have to be muxed to a specific function to generate an interrupt. This patch adds the irqchip and the needed logic to use the PIO controller as an interrupt controller. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/pinctrl-sunxi.c155
-rw-r--r--drivers/pinctrl/pinctrl-sunxi.h68
2 files changed, 223 insertions, 0 deletions
diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c
index f4a74f1c0bfd..e2bab0f75fc5 100644
--- a/drivers/pinctrl/pinctrl-sunxi.c
+++ b/drivers/pinctrl/pinctrl-sunxi.c
@@ -13,10 +13,12 @@
13#include <linux/io.h> 13#include <linux/io.h>
14#include <linux/clk.h> 14#include <linux/clk.h>
15#include <linux/gpio.h> 15#include <linux/gpio.h>
16#include <linux/irqdomain.h>
16#include <linux/module.h> 17#include <linux/module.h>
17#include <linux/of.h> 18#include <linux/of.h>
18#include <linux/of_address.h> 19#include <linux/of_address.h>
19#include <linux/of_device.h> 20#include <linux/of_device.h>
21#include <linux/of_irq.h>
20#include <linux/pinctrl/consumer.h> 22#include <linux/pinctrl/consumer.h>
21#include <linux/pinctrl/machine.h> 23#include <linux/pinctrl/machine.h>
22#include <linux/pinctrl/pinctrl.h> 24#include <linux/pinctrl/pinctrl.h>
@@ -1796,6 +1798,26 @@ static int sunxi_pinctrl_gpio_of_xlate(struct gpio_chip *gc,
1796 return pin; 1798 return pin;
1797} 1799}
1798 1800
1801static int sunxi_pinctrl_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
1802{
1803 struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev);
1804 struct sunxi_desc_function *desc;
1805
1806 if (offset > chip->ngpio)
1807 return -ENXIO;
1808
1809 desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, offset, "irq");
1810 if (!desc)
1811 return -EINVAL;
1812
1813 pctl->irq_array[desc->irqnum] = offset;
1814
1815 dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n",
1816 chip->label, offset + chip->base, desc->irqnum);
1817
1818 return irq_find_mapping(pctl->domain, desc->irqnum);
1819}
1820
1799static struct gpio_chip sunxi_pinctrl_gpio_chip = { 1821static struct gpio_chip sunxi_pinctrl_gpio_chip = {
1800 .owner = THIS_MODULE, 1822 .owner = THIS_MODULE,
1801 .request = sunxi_pinctrl_gpio_request, 1823 .request = sunxi_pinctrl_gpio_request,
@@ -1805,10 +1827,118 @@ static struct gpio_chip sunxi_pinctrl_gpio_chip = {
1805 .get = sunxi_pinctrl_gpio_get, 1827 .get = sunxi_pinctrl_gpio_get,
1806 .set = sunxi_pinctrl_gpio_set, 1828 .set = sunxi_pinctrl_gpio_set,
1807 .of_xlate = sunxi_pinctrl_gpio_of_xlate, 1829 .of_xlate = sunxi_pinctrl_gpio_of_xlate,
1830 .to_irq = sunxi_pinctrl_gpio_to_irq,
1808 .of_gpio_n_cells = 3, 1831 .of_gpio_n_cells = 3,
1809 .can_sleep = 0, 1832 .can_sleep = 0,
1810}; 1833};
1811 1834
1835static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
1836 unsigned int type)
1837{
1838 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
1839 u32 reg = sunxi_irq_cfg_reg(d->hwirq);
1840 u8 index = sunxi_irq_cfg_offset(d->hwirq);
1841 u8 mode;
1842
1843 switch (type) {
1844 case IRQ_TYPE_EDGE_RISING:
1845 mode = IRQ_EDGE_RISING;
1846 break;
1847 case IRQ_TYPE_EDGE_FALLING:
1848 mode = IRQ_EDGE_FALLING;
1849 break;
1850 case IRQ_TYPE_EDGE_BOTH:
1851 mode = IRQ_EDGE_BOTH;
1852 break;
1853 case IRQ_TYPE_LEVEL_HIGH:
1854 mode = IRQ_LEVEL_HIGH;
1855 break;
1856 case IRQ_TYPE_LEVEL_LOW:
1857 mode = IRQ_LEVEL_LOW;
1858 break;
1859 default:
1860 return -EINVAL;
1861 }
1862
1863 writel((mode & IRQ_CFG_IRQ_MASK) << index, pctl->membase + reg);
1864
1865 return 0;
1866}
1867
1868static void sunxi_pinctrl_irq_mask_ack(struct irq_data *d)
1869{
1870 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
1871 u32 ctrl_reg = sunxi_irq_ctrl_reg(d->hwirq);
1872 u8 ctrl_idx = sunxi_irq_ctrl_offset(d->hwirq);
1873 u32 status_reg = sunxi_irq_status_reg(d->hwirq);
1874 u8 status_idx = sunxi_irq_status_offset(d->hwirq);
1875 u32 val;
1876
1877 /* Mask the IRQ */
1878 val = readl(pctl->membase + ctrl_reg);
1879 writel(val & ~(1 << ctrl_idx), pctl->membase + ctrl_reg);
1880
1881 /* Clear the IRQ */
1882 writel(1 << status_idx, pctl->membase + status_reg);
1883}
1884
1885static void sunxi_pinctrl_irq_mask(struct irq_data *d)
1886{
1887 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
1888 u32 reg = sunxi_irq_ctrl_reg(d->hwirq);
1889 u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
1890 u32 val;
1891
1892 /* Mask the IRQ */
1893 val = readl(pctl->membase + reg);
1894 writel(val & ~(1 << idx), pctl->membase + reg);
1895}
1896
1897static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
1898{
1899 struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
1900 struct sunxi_desc_function *func;
1901 u32 reg = sunxi_irq_ctrl_reg(d->hwirq);
1902 u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
1903 u32 val;
1904
1905 func = sunxi_pinctrl_desc_find_function_by_pin(pctl,
1906 pctl->irq_array[d->hwirq],
1907 "irq");
1908
1909 /* Change muxing to INT mode */
1910 sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq], func->muxval);
1911
1912 /* Unmask the IRQ */
1913 val = readl(pctl->membase + reg);
1914 writel(val | (1 << idx), pctl->membase + reg);
1915}
1916
1917static struct irq_chip sunxi_pinctrl_irq_chip = {
1918 .irq_mask = sunxi_pinctrl_irq_mask,
1919 .irq_mask_ack = sunxi_pinctrl_irq_mask_ack,
1920 .irq_unmask = sunxi_pinctrl_irq_unmask,
1921 .irq_set_type = sunxi_pinctrl_irq_set_type,
1922};
1923
1924static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
1925{
1926 struct sunxi_pinctrl *pctl = irq_get_handler_data(irq);
1927 const unsigned long reg = readl(pctl->membase + IRQ_STATUS_REG);
1928
1929 /* Clear all interrupts */
1930 writel(reg, pctl->membase + IRQ_STATUS_REG);
1931
1932 if (reg) {
1933 int irqoffset;
1934
1935 for_each_set_bit(irqoffset, &reg, SUNXI_IRQ_NUMBER) {
1936 int pin_irq = irq_find_mapping(pctl->domain, irqoffset);
1937 generic_handle_irq(pin_irq);
1938 }
1939 }
1940}
1941
1812static struct of_device_id sunxi_pinctrl_match[] = { 1942static struct of_device_id sunxi_pinctrl_match[] = {
1813 { .compatible = "allwinner,sun4i-a10-pinctrl", .data = (void *)&sun4i_a10_pinctrl_data }, 1943 { .compatible = "allwinner,sun4i-a10-pinctrl", .data = (void *)&sun4i_a10_pinctrl_data },
1814 { .compatible = "allwinner,sun5i-a13-pinctrl", .data = (void *)&sun5i_a13_pinctrl_data }, 1944 { .compatible = "allwinner,sun5i-a13-pinctrl", .data = (void *)&sun5i_a13_pinctrl_data },
@@ -2005,6 +2135,31 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev)
2005 2135
2006 clk_prepare_enable(clk); 2136 clk_prepare_enable(clk);
2007 2137
2138 pctl->irq = irq_of_parse_and_map(node, 0);
2139 if (!pctl->irq) {
2140 ret = -EINVAL;
2141 goto gpiochip_error;
2142 }
2143
2144 pctl->domain = irq_domain_add_linear(node, SUNXI_IRQ_NUMBER,
2145 &irq_domain_simple_ops, NULL);
2146 if (!pctl->domain) {
2147 dev_err(&pdev->dev, "Couldn't register IRQ domain\n");
2148 ret = -ENOMEM;
2149 goto gpiochip_error;
2150 }
2151
2152 for (i = 0; i < SUNXI_IRQ_NUMBER; i++) {
2153 int irqno = irq_create_mapping(pctl->domain, i);
2154
2155 irq_set_chip_and_handler(irqno, &sunxi_pinctrl_irq_chip,
2156 handle_simple_irq);
2157 irq_set_chip_data(irqno, pctl);
2158 };
2159
2160 irq_set_chained_handler(pctl->irq, sunxi_pinctrl_irq_handler);
2161 irq_set_handler_data(pctl->irq, pctl);
2162
2008 dev_info(&pdev->dev, "initialized sunXi PIO driver\n"); 2163 dev_info(&pdev->dev, "initialized sunXi PIO driver\n");
2009 2164
2010 return 0; 2165 return 0;
diff --git a/drivers/pinctrl/pinctrl-sunxi.h b/drivers/pinctrl/pinctrl-sunxi.h
index e921621059ce..d68047d8f699 100644
--- a/drivers/pinctrl/pinctrl-sunxi.h
+++ b/drivers/pinctrl/pinctrl-sunxi.h
@@ -344,9 +344,31 @@
344#define PULL_PINS_BITS 2 344#define PULL_PINS_BITS 2
345#define PULL_PINS_MASK 0x03 345#define PULL_PINS_MASK 0x03
346 346
347#define SUNXI_IRQ_NUMBER 32
348
349#define IRQ_CFG_REG 0x200
350#define IRQ_CFG_IRQ_PER_REG 8
351#define IRQ_CFG_IRQ_BITS 4
352#define IRQ_CFG_IRQ_MASK ((1 << IRQ_CFG_IRQ_BITS) - 1)
353#define IRQ_CTRL_REG 0x210
354#define IRQ_CTRL_IRQ_PER_REG 32
355#define IRQ_CTRL_IRQ_BITS 1
356#define IRQ_CTRL_IRQ_MASK ((1 << IRQ_CTRL_IRQ_BITS) - 1)
357#define IRQ_STATUS_REG 0x214
358#define IRQ_STATUS_IRQ_PER_REG 32
359#define IRQ_STATUS_IRQ_BITS 1
360#define IRQ_STATUS_IRQ_MASK ((1 << IRQ_STATUS_IRQ_BITS) - 1)
361
362#define IRQ_EDGE_RISING 0x00
363#define IRQ_EDGE_FALLING 0x01
364#define IRQ_LEVEL_HIGH 0x02
365#define IRQ_LEVEL_LOW 0x03
366#define IRQ_EDGE_BOTH 0x04
367
347struct sunxi_desc_function { 368struct sunxi_desc_function {
348 const char *name; 369 const char *name;
349 u8 muxval; 370 u8 muxval;
371 u8 irqnum;
350}; 372};
351 373
352struct sunxi_desc_pin { 374struct sunxi_desc_pin {
@@ -378,10 +400,13 @@ struct sunxi_pinctrl {
378 struct gpio_chip *chip; 400 struct gpio_chip *chip;
379 struct sunxi_pinctrl_desc *desc; 401 struct sunxi_pinctrl_desc *desc;
380 struct device *dev; 402 struct device *dev;
403 struct irq_domain *domain;
381 struct sunxi_pinctrl_function *functions; 404 struct sunxi_pinctrl_function *functions;
382 unsigned nfunctions; 405 unsigned nfunctions;
383 struct sunxi_pinctrl_group *groups; 406 struct sunxi_pinctrl_group *groups;
384 unsigned ngroups; 407 unsigned ngroups;
408 int irq;
409 int irq_array[SUNXI_IRQ_NUMBER];
385 struct pinctrl_dev *pctl_dev; 410 struct pinctrl_dev *pctl_dev;
386}; 411};
387 412
@@ -398,6 +423,13 @@ struct sunxi_pinctrl {
398 .muxval = _val, \ 423 .muxval = _val, \
399 } 424 }
400 425
426#define SUNXI_FUNCTION_IRQ(_val, _irq) \
427 { \
428 .name = "irq", \
429 .muxval = _val, \
430 .irqnum = _irq, \
431 }
432
401/* 433/*
402 * The sunXi PIO registers are organized as is: 434 * The sunXi PIO registers are organized as is:
403 * 0x00 - 0x0c Muxing values. 435 * 0x00 - 0x0c Muxing values.
@@ -475,4 +507,40 @@ static inline u32 sunxi_pull_offset(u16 pin)
475 return pin_num * PULL_PINS_BITS; 507 return pin_num * PULL_PINS_BITS;
476} 508}
477 509
510static inline u32 sunxi_irq_cfg_reg(u16 irq)
511{
512 u8 reg = irq / IRQ_CFG_IRQ_PER_REG;
513 return reg + IRQ_CFG_REG;
514}
515
516static inline u32 sunxi_irq_cfg_offset(u16 irq)
517{
518 u32 irq_num = irq % IRQ_CFG_IRQ_PER_REG;
519 return irq_num * IRQ_CFG_IRQ_BITS;
520}
521
522static inline u32 sunxi_irq_ctrl_reg(u16 irq)
523{
524 u8 reg = irq / IRQ_CTRL_IRQ_PER_REG;
525 return reg + IRQ_CTRL_REG;
526}
527
528static inline u32 sunxi_irq_ctrl_offset(u16 irq)
529{
530 u32 irq_num = irq % IRQ_CTRL_IRQ_PER_REG;
531 return irq_num * IRQ_CTRL_IRQ_BITS;
532}
533
534static inline u32 sunxi_irq_status_reg(u16 irq)
535{
536 u8 reg = irq / IRQ_STATUS_IRQ_PER_REG;
537 return reg + IRQ_STATUS_REG;
538}
539
540static inline u32 sunxi_irq_status_offset(u16 irq)
541{
542 u32 irq_num = irq % IRQ_STATUS_IRQ_PER_REG;
543 return irq_num * IRQ_STATUS_IRQ_BITS;
544}
545
478#endif /* __PINCTRL_SUNXI_H */ 546#endif /* __PINCTRL_SUNXI_H */