Intel® Quark™ Microcontroller Software Interface  1.4.0
Intel® Quark™ Microcontroller BSP
qm_gpio.c
1 /*
2  * {% copyright %}
3  */
4 
5 #include "qm_gpio.h"
6 
7 #if (HAS_SOC_CONTEXT_RETENTION)
8 #include "power_states.h"
9 #endif /* HAS_SOC_CONTEXT_RETENTION */
10 
11 #define ENABLE_PCLK (0x1)
12 
13 #ifndef UNIT_TEST
14 qm_gpio_reg_t *qm_gpio[QM_GPIO_NUM] = {(qm_gpio_reg_t *)QM_GPIO_BASE,
15 #if (HAS_AON_GPIO)
16  (qm_gpio_reg_t *)QM_AON_GPIO_BASE
17 #endif /* HAS_AON_GPIO */
18 };
19 #endif /* UNIT_TEST */
20 
21 static void (*callback[QM_GPIO_NUM])(void *, uint32_t);
22 static void *callback_data[QM_GPIO_NUM];
23 
24 static void gpio_isr(const qm_gpio_t gpio)
25 {
26  const uint32_t int_status = QM_GPIO[gpio]->gpio_intstatus;
27 
28 #if (HAS_SOC_CONTEXT_RETENTION)
29  if (QM_SCSS_GP->gps0 & QM_GPS0_POWER_STATES_MASK) {
31  }
32 #endif
33 
34  if (callback[gpio]) {
35  (*callback[gpio])(callback_data[gpio], int_status);
36  }
37 
38  /* This will clear all pending interrupts flags in status */
39  QM_GPIO[gpio]->gpio_porta_eoi = int_status;
40  /* Read back EOI register to avoid a spurious interrupt due to EOI
41  * propagation delay */
42  QM_GPIO[gpio]->gpio_porta_eoi;
43 }
44 
45 QM_ISR_DECLARE(qm_gpio_0_isr)
46 {
47  gpio_isr(QM_GPIO_0);
48  QM_ISR_EOI(QM_IRQ_GPIO_0_INT_VECTOR);
49 }
50 
51 #if (HAS_AON_GPIO)
52 QM_ISR_DECLARE(qm_aon_gpio_0_isr)
53 {
54  gpio_isr(QM_AON_GPIO_0);
55  QM_ISR_EOI(QM_IRQ_AON_GPIO_0_INT_VECTOR);
56 }
57 #endif
58 
60  const qm_gpio_port_config_t *const cfg)
61 {
62  QM_CHECK(gpio < QM_GPIO_NUM, -EINVAL);
63  QM_CHECK(cfg != NULL, -EINVAL);
64 
65  qm_gpio_reg_t *const controller = QM_GPIO[gpio];
66 
67  uint32_t mask = controller->gpio_intmask;
68  controller->gpio_intmask = 0xffffffff;
69 
70  controller->gpio_swporta_ddr = cfg->direction;
71  controller->gpio_inten = cfg->int_en;
72  controller->gpio_inttype_level = cfg->int_type;
73  controller->gpio_int_polarity = cfg->int_polarity;
74  controller->gpio_debounce = cfg->int_debounce;
75  controller->gpio_int_bothedge = cfg->int_bothedge;
76  controller->gpio_ls_sync |= ENABLE_PCLK;
77  callback[gpio] = cfg->callback;
78  callback_data[gpio] = cfg->callback_data;
79 
80  controller->gpio_intmask = mask;
81 
82  return 0;
83 }
84 
85 int qm_gpio_read_pin(const qm_gpio_t gpio, const uint8_t pin,
86  qm_gpio_state_t *const state)
87 {
88  QM_CHECK(gpio < QM_GPIO_NUM, -EINVAL);
89  QM_CHECK(pin <= QM_NUM_GPIO_PINS, -EINVAL);
90  QM_CHECK(state != NULL, -EINVAL);
91 
92  *state = ((QM_GPIO[gpio]->gpio_ext_porta) >> pin) & 1;
93 
94  return 0;
95 }
96 
97 int qm_gpio_set_pin(const qm_gpio_t gpio, const uint8_t pin)
98 {
99  QM_CHECK(gpio < QM_GPIO_NUM, -EINVAL);
100  QM_CHECK(pin <= QM_NUM_GPIO_PINS, -EINVAL);
101 
102  QM_GPIO[gpio]->gpio_swporta_dr |= (1 << pin);
103 
104  return 0;
105 }
106 
107 int qm_gpio_clear_pin(const qm_gpio_t gpio, const uint8_t pin)
108 {
109  QM_CHECK(gpio < QM_GPIO_NUM, -EINVAL);
110  QM_CHECK(pin <= QM_NUM_GPIO_PINS, -EINVAL);
111 
112  QM_GPIO[gpio]->gpio_swporta_dr &= ~(1 << pin);
113 
114  return 0;
115 }
116 
117 int qm_gpio_set_pin_state(const qm_gpio_t gpio, const uint8_t pin,
118  const qm_gpio_state_t state)
119 {
120  QM_CHECK(gpio < QM_GPIO_NUM, -EINVAL);
121  QM_CHECK(pin <= QM_NUM_GPIO_PINS, -EINVAL);
122  QM_CHECK(state < QM_GPIO_STATE_NUM, -EINVAL);
123 
124  uint32_t reg = QM_GPIO[gpio]->gpio_swporta_dr;
125  reg ^= (-state ^ reg) & (1 << pin);
126  QM_GPIO[gpio]->gpio_swporta_dr = reg;
127 
128  return 0;
129 }
130 
131 int qm_gpio_read_port(const qm_gpio_t gpio, uint32_t *const port)
132 {
133  QM_CHECK(gpio < QM_GPIO_NUM, -EINVAL);
134  QM_CHECK(port != NULL, -EINVAL);
135 
136  *port = QM_GPIO[gpio]->gpio_ext_porta;
137 
138  return 0;
139 }
140 
141 int qm_gpio_write_port(const qm_gpio_t gpio, const uint32_t val)
142 {
143  QM_CHECK(gpio < QM_GPIO_NUM, -EINVAL);
144 
145  QM_GPIO[gpio]->gpio_swporta_dr = val;
146 
147  return 0;
148 }
149 
150 #if (ENABLE_RESTORE_CONTEXT)
152 {
153  QM_CHECK(gpio < QM_GPIO_NUM, -EINVAL);
154  QM_CHECK(ctx != NULL, -EINVAL);
155 
156  qm_gpio_reg_t *const controller = QM_GPIO[gpio];
157 
158  if (gpio == QM_GPIO_0) {
159  ctx->gpio_swporta_dr = controller->gpio_swporta_dr;
160  ctx->gpio_swporta_ddr = controller->gpio_swporta_ddr;
161  ctx->gpio_swporta_ctl = controller->gpio_swporta_ctl;
162  ctx->gpio_inten = controller->gpio_inten;
163  ctx->gpio_intmask = controller->gpio_intmask;
164  ctx->gpio_inttype_level = controller->gpio_inttype_level;
165  ctx->gpio_int_polarity = controller->gpio_int_polarity;
166  ctx->gpio_debounce = controller->gpio_debounce;
167  ctx->gpio_ls_sync = controller->gpio_ls_sync;
168  ctx->gpio_int_bothedge = controller->gpio_int_bothedge;
169  }
170 
171  return 0;
172 }
173 
175  const qm_gpio_context_t *const ctx)
176 {
177  QM_CHECK(gpio < QM_GPIO_NUM, -EINVAL);
178  QM_CHECK(ctx != NULL, -EINVAL);
179 
180  qm_gpio_reg_t *const controller = QM_GPIO[gpio];
181 
182  if (gpio == QM_GPIO_0) {
183  controller->gpio_intmask = 0xffffffff;
184  controller->gpio_swporta_dr = ctx->gpio_swporta_dr;
185  controller->gpio_swporta_ddr = ctx->gpio_swporta_ddr;
186  controller->gpio_swporta_ctl = ctx->gpio_swporta_ctl;
187  controller->gpio_inten = ctx->gpio_inten;
188  controller->gpio_inttype_level = ctx->gpio_inttype_level;
189  controller->gpio_int_polarity = ctx->gpio_int_polarity;
190  controller->gpio_debounce = ctx->gpio_debounce;
191  controller->gpio_ls_sync = ctx->gpio_ls_sync;
192  controller->gpio_int_bothedge = ctx->gpio_int_bothedge;
193  controller->gpio_intmask = ctx->gpio_intmask;
194  }
195 
196  return 0;
197 }
198 #else
199 int qm_gpio_save_context(const qm_gpio_t gpio, qm_gpio_context_t *const ctx)
200 {
201  (void)gpio;
202  (void)ctx;
203 
204  return 0;
205 }
206 
207 int qm_gpio_restore_context(const qm_gpio_t gpio,
208  const qm_gpio_context_t *const ctx)
209 {
210  (void)gpio;
211  (void)ctx;
212 
213  return 0;
214 }
215 #endif /* ENABLE_RESTORE_CONTEXT */
QM_RW uint32_t gpio_inten
Interrupt Enable.
Definition: qm_soc_regs.h:1021
QM_ISR_DECLARE(qm_gpio_0_isr)
ISR for GPIO 0 interrupt.
Definition: qm_gpio.c:45
int qm_gpio_clear_pin(const qm_gpio_t gpio, const uint8_t pin)
Clear a single pin on a given GPIO port.
Definition: qm_gpio.c:107
void qm_power_soc_restore(void)
Restore system state after sleep or deep sleep.
Definition: power_states.c:402
uint32_t int_polarity
Interrupt polarity, 0b: low, 1b: high.
Definition: qm_gpio.h:36
uint32_t gpio_swporta_ddr
Port A Data Direction.
Definition: qm_soc_regs.h:1401
uint32_t direction
GPIO direction, 0b: input, 1b: output.
Definition: qm_gpio.h:33
uint32_t gpio_inttype_level
Interrupt Type.
Definition: qm_soc_regs.h:1405
int qm_gpio_read_pin(const qm_gpio_t gpio, const uint8_t pin, qm_gpio_state_t *const state)
Read the current state of a single pin on a given GPIO port.
Definition: qm_gpio.c:85
int qm_gpio_set_pin(const qm_gpio_t gpio, const uint8_t pin)
Set a single pin on a given GPIO port.
Definition: qm_gpio.c:97
int qm_gpio_write_port(const qm_gpio_t gpio, const uint32_t val)
Write a value to every pin on a GPIO port.
Definition: qm_gpio.c:141
qm_gpio_reg_t * qm_gpio[QM_GPIO_NUM]
GPIO register block.
Definition: qm_gpio.c:14
uint32_t gpio_ls_sync
Synchronization Level.
Definition: qm_soc_regs.h:1408
uint32_t gpio_intmask
Interrupt Mask.
Definition: qm_soc_regs.h:1404
QM_RW uint32_t gpio_swporta_ddr
Port A Data Direction.
Definition: qm_soc_regs.h:1019
uint32_t int_debounce
Interrupt debounce on/off.
Definition: qm_gpio.h:37
QM_RW uint32_t gpio_debounce
Debounce Enable.
Definition: qm_soc_regs.h:1027
void(* callback)(void *data, uint32_t int_status)
Transfer callback.
Definition: qm_gpio.h:46
uint32_t gpio_int_polarity
Interrupt Polarity.
Definition: qm_soc_regs.h:1406
QM_RW uint32_t gpio_swporta_dr
Port A Data.
Definition: qm_soc_regs.h:1018
uint32_t int_type
Interrupt type, 0b: level; 1b: edge.
Definition: qm_gpio.h:35
uint32_t int_bothedge
Interrupt on rising and falling edges.
Definition: qm_gpio.h:38
uint32_t gpio_int_bothedge
Interrupt both edge type.
Definition: qm_soc_regs.h:1409
int qm_gpio_save_context(const qm_gpio_t gpio, qm_gpio_context_t *const ctx)
Save GPIO context.
Definition: qm_gpio.c:151
QM_RW uint32_t gpio_swporta_ctl
Port A Data Source.
Definition: qm_soc_regs.h:1372
GPIO register map.
Definition: qm_soc_regs.h:1017
QM_RW uint32_t gpio_intmask
Interrupt Mask.
Definition: qm_soc_regs.h:1022
Number of GPIO states.
Definition: qm_gpio.h:24
int qm_gpio_set_pin_state(const qm_gpio_t gpio, const uint8_t pin, const qm_gpio_state_t state)
Set or clear a single GPIO pin using a state variable.
Definition: qm_gpio.c:117
QM_RW uint32_t gpio_int_polarity
Interrupt Polarity.
Definition: qm_soc_regs.h:1024
uint32_t gpio_inten
Interrupt Enable.
Definition: qm_soc_regs.h:1403
uint32_t int_en
Interrupt enable.
Definition: qm_gpio.h:34
qm_gpio_state_t
GPIO pin states.
Definition: qm_gpio.h:21
uint32_t gpio_swporta_dr
Port A Data.
Definition: qm_soc_regs.h:1400
GPIO context type.
Definition: qm_soc_regs.h:1399
qm_gpio_t
Number of GPIO controllers.
Definition: qm_soc_regs.h:1014
QM_RW uint32_t gpio_ls_sync
Synchronization Level.
Definition: qm_soc_regs.h:1031
uint32_t gpio_debounce
Debounce Enable.
Definition: qm_soc_regs.h:1407
int qm_gpio_read_port(const qm_gpio_t gpio, uint32_t *const port)
Read the value of every pin on a GPIO port.
Definition: qm_gpio.c:131
QM_RW uint32_t gpio_inttype_level
Interrupt Type.
Definition: qm_soc_regs.h:1023
int qm_gpio_restore_context(const qm_gpio_t gpio, const qm_gpio_context_t *const ctx)
Restore GPIO context.
Definition: qm_gpio.c:174
void * callback_data
Callback user data.
Definition: qm_gpio.h:47
GPIO port configuration type.
Definition: qm_gpio.h:32
uint32_t gpio_swporta_ctl
Port A Data Source.
Definition: qm_soc_regs.h:1402
int qm_gpio_set_config(const qm_gpio_t gpio, const qm_gpio_port_config_t *const cfg)
Set GPIO port configuration.
Definition: qm_gpio.c:59
QM_RW uint32_t gpio_int_bothedge
Interrupt both edge type.
Definition: qm_soc_regs.h:1033