Skip to content

Commit 6fc6553

Browse files
Charles E. Youseandrewboie
authored andcommitted
drivers/gpio/gpio_intel_apl: remove dependency on shared interrupts
The GPIO driver for the Intel Apollo Lake has so many pins it has to export ten devices to shoehorn its one device into the GPIO API. The current implementation uses the shared IRQ driver because these pseudodevices all share one IRQ. However, since the GPIO driver is aware of all the possible interrupt sources, it's smaller and faster (and not even messy) to handle it internally, so this patch eliminates the dependency on the shared IRQ driver. Signed-off-by: Charles E. Youse <[email protected]>
1 parent 51a9e6f commit 6fc6553

File tree

5 files changed

+98
-124
lines changed

5 files changed

+98
-124
lines changed

drivers/gpio/gpio_intel_apl.c

Lines changed: 60 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,14 @@
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>
@@ -30,9 +31,12 @@
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+
151164
static 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-
437455
int 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+
473505
GPIO_INTEL_APL_DEV_CFG_DATA(n, N, 0, 0, 32);
474506
GPIO_INTEL_APL_DEV_CFG_DATA(n, N, 1, 32, 32);
475507
GPIO_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

484516
GPIO_INTEL_APL_DEV_CFG_DATA(sw, SW, 0, 0, 32);
485517
GPIO_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-
}

dts/bindings/gpio/intel,apl-gpio.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ properties:
3030
description: Human readable string describing the device (used by Zephyr for API name)
3131
generation: define
3232

33+
interrupts:
34+
type: int
35+
generation: define
36+
category: required
37+
3338
cell_string: GPIO
3439

3540
"#cells":

dts/x86/apollo_lake.dtsi

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,21 +50,14 @@
5050
<0xd0c40000 0x1000>,
5151
<0xd0c70000 0x1000>,
5252
<0xd0c00000 0x1000>;
53-
label = "APL_GPIO";
53+
interrupts = <14 IRQ_TYPE_LEVEL_LOW 3>;
54+
interrupt-parent = <&intc>;
5455

56+
label = "APL_GPIO";
5557
gpio-controller ;
5658
#gpio-cells = <2>;
5759

5860
status = "disabled";
5961
};
6062
};
61-
62-
sharedirq0: sharedirq0 {
63-
compatible = "shared-irq";
64-
label = "APL_GPIO_IRQ";
65-
interrupts = <14 IRQ_TYPE_LEVEL_LOW 3>;
66-
interrupt-parent = <&intc>;
67-
68-
status = "ok";
69-
};
7063
};

soc/x86/apollo_lake/Kconfig.defconfig

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,6 @@ if GPIO
6262
config GPIO_INTEL_APL
6363
default y
6464

65-
config SHARED_IRQ
66-
default y if GPIO_INTEL_APL
67-
68-
config SHARED_IRQ_0
69-
default y if SHARED_IRQ
70-
71-
config SHARED_IRQ_NUM_CLIENTS
72-
default 10 if SHARED_IRQ
73-
7465
endif # GPIO
7566

7667
endif # SOC_APOLLO_LAKE

soc/x86/apollo_lake/dts_fixup.h

Lines changed: 30 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -6,70 +6,35 @@
66

77
/* SoC level DTS fixup file */
88

9-
#define DT_PHYS_RAM_ADDR CONFIG_SRAM_BASE_ADDRESS
10-
11-
#define DT_PHYS_LOAD_ADDR CONFIG_FLASH_BASE_ADDRESS
12-
13-
#define DT_RAM_SIZE CONFIG_SRAM_SIZE
14-
15-
#define DT_ROM_SIZE CONFIG_FLASH_SIZE
16-
17-
#define DT_IOAPIC_BASE_ADDRESS \
18-
DT_INTEL_IOAPIC_FEC00000_BASE_ADDRESS
19-
20-
#define DT_APL_GPIO_BASE_ADDRESS_N \
21-
DT_INTEL_APL_GPIO_D0C50000_BASE_ADDRESS_0
22-
23-
#define DT_APL_GPIO_BASE_ADDRESS_NW \
24-
DT_INTEL_APL_GPIO_D0C50000_BASE_ADDRESS_1
25-
26-
#define DT_APL_GPIO_BASE_ADDRESS_W \
27-
DT_INTEL_APL_GPIO_D0C50000_BASE_ADDRESS_2
28-
29-
#define DT_APL_GPIO_BASE_ADDRESS_SW \
30-
DT_INTEL_APL_GPIO_D0C50000_BASE_ADDRESS_3
31-
32-
#define DT_APL_GPIO_IRQ DT_INTEL_APL_GPIO_D0C50000_IRQ_0
33-
34-
#define DT_APL_GPIO_IRQ_PRIORITY \
35-
DT_INTEL_APL_GPIO_D0C50000_IRQ_0_PRIORITY
36-
37-
#define DT_APL_GPIO_IRQ_SENSE \
38-
DT_INTEL_APL_GPIO_D0C50000_IRQ_0_SENSE
39-
40-
#define DT_APL_GPIO_MEM_SIZE_N DT_INTEL_APL_GPIO_D0C50000_SIZE_0
41-
#define DT_APL_GPIO_MEM_SIZE_NW DT_INTEL_APL_GPIO_D0C50000_SIZE_1
42-
#define DT_APL_GPIO_MEM_SIZE_W DT_INTEL_APL_GPIO_D0C50000_SIZE_2
43-
#define DT_APL_GPIO_MEM_SIZE_SW DT_INTEL_APL_GPIO_D0C50000_SIZE_3
44-
45-
#define DT_APL_GPIO_LABEL_N_0 \
46-
DT_INTEL_APL_GPIO_D0C50000_LABEL "_N_0"
47-
48-
#define DT_APL_GPIO_LABEL_N_1 \
49-
DT_INTEL_APL_GPIO_D0C50000_LABEL "_N_1"
50-
51-
#define DT_APL_GPIO_LABEL_N_2 \
52-
DT_INTEL_APL_GPIO_D0C50000_LABEL "_N_2"
53-
54-
#define DT_APL_GPIO_LABEL_NW_0 \
55-
DT_INTEL_APL_GPIO_D0C50000_LABEL "_NW_0"
56-
57-
#define DT_APL_GPIO_LABEL_NW_1 \
58-
DT_INTEL_APL_GPIO_D0C50000_LABEL "_NW_1"
59-
60-
#define DT_APL_GPIO_LABEL_NW_2 \
61-
DT_INTEL_APL_GPIO_D0C50000_LABEL "_NW_2"
62-
63-
#define DT_APL_GPIO_LABEL_W_0 \
64-
DT_INTEL_APL_GPIO_D0C50000_LABEL "_W_0"
65-
66-
#define DT_APL_GPIO_LABEL_W_1 \
67-
DT_INTEL_APL_GPIO_D0C50000_LABEL "_W_1"
68-
69-
#define DT_APL_GPIO_LABEL_SW_0 \
70-
DT_INTEL_APL_GPIO_D0C50000_LABEL "_SW_0"
71-
72-
#define DT_APL_GPIO_LABEL_SW_1 \
73-
DT_INTEL_APL_GPIO_D0C50000_LABEL "_SW_1"
9+
#define DT_PHYS_RAM_ADDR CONFIG_SRAM_BASE_ADDRESS
10+
#define DT_PHYS_LOAD_ADDR CONFIG_FLASH_BASE_ADDRESS
11+
#define DT_RAM_SIZE CONFIG_SRAM_SIZE
12+
#define DT_ROM_SIZE CONFIG_FLASH_SIZE
13+
14+
#define DT_IOAPIC_BASE_ADDRESS DT_INTEL_IOAPIC_FEC00000_BASE_ADDRESS
15+
#define DT_APL_GPIO_BASE_ADDRESS_N DT_INTEL_APL_GPIO_D0C50000_BASE_ADDRESS_0
16+
#define DT_APL_GPIO_BASE_ADDRESS_NW DT_INTEL_APL_GPIO_D0C50000_BASE_ADDRESS_1
17+
#define DT_APL_GPIO_BASE_ADDRESS_W DT_INTEL_APL_GPIO_D0C50000_BASE_ADDRESS_2
18+
#define DT_APL_GPIO_BASE_ADDRESS_SW DT_INTEL_APL_GPIO_D0C50000_BASE_ADDRESS_3
19+
20+
#define DT_APL_GPIO_IRQ DT_INTEL_APL_GPIO_D0C50000_IRQ_0
21+
#define DT_APL_GPIO_IRQ_PRIORITY DT_INTEL_APL_GPIO_D0C50000_IRQ_0_PRIORITY
22+
#define DT_APL_GPIO_IRQ_SENSE DT_INTEL_APL_GPIO_D0C50000_IRQ_0_SENSE
23+
24+
#define DT_APL_GPIO_MEM_SIZE_N DT_INTEL_APL_GPIO_D0C50000_SIZE_0
25+
#define DT_APL_GPIO_MEM_SIZE_NW DT_INTEL_APL_GPIO_D0C50000_SIZE_1
26+
#define DT_APL_GPIO_MEM_SIZE_W DT_INTEL_APL_GPIO_D0C50000_SIZE_2
27+
#define DT_APL_GPIO_MEM_SIZE_SW DT_INTEL_APL_GPIO_D0C50000_SIZE_3
28+
29+
#define DT_APL_GPIO_LABEL_N_0 DT_INTEL_APL_GPIO_D0C50000_LABEL "_N_0"
30+
#define DT_APL_GPIO_LABEL_N_1 DT_INTEL_APL_GPIO_D0C50000_LABEL "_N_1"
31+
#define DT_APL_GPIO_LABEL_N_2 DT_INTEL_APL_GPIO_D0C50000_LABEL "_N_2"
32+
#define DT_APL_GPIO_LABEL_NW_0 DT_INTEL_APL_GPIO_D0C50000_LABEL "_NW_0"
33+
#define DT_APL_GPIO_LABEL_NW_1 DT_INTEL_APL_GPIO_D0C50000_LABEL "_NW_1"
34+
#define DT_APL_GPIO_LABEL_NW_2 DT_INTEL_APL_GPIO_D0C50000_LABEL "_NW_2"
35+
#define DT_APL_GPIO_LABEL_W_0 DT_INTEL_APL_GPIO_D0C50000_LABEL "_W_0"
36+
#define DT_APL_GPIO_LABEL_W_1 DT_INTEL_APL_GPIO_D0C50000_LABEL "_W_1"
37+
#define DT_APL_GPIO_LABEL_SW_0 DT_INTEL_APL_GPIO_D0C50000_LABEL "_SW_0"
38+
#define DT_APL_GPIO_LABEL_SW_1 DT_INTEL_APL_GPIO_D0C50000_LABEL "_SW_1"
7439

7540
/* End of SoC Level DTS fixup file */

0 commit comments

Comments
 (0)