@@ -331,13 +331,19 @@ struct ocelot_pinctrl {
331331 const struct ocelot_pincfg_data * pincfg_data ;
332332 struct ocelot_pmx_func func [FUNC_MAX ];
333333 u8 stride ;
334+ struct workqueue_struct * wq ;
334335};
335336
336337struct ocelot_match_data {
337338 struct pinctrl_desc desc ;
338339 struct ocelot_pincfg_data pincfg_data ;
339340};
340341
342+ struct ocelot_irq_work {
343+ struct work_struct irq_work ;
344+ struct irq_desc * irq_desc ;
345+ };
346+
341347#define LUTON_P (p , f0 , f1 ) \
342348static struct ocelot_pin_caps luton_pin_##p = { \
343349 .pin = p, \
@@ -1813,6 +1819,75 @@ static void ocelot_irq_mask(struct irq_data *data)
18131819 gpiochip_disable_irq (chip , gpio );
18141820}
18151821
1822+ static void ocelot_irq_work (struct work_struct * work )
1823+ {
1824+ struct ocelot_irq_work * w = container_of (work , struct ocelot_irq_work , irq_work );
1825+ struct irq_chip * parent_chip = irq_desc_get_chip (w -> irq_desc );
1826+ struct gpio_chip * chip = irq_desc_get_chip_data (w -> irq_desc );
1827+ struct irq_data * data = irq_desc_get_irq_data (w -> irq_desc );
1828+ unsigned int gpio = irqd_to_hwirq (data );
1829+
1830+ local_irq_disable ();
1831+ chained_irq_enter (parent_chip , w -> irq_desc );
1832+ generic_handle_domain_irq (chip -> irq .domain , gpio );
1833+ chained_irq_exit (parent_chip , w -> irq_desc );
1834+ local_irq_enable ();
1835+
1836+ kfree (w );
1837+ }
1838+
1839+ static void ocelot_irq_unmask_level (struct irq_data * data )
1840+ {
1841+ struct gpio_chip * chip = irq_data_get_irq_chip_data (data );
1842+ struct ocelot_pinctrl * info = gpiochip_get_data (chip );
1843+ struct irq_desc * desc = irq_data_to_desc (data );
1844+ unsigned int gpio = irqd_to_hwirq (data );
1845+ unsigned int bit = BIT (gpio % 32 );
1846+ bool ack = false, active = false;
1847+ u8 trigger_level ;
1848+ int val ;
1849+
1850+ trigger_level = irqd_get_trigger_type (data );
1851+
1852+ /* Check if the interrupt line is still active. */
1853+ regmap_read (info -> map , REG (OCELOT_GPIO_IN , info , gpio ), & val );
1854+ if ((!(val & bit ) && trigger_level == IRQ_TYPE_LEVEL_LOW ) ||
1855+ (val & bit && trigger_level == IRQ_TYPE_LEVEL_HIGH ))
1856+ active = true;
1857+
1858+ /*
1859+ * Check if the interrupt controller has seen any changes in the
1860+ * interrupt line.
1861+ */
1862+ regmap_read (info -> map , REG (OCELOT_GPIO_INTR , info , gpio ), & val );
1863+ if (val & bit )
1864+ ack = true;
1865+
1866+ /* Enable the interrupt now */
1867+ gpiochip_enable_irq (chip , gpio );
1868+ regmap_update_bits (info -> map , REG (OCELOT_GPIO_INTR_ENA , info , gpio ),
1869+ bit , bit );
1870+
1871+ /*
1872+ * In case the interrupt line is still active and the interrupt
1873+ * controller has not seen any changes in the interrupt line, then it
1874+ * means that there happen another interrupt while the line was active.
1875+ * So we missed that one, so we need to kick the interrupt again
1876+ * handler.
1877+ */
1878+ if (active && !ack ) {
1879+ struct ocelot_irq_work * work ;
1880+
1881+ work = kmalloc (sizeof (* work ), GFP_ATOMIC );
1882+ if (!work )
1883+ return ;
1884+
1885+ work -> irq_desc = desc ;
1886+ INIT_WORK (& work -> irq_work , ocelot_irq_work );
1887+ queue_work (info -> wq , & work -> irq_work );
1888+ }
1889+ }
1890+
18161891static void ocelot_irq_unmask (struct irq_data * data )
18171892{
18181893 struct gpio_chip * chip = irq_data_get_irq_chip_data (data );
@@ -1836,13 +1911,12 @@ static void ocelot_irq_ack(struct irq_data *data)
18361911
18371912static int ocelot_irq_set_type (struct irq_data * data , unsigned int type );
18381913
1839- static struct irq_chip ocelot_eoi_irqchip = {
1914+ static struct irq_chip ocelot_level_irqchip = {
18401915 .name = "gpio" ,
18411916 .irq_mask = ocelot_irq_mask ,
1842- .irq_eoi = ocelot_irq_ack ,
1843- .irq_unmask = ocelot_irq_unmask ,
1844- .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED |
1845- IRQCHIP_IMMUTABLE ,
1917+ .irq_ack = ocelot_irq_ack ,
1918+ .irq_unmask = ocelot_irq_unmask_level ,
1919+ .flags = IRQCHIP_IMMUTABLE ,
18461920 .irq_set_type = ocelot_irq_set_type ,
18471921 GPIOCHIP_IRQ_RESOURCE_HELPERS
18481922};
@@ -1859,14 +1933,9 @@ static struct irq_chip ocelot_irqchip = {
18591933
18601934static int ocelot_irq_set_type (struct irq_data * data , unsigned int type )
18611935{
1862- type &= IRQ_TYPE_SENSE_MASK ;
1863-
1864- if (!(type & (IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_LEVEL_HIGH )))
1865- return - EINVAL ;
1866-
1867- if (type & IRQ_TYPE_LEVEL_HIGH )
1868- irq_set_chip_handler_name_locked (data , & ocelot_eoi_irqchip ,
1869- handle_fasteoi_irq , NULL );
1936+ if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW ))
1937+ irq_set_chip_handler_name_locked (data , & ocelot_level_irqchip ,
1938+ handle_level_irq , NULL );
18701939 if (type & IRQ_TYPE_EDGE_BOTH )
18711940 irq_set_chip_handler_name_locked (data , & ocelot_irqchip ,
18721941 handle_edge_irq , NULL );
@@ -1996,6 +2065,10 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev)
19962065 if (!info -> desc )
19972066 return - ENOMEM ;
19982067
2068+ info -> wq = alloc_ordered_workqueue ("ocelot_ordered" , 0 );
2069+ if (!info -> wq )
2070+ return - ENOMEM ;
2071+
19992072 info -> pincfg_data = & data -> pincfg_data ;
20002073
20012074 reset = devm_reset_control_get_optional_shared (dev , "switch" );
@@ -2018,7 +2091,7 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev)
20182091 dev_err (dev , "Failed to create regmap\n" );
20192092 return PTR_ERR (info -> map );
20202093 }
2021- dev_set_drvdata (dev , info -> map );
2094+ dev_set_drvdata (dev , info );
20222095 info -> dev = dev ;
20232096
20242097 /* Pinconf registers */
@@ -2043,13 +2116,23 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev)
20432116 return 0 ;
20442117}
20452118
2119+ static int ocelot_pinctrl_remove (struct platform_device * pdev )
2120+ {
2121+ struct ocelot_pinctrl * info = platform_get_drvdata (pdev );
2122+
2123+ destroy_workqueue (info -> wq );
2124+
2125+ return 0 ;
2126+ }
2127+
20462128static struct platform_driver ocelot_pinctrl_driver = {
20472129 .driver = {
20482130 .name = "pinctrl-ocelot" ,
20492131 .of_match_table = of_match_ptr (ocelot_pinctrl_of_match ),
20502132 .suppress_bind_attrs = true,
20512133 },
20522134 .probe = ocelot_pinctrl_probe ,
2135+ .remove = ocelot_pinctrl_remove ,
20532136};
20542137module_platform_driver (ocelot_pinctrl_driver );
20552138MODULE_LICENSE ("Dual MIT/GPL" );
0 commit comments