1515 * The GPIO controller has 245 pins divided into four sets.
1616 * Each set has its own MMIO address space. Due to GPIO
1717 * callback only allowing 32 pins (as a 32-bit mask) at once,
18- * each set is further sub-divided into multiple devices.
19- * Because of this, shared IRQ must be used .
18+ * each set is further sub-divided into multiple devices, so
19+ * we export GPIO_INTEL_APL_NR_SUBDEVS devices to the kernel .
2020 */
2121
22+ #define GPIO_INTEL_APL_NR_SUBDEVS 10
23+
2224#include <errno.h>
2325#include <gpio.h>
24- #include <shared_irq.h>
2526#include <soc.h>
2627#include <sys_io.h>
2728#include <misc/__assert.h>
3031
3132#include "gpio_utils.h"
3233
33- #ifndef CONFIG_SHARED_IRQ
34- #error "Need CONFIG_SHARED_IRQ!"
35- #endif
34+ /*
35+ * only IRQ 14 is supported now. the docs say IRQ 15 is supported
36+ * as well, but my (admitted cursory) testing disagrees.
37+ */
38+
39+ BUILD_ASSERT (DT_APL_GPIO_IRQ == 14 );
3640
3741#define REG_PAD_BASE_ADDR 0x000C
3842
@@ -148,29 +152,45 @@ static bool check_perm(struct device *dev, u32_t raw_pin)
148152#define check_perm (...) (1)
149153#endif
150154
155+ /*
156+ * as the kernel initializes the subdevices, we add them
157+ * to the list of devices to check at ISR time.
158+ */
159+
160+ static int nr_isr_devs ;
161+
162+ static struct device * isr_devs [GPIO_INTEL_APL_NR_SUBDEVS ];
163+
151164static int gpio_intel_apl_isr (struct device * dev )
152165{
153- const struct gpio_intel_apl_config * cfg = dev -> config -> config_info ;
154- struct gpio_intel_apl_data * data = dev -> driver_data ;
166+ const struct gpio_intel_apl_config * cfg ;
167+ struct gpio_intel_apl_data * data ;
155168 struct gpio_callback * cb , * tmp ;
156169 u32_t reg , int_sts , cur_mask , acc_mask ;
157-
158- reg = cfg -> reg_base + REG_GPI_INT_STS_BASE
159- + ((cfg -> pin_offset >> 5 ) << 2 );
160- int_sts = sys_read32 (reg );
161- acc_mask = 0U ;
162-
163- SYS_SLIST_FOR_EACH_CONTAINER_SAFE (& data -> cb , cb , tmp , node ) {
164- cur_mask = int_sts & cb -> pin_mask ;
165- acc_mask |= cur_mask ;
166- if (cur_mask ) {
167- __ASSERT (cb -> handler , "No callback handler!" );
168- cb -> handler (dev , cb , cur_mask );
170+ int isr_dev ;
171+
172+ for (isr_dev = 0 ; isr_dev < nr_isr_devs ; ++ isr_dev ) {
173+ dev = isr_devs [isr_dev ];
174+ cfg = dev -> config -> config_info ;
175+ data = dev -> driver_data ;
176+
177+ reg = cfg -> reg_base + REG_GPI_INT_STS_BASE
178+ + ((cfg -> pin_offset >> 5 ) << 2 );
179+ int_sts = sys_read32 (reg );
180+ acc_mask = 0U ;
181+
182+ SYS_SLIST_FOR_EACH_CONTAINER_SAFE (& data -> cb , cb , tmp , node ) {
183+ cur_mask = int_sts & cb -> pin_mask ;
184+ acc_mask |= cur_mask ;
185+ if (cur_mask ) {
186+ __ASSERT (cb -> handler , "No callback handler!" );
187+ cb -> handler (dev , cb , cur_mask );
188+ }
169189 }
170- }
171190
172- /* clear handled interrupt bits */
173- sys_write32 (acc_mask , reg );
191+ /* clear handled interrupt bits */
192+ sys_write32 (acc_mask , reg );
193+ }
174194
175195 return 0 ;
176196}
@@ -432,18 +452,28 @@ static const struct gpio_driver_api gpio_intel_apl_api = {
432452 .disable_callback = gpio_intel_apl_disable_callback ,
433453};
434454
435- static void gpio_intel_apl_irq_config (struct device * dev );
436-
437455int gpio_intel_apl_init (struct device * dev )
438456{
439457 const struct gpio_intel_apl_config * cfg = dev -> config -> config_info ;
440458 struct gpio_intel_apl_data * data = dev -> driver_data ;
441459
442- gpio_intel_apl_irq_config (dev );
443-
444460 data -> pad_base = sys_read32 (cfg -> reg_base + REG_PAD_BASE_ADDR );
445461
446- /* Set to route interrupt through IRQ 14 */
462+ __ASSERT (nr_isr_devs < GPIO_INTEL_APL_NR_SUBDEVS , "too many subdevs" );
463+
464+ if (nr_isr_devs == 0 ) {
465+ IRQ_CONNECT (DT_APL_GPIO_IRQ ,
466+ DT_APL_GPIO_IRQ_PRIORITY ,
467+ gpio_intel_apl_isr , NULL ,
468+ DT_APL_GPIO_IRQ_SENSE );
469+
470+ irq_enable (DT_APL_GPIO_IRQ );
471+ }
472+
473+ isr_devs [nr_isr_devs ++ ] = dev ;
474+
475+ /* route to IRQ 14 */
476+
447477 sys_bitfield_clear_bit (data -> pad_base + REG_MISCCFG ,
448478 MISCCFG_IRQ_ROUTE_POS );
449479
@@ -470,6 +500,8 @@ DEVICE_AND_API_INIT(gpio_intel_apl_##dir_l##_##pos, \
470500 POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
471501 &gpio_intel_apl_api)
472502
503+ /* "sub" devices. no more than GPIO_INTEL_APL_NR_SUBDEVS of these! */
504+
473505GPIO_INTEL_APL_DEV_CFG_DATA (n , N , 0 , 0 , 32 );
474506GPIO_INTEL_APL_DEV_CFG_DATA (n , N , 1 , 32 , 32 );
475507GPIO_INTEL_APL_DEV_CFG_DATA (n , N , 2 , 32 , 14 );
@@ -483,15 +515,3 @@ GPIO_INTEL_APL_DEV_CFG_DATA(w, W, 1, 32, 15);
483515
484516GPIO_INTEL_APL_DEV_CFG_DATA (sw , SW , 0 , 0 , 32 );
485517GPIO_INTEL_APL_DEV_CFG_DATA (sw , SW , 1 , 32 , 11 );
486-
487- static void gpio_intel_apl_irq_config (struct device * dev )
488- {
489- struct device * irq_dev ;
490-
491- irq_dev = device_get_binding (DT_SHARED_IRQ_SHAREDIRQ0_LABEL );
492- __ASSERT (irq_dev != NULL ,
493- "Failed to get shared IRQ device binding" );
494-
495- shared_irq_isr_register (irq_dev , gpio_intel_apl_isr , dev );
496- shared_irq_enable (irq_dev , dev );
497- }
0 commit comments