aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/pinctrl-sunxi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/pinctrl-sunxi.c')
-rw-r--r--drivers/pinctrl/pinctrl-sunxi.c155
1 files changed, 155 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;