77 * Copyright 2025 Analog Devices, Inc.
88 */
99
10+ #include <linux/bitmap.h>
11+ #include <linux/bitops.h>
12+ #include <linux/container_of.h>
1013#include <linux/device.h>
1114#include <linux/gpio/driver.h>
1215#include <linux/mfd/adp5585.h>
1316#include <linux/module.h>
17+ #include <linux/mutex.h>
18+ #include <linux/notifier.h>
1419#include <linux/platform_device.h>
1520#include <linux/regmap.h>
1621#include <linux/types.h>
3641struct adp5585_gpio_chip {
3742 int (* bank )(unsigned int off );
3843 int (* bit )(unsigned int off );
39- unsigned int max_gpio ;
4044 unsigned int debounce_dis_a ;
4145 unsigned int rpull_cfg_a ;
4246 unsigned int gpo_data_a ;
4347 unsigned int gpo_out_a ;
4448 unsigned int gpio_dir_a ;
4549 unsigned int gpi_stat_a ;
50+ unsigned int gpi_int_lvl_a ;
51+ unsigned int gpi_ev_a ;
52+ unsigned int gpi_ev_min ;
53+ unsigned int gpi_ev_max ;
4654 bool has_bias_hole ;
4755};
4856
4957struct adp5585_gpio_dev {
5058 struct gpio_chip gpio_chip ;
59+ struct notifier_block nb ;
5160 const struct adp5585_gpio_chip * info ;
5261 struct regmap * regmap ;
62+ unsigned long irq_mask ;
63+ unsigned long irq_en ;
64+ unsigned long irq_active_high ;
65+ /* used for irqchip bus locking */
66+ struct mutex bus_lock ;
5367};
5468
5569static int adp5585_gpio_bank (unsigned int off )
@@ -224,12 +238,175 @@ static int adp5585_gpio_set_config(struct gpio_chip *chip, unsigned int off,
224238 };
225239}
226240
241+ static int adp5585_gpio_request (struct gpio_chip * chip , unsigned int off )
242+ {
243+ struct adp5585_gpio_dev * adp5585_gpio = gpiochip_get_data (chip );
244+ const struct adp5585_gpio_chip * info = adp5585_gpio -> info ;
245+ struct device * dev = chip -> parent ;
246+ struct adp5585_dev * adp5585 = dev_get_drvdata (dev -> parent );
247+ const struct adp5585_regs * regs = adp5585 -> regs ;
248+ int ret ;
249+
250+ ret = test_and_set_bit (off , adp5585 -> pin_usage );
251+ if (ret )
252+ return - EBUSY ;
253+
254+ /* make sure it's configured for GPIO */
255+ return regmap_clear_bits (adp5585_gpio -> regmap ,
256+ regs -> pin_cfg_a + info -> bank (off ),
257+ info -> bit (off ));
258+ }
259+
260+ static void adp5585_gpio_free (struct gpio_chip * chip , unsigned int off )
261+ {
262+ struct device * dev = chip -> parent ;
263+ struct adp5585_dev * adp5585 = dev_get_drvdata (dev -> parent );
264+
265+ clear_bit (off , adp5585 -> pin_usage );
266+ }
267+
268+ static int adp5585_gpio_key_event (struct notifier_block * nb , unsigned long key ,
269+ void * data )
270+ {
271+ struct adp5585_gpio_dev * adp5585_gpio = container_of (nb , struct adp5585_gpio_dev , nb );
272+ struct device * dev = adp5585_gpio -> gpio_chip .parent ;
273+ unsigned long key_press = (unsigned long )data ;
274+ unsigned int irq , irq_type ;
275+ struct irq_data * irqd ;
276+ bool active_high ;
277+ unsigned int off ;
278+
279+ /* make sure the event is for me */
280+ if (key < adp5585_gpio -> info -> gpi_ev_min || key > adp5585_gpio -> info -> gpi_ev_max )
281+ return NOTIFY_DONE ;
282+
283+ off = key - adp5585_gpio -> info -> gpi_ev_min ;
284+ active_high = test_bit (off , & adp5585_gpio -> irq_active_high );
285+
286+ irq = irq_find_mapping (adp5585_gpio -> gpio_chip .irq .domain , off );
287+ if (!irq )
288+ return NOTIFY_BAD ;
289+
290+ irqd = irq_get_irq_data (irq );
291+ if (!irqd ) {
292+ dev_err (dev , "Could not get irq(%u) data\n" , irq );
293+ return NOTIFY_BAD ;
294+ }
295+
296+ dev_dbg_ratelimited (dev , "gpio-keys event(%u) press=%lu, a_high=%u\n" ,
297+ off , key_press , active_high );
298+
299+ if (!active_high )
300+ key_press = !key_press ;
301+
302+ irq_type = irqd_get_trigger_type (irqd );
303+
304+ if ((irq_type & IRQ_TYPE_EDGE_RISING && key_press ) ||
305+ (irq_type & IRQ_TYPE_EDGE_FALLING && !key_press ))
306+ handle_nested_irq (irq );
307+
308+ return NOTIFY_STOP ;
309+ }
310+
311+ static void adp5585_irq_bus_lock (struct irq_data * d )
312+ {
313+ struct gpio_chip * gc = irq_data_get_irq_chip_data (d );
314+ struct adp5585_gpio_dev * adp5585_gpio = gpiochip_get_data (gc );
315+
316+ mutex_lock (& adp5585_gpio -> bus_lock );
317+ }
318+
319+ static void adp5585_irq_bus_sync_unlock (struct irq_data * d )
320+ {
321+ struct gpio_chip * chip = irq_data_get_irq_chip_data (d );
322+ struct adp5585_gpio_dev * adp5585_gpio = gpiochip_get_data (chip );
323+ const struct adp5585_gpio_chip * info = adp5585_gpio -> info ;
324+ irq_hw_number_t hwirq = irqd_to_hwirq (d );
325+ bool active_high = test_bit (hwirq , & adp5585_gpio -> irq_active_high );
326+ bool enabled = test_bit (hwirq , & adp5585_gpio -> irq_en );
327+ bool masked = test_bit (hwirq , & adp5585_gpio -> irq_mask );
328+ unsigned int bank = adp5585_gpio -> info -> bank (hwirq );
329+ unsigned int bit = adp5585_gpio -> info -> bit (hwirq );
330+
331+ if (masked && !enabled )
332+ goto out_unlock ;
333+ if (!masked && enabled )
334+ goto out_unlock ;
335+
336+ regmap_update_bits (adp5585_gpio -> regmap , info -> gpi_int_lvl_a + bank , bit ,
337+ active_high ? bit : 0 );
338+ regmap_update_bits (adp5585_gpio -> regmap , info -> gpi_ev_a + bank , bit ,
339+ masked ? 0 : bit );
340+ assign_bit (hwirq , & adp5585_gpio -> irq_en , !masked );
341+
342+ out_unlock :
343+ mutex_unlock (& adp5585_gpio -> bus_lock );
344+ }
345+
346+ static void adp5585_irq_mask (struct irq_data * d )
347+ {
348+ struct gpio_chip * gc = irq_data_get_irq_chip_data (d );
349+ struct adp5585_gpio_dev * adp5585_gpio = gpiochip_get_data (gc );
350+ irq_hw_number_t hwirq = irqd_to_hwirq (d );
351+
352+ __set_bit (hwirq , & adp5585_gpio -> irq_mask );
353+ gpiochip_disable_irq (gc , hwirq );
354+ }
355+
356+ static void adp5585_irq_unmask (struct irq_data * d )
357+ {
358+ struct gpio_chip * gc = irq_data_get_irq_chip_data (d );
359+ struct adp5585_gpio_dev * adp5585_gpio = gpiochip_get_data (gc );
360+ irq_hw_number_t hwirq = irqd_to_hwirq (d );
361+
362+ gpiochip_enable_irq (gc , hwirq );
363+ __clear_bit (hwirq , & adp5585_gpio -> irq_mask );
364+ }
365+
366+ static int adp5585_irq_set_type (struct irq_data * d , unsigned int type )
367+ {
368+ struct gpio_chip * gc = irq_data_get_irq_chip_data (d );
369+ struct adp5585_gpio_dev * adp5585_gpio = gpiochip_get_data (gc );
370+ irq_hw_number_t hwirq = irqd_to_hwirq (d );
371+
372+ if (!(type & IRQ_TYPE_EDGE_BOTH ))
373+ return - EINVAL ;
374+
375+ assign_bit (hwirq , & adp5585_gpio -> irq_active_high ,
376+ type == IRQ_TYPE_EDGE_RISING );
377+
378+ irq_set_handler_locked (d , handle_edge_irq );
379+ return 0 ;
380+ }
381+
382+ static const struct irq_chip adp5585_irq_chip = {
383+ .name = "adp5585" ,
384+ .irq_mask = adp5585_irq_mask ,
385+ .irq_unmask = adp5585_irq_unmask ,
386+ .irq_bus_lock = adp5585_irq_bus_lock ,
387+ .irq_bus_sync_unlock = adp5585_irq_bus_sync_unlock ,
388+ .irq_set_type = adp5585_irq_set_type ,
389+ .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_IMMUTABLE ,
390+ GPIOCHIP_IRQ_RESOURCE_HELPERS ,
391+ };
392+
393+ static void adp5585_gpio_unreg_notifier (void * data )
394+ {
395+ struct adp5585_gpio_dev * adp5585_gpio = data ;
396+ struct device * dev = adp5585_gpio -> gpio_chip .parent ;
397+ struct adp5585_dev * adp5585 = dev_get_drvdata (dev -> parent );
398+
399+ blocking_notifier_chain_unregister (& adp5585 -> event_notifier ,
400+ & adp5585_gpio -> nb );
401+ }
402+
227403static int adp5585_gpio_probe (struct platform_device * pdev )
228404{
229405 struct adp5585_dev * adp5585 = dev_get_drvdata (pdev -> dev .parent );
230406 const struct platform_device_id * id = platform_get_device_id (pdev );
231407 struct adp5585_gpio_dev * adp5585_gpio ;
232408 struct device * dev = & pdev -> dev ;
409+ struct gpio_irq_chip * girq ;
233410 struct gpio_chip * gc ;
234411 int ret ;
235412
@@ -253,13 +430,43 @@ static int adp5585_gpio_probe(struct platform_device *pdev)
253430 gc -> get = adp5585_gpio_get_value ;
254431 gc -> set_rv = adp5585_gpio_set_value ;
255432 gc -> set_config = adp5585_gpio_set_config ;
433+ gc -> request = adp5585_gpio_request ;
434+ gc -> free = adp5585_gpio_free ;
256435 gc -> can_sleep = true;
257436
258437 gc -> base = -1 ;
259- gc -> ngpio = adp5585_gpio -> info -> max_gpio ;
438+ gc -> ngpio = adp5585 -> n_pins ;
260439 gc -> label = pdev -> name ;
261440 gc -> owner = THIS_MODULE ;
262441
442+ if (device_property_present (dev -> parent , "interrupt-controller" )) {
443+ if (!adp5585 -> irq )
444+ return dev_err_probe (dev , - EINVAL ,
445+ "Unable to serve as interrupt controller without IRQ\n" );
446+
447+ girq = & adp5585_gpio -> gpio_chip .irq ;
448+ gpio_irq_chip_set_chip (girq , & adp5585_irq_chip );
449+ girq -> handler = handle_bad_irq ;
450+ girq -> threaded = true;
451+
452+ adp5585_gpio -> nb .notifier_call = adp5585_gpio_key_event ;
453+ ret = blocking_notifier_chain_register (& adp5585 -> event_notifier ,
454+ & adp5585_gpio -> nb );
455+ if (ret )
456+ return ret ;
457+
458+ ret = devm_add_action_or_reset (dev , adp5585_gpio_unreg_notifier ,
459+ adp5585_gpio );
460+ if (ret )
461+ return ret ;
462+ }
463+
464+ /* everything masked by default */
465+ adp5585_gpio -> irq_mask = ~0UL ;
466+
467+ ret = devm_mutex_init (dev , & adp5585_gpio -> bus_lock );
468+ if (ret )
469+ return ret ;
263470 ret = devm_gpiochip_add_data (dev , & adp5585_gpio -> gpio_chip ,
264471 adp5585_gpio );
265472 if (ret )
@@ -277,8 +484,11 @@ static const struct adp5585_gpio_chip adp5585_gpio_chip_info = {
277484 .gpo_out_a = ADP5585_GPO_OUT_MODE_A ,
278485 .gpio_dir_a = ADP5585_GPIO_DIRECTION_A ,
279486 .gpi_stat_a = ADP5585_GPI_STATUS_A ,
280- .max_gpio = ADP5585_PIN_MAX ,
281487 .has_bias_hole = true,
488+ .gpi_ev_min = ADP5585_GPI_EVENT_START ,
489+ .gpi_ev_max = ADP5585_GPI_EVENT_END ,
490+ .gpi_int_lvl_a = ADP5585_GPI_INT_LEVEL_A ,
491+ .gpi_ev_a = ADP5585_GPI_EVENT_EN_A ,
282492};
283493
284494static const struct adp5585_gpio_chip adp5589_gpio_chip_info = {
@@ -290,7 +500,10 @@ static const struct adp5585_gpio_chip adp5589_gpio_chip_info = {
290500 .gpo_out_a = ADP5589_GPO_OUT_MODE_A ,
291501 .gpio_dir_a = ADP5589_GPIO_DIRECTION_A ,
292502 .gpi_stat_a = ADP5589_GPI_STATUS_A ,
293- .max_gpio = ADP5589_PIN_MAX ,
503+ .gpi_ev_min = ADP5589_GPI_EVENT_START ,
504+ .gpi_ev_max = ADP5589_GPI_EVENT_END ,
505+ .gpi_int_lvl_a = ADP5589_GPI_INT_LEVEL_A ,
506+ .gpi_ev_a = ADP5589_GPI_EVENT_EN_A ,
294507};
295508
296509static const struct platform_device_id adp5585_gpio_id_table [] = {
0 commit comments