diff options
Diffstat (limited to 'firmware/target/arm/s5l8702/gpio-s5l8702.c')
-rw-r--r-- | firmware/target/arm/s5l8702/gpio-s5l8702.c | 193 |
1 files changed, 93 insertions, 100 deletions
diff --git a/firmware/target/arm/s5l8702/gpio-s5l8702.c b/firmware/target/arm/s5l8702/gpio-s5l8702.c index 3b2c02861f..0f7a029fb6 100644 --- a/firmware/target/arm/s5l8702/gpio-s5l8702.c +++ b/firmware/target/arm/s5l8702/gpio-s5l8702.c | |||
@@ -23,11 +23,30 @@ | |||
23 | 23 | ||
24 | #include "config.h" | 24 | #include "config.h" |
25 | #include "system.h" | 25 | #include "system.h" |
26 | #include "gpio-s5l8702.h" | ||
27 | #include "panic.h" | 26 | #include "panic.h" |
28 | 27 | ||
28 | #include "gpio-s5l8702.h" | ||
29 | |||
30 | |||
29 | int rec_hw_ver; | 31 | int rec_hw_ver; |
30 | 32 | ||
33 | static uint32_t gpio_data[] = | ||
34 | { | ||
35 | 0x5322222F, 0xEEEEEE00, 0x2332EEEE, 0x3333E222, | ||
36 | 0x33333333, 0x33333333, 0x3F000E33, 0xEEEEEEEE, | ||
37 | 0xEEEEEEEE, 0xEEEEEEEE, 0xE0EEEEEE, 0xEE00EE0E, | ||
38 | 0xEEEE0EEE, 0xEEEEEEEE, 0xEE2222EE, 0xEEEE0EEE | ||
39 | }; | ||
40 | |||
41 | void INIT_ATTR gpio_preinit(void) | ||
42 | { | ||
43 | for (int i = 0; i < 16; i++) { | ||
44 | PCON(i) = gpio_data[i]; | ||
45 | PUNB(i) = 0; | ||
46 | PUNC(i) = 0; | ||
47 | } | ||
48 | } | ||
49 | |||
31 | void INIT_ATTR gpio_init(void) | 50 | void INIT_ATTR gpio_init(void) |
32 | { | 51 | { |
33 | /* Capture hardware versions: | 52 | /* Capture hardware versions: |
@@ -44,9 +63,8 @@ void INIT_ATTR gpio_init(void) | |||
44 | */ | 63 | */ |
45 | GPIOCMD = 0xe0700; | 64 | GPIOCMD = 0xe0700; |
46 | rec_hw_ver = (PDAT(14) & (1 << 7)) ? 0 : 1; | 65 | rec_hw_ver = (PDAT(14) & (1 << 7)) ? 0 : 1; |
66 | GPIOCMD = 0xe070e; /* restore default configuration */ | ||
47 | 67 | ||
48 | /* default GPIO configuration */ | ||
49 | GPIOCMD = 0xe070e; | ||
50 | if (rec_hw_ver == 0) { | 68 | if (rec_hw_ver == 0) { |
51 | GPIOCMD = 0xe060e; | 69 | GPIOCMD = 0xe060e; |
52 | } | 70 | } |
@@ -56,31 +74,9 @@ void INIT_ATTR gpio_init(void) | |||
56 | GPIOCMD = 0xe0600; | 74 | GPIOCMD = 0xe0600; |
57 | PUNB(14) |= (1 << 6); | 75 | PUNB(14) |= (1 << 6); |
58 | } | 76 | } |
59 | |||
60 | /* TODO: initialize GPIO ports for minimum power consumption */ | ||
61 | } | 77 | } |
62 | 78 | ||
63 | |||
64 | /* | ||
65 | * XXX: disabled, not used and never tested! | ||
66 | */ | ||
67 | #if 0 | 79 | #if 0 |
68 | /* handlers list */ | ||
69 | #define GPIOIC_MAX_HANDLERS 2 | ||
70 | |||
71 | #define FLAG_TYPE_LEVEL (1 << 0) | ||
72 | #define FLAG_AUTOFLIP (1 << 1) | ||
73 | |||
74 | struct gpio_handler { | ||
75 | int gpio_n; | ||
76 | void (*isr)(void); | ||
77 | int flags; | ||
78 | }; | ||
79 | static struct gpio_handler l_handlers[GPIOIC_MAX_HANDLERS] IDATA_ATTR; | ||
80 | static int n_handlers = 0; | ||
81 | |||
82 | |||
83 | /* API */ | ||
84 | uint32_t gpio_group_get(int group) | 80 | uint32_t gpio_group_get(int group) |
85 | { | 81 | { |
86 | uint32_t pcon = PCON(group); | 82 | uint32_t pcon = PCON(group); |
@@ -103,131 +99,128 @@ void gpio_group_set(int group, uint32_t mask, uint32_t cfg) | |||
103 | { | 99 | { |
104 | PCON(group) = (PCON(group) & ~mask) | (cfg & mask); | 100 | PCON(group) = (PCON(group) & ~mask) | (cfg & mask); |
105 | } | 101 | } |
102 | #endif | ||
106 | 103 | ||
107 | void gpio_int_register(int gpio_n, void *isr, int type, int level, int autoflip) | ||
108 | { | ||
109 | if (n_handlers >= GPIOIC_MAX_HANDLERS) | ||
110 | panicf("gpio_int_register(): too many handlers!"); | ||
111 | 104 | ||
112 | int group = IC_GROUP(gpio_n); | 105 | /* |
113 | int index = IC_IDX(gpio_n); | 106 | * eINT API |
107 | */ | ||
108 | #ifndef EINT_MAX_HANDLERS | ||
109 | #define EINT_MAX_HANDLERS 1 | ||
110 | #endif | ||
111 | static struct eint_handler* l_handlers[EINT_MAX_HANDLERS] IDATA_ATTR; | ||
114 | 112 | ||
113 | void INIT_ATTR eint_init(void) | ||
114 | { | ||
115 | /* disable external interrupts */ | ||
116 | for (int i = 0; i < EIC_N_GROUPS; i++) | ||
117 | EIC_INTEN(i) = 0; | ||
118 | } | ||
119 | |||
120 | void eint_register(struct eint_handler *h) | ||
121 | { | ||
122 | int i; | ||
115 | int flags = disable_irq_save(); | 123 | int flags = disable_irq_save(); |
116 | 124 | ||
117 | /* fill handler struct */ | 125 | for (i = 0; i < EINT_MAX_HANDLERS; i++) { |
118 | struct gpio_handler *handler = &l_handlers[n_handlers++]; | 126 | if (!l_handlers[i]) { |
127 | int group = EIC_GROUP(h->gpio_n); | ||
128 | int index = EIC_INDEX(h->gpio_n); | ||
119 | 129 | ||
120 | handler->gpio_n = gpio_n; | 130 | EIC_INTTYPE(group) |= (h->type << index); |
121 | handler->isr = isr; | 131 | EIC_INTLEVEL(group) |= (h->level << index); |
122 | handler->flags = (type ? FLAG_TYPE_LEVEL : 0) | 132 | EIC_INTSTAT(group) = (1 << index); /* clear */ |
123 | | (autoflip ? FLAG_AUTOFLIP : 0); | 133 | EIC_INTEN(group) |= (1 << index); /* enable */ |
124 | 134 | ||
125 | /* configure */ | 135 | /* XXX: valid only for gpio_n = 0..127 (IRQ_EXT0..IRQ_EXT3) */ |
126 | GPIOIC_INTTYPE(group) |= | 136 | VIC0INTENABLE = 1 << (IRQ_EXT0 + (h->gpio_n >> 5)); |
127 | (type ? GPIOIC_INTTYPE_LEVEL : GPIOIC_INTTYPE_EDGE) << index; | 137 | |
128 | GPIOIC_INTLEVEL(group) |= | 138 | l_handlers[i] = h; |
129 | (level ? GPIOIC_INTLEVEL_HIGH : GPIOIC_INTLEVEL_LOW) << index; | 139 | break; |
140 | } | ||
141 | } | ||
130 | 142 | ||
131 | restore_irq(flags); | 143 | restore_irq(flags); |
132 | 144 | ||
133 | /* XXX: valid only for gpio_n = 0..127 (IRQ_EXT0..IRQ_EXT3) */ | 145 | if (i == EINT_MAX_HANDLERS) |
134 | VIC0INTENABLE = 1 << (IRQ_EXT0 + (gpio_n >> 5)); | 146 | panicf("%s(): too many handlers!", __func__); |
135 | } | 147 | } |
136 | 148 | ||
137 | void gpio_int_enable(int gpio_n) | 149 | void eint_unregister(struct eint_handler *h) |
138 | { | 150 | { |
139 | int group = IC_GROUP(gpio_n); | ||
140 | uint32_t bit_mask = 1 << IC_IDX(gpio_n); | ||
141 | |||
142 | int flags = disable_irq_save(); | 151 | int flags = disable_irq_save(); |
143 | GPIOIC_INTSTAT(group) = bit_mask; /* clear */ | ||
144 | GPIOIC_INTEN(group) |= bit_mask; /* enable */ | ||
145 | restore_irq(flags); | ||
146 | } | ||
147 | 152 | ||
148 | void gpio_int_disable(int gpio_n) | 153 | for (int i = 0; i < EINT_MAX_HANDLERS; i++) { |
149 | { | 154 | if (l_handlers[i] == h) { |
150 | int group = IC_GROUP(gpio_n); | 155 | int group = EIC_GROUP(h->gpio_n); |
151 | uint32_t bit_mask = 1 << IC_IDX(gpio_n); | 156 | int index = EIC_INDEX(h->gpio_n); |
157 | |||
158 | EIC_INTEN(group) &= ~(1 << index); /* disable */ | ||
159 | |||
160 | /* XXX: valid only for gpio_n = 0..127 (IRQ_EXT0..IRQ_EXT3) */ | ||
161 | if (EIC_INTEN(group) == 0) | ||
162 | VIC0INTENCLEAR = 1 << (IRQ_EXT0 + (h->gpio_n >> 5)); | ||
163 | |||
164 | l_handlers[i] = NULL; | ||
165 | break; | ||
166 | } | ||
167 | } | ||
152 | 168 | ||
153 | int flags = disable_irq_save(); | ||
154 | GPIOIC_INTEN(group) &= ~bit_mask; /* disable */ | ||
155 | GPIOIC_INTSTAT(group) = bit_mask; /* clear */ | ||
156 | restore_irq(flags); | 169 | restore_irq(flags); |
157 | } | 170 | } |
158 | 171 | ||
159 | |||
160 | /* ISR */ | 172 | /* ISR */ |
161 | void ICODE_ATTR gpio_handler(int group) | 173 | void ICODE_ATTR eint_handler(int group) |
162 | { | 174 | { |
163 | int i; | 175 | int i; |
164 | struct gpio_handler *handler; | 176 | uint32_t ints; |
165 | uint32_t ints, bit_mask; | ||
166 | 177 | ||
167 | ints = GPIOIC_INTSTAT(group) & GPIOIC_INTEN(group); | 178 | ints = EIC_INTSTAT(group) & EIC_INTEN(group); |
168 | 179 | ||
169 | for (i = 0; i < n_handlers; i++) { | 180 | for (i = 0; i < EINT_MAX_HANDLERS; i++) { |
170 | handler = &l_handlers[i]; | 181 | struct eint_handler *h = l_handlers[i]; |
171 | 182 | ||
172 | if (IC_GROUP(handler->gpio_n) != group) | 183 | if (!h || (EIC_GROUP(h->gpio_n) != group)) |
173 | continue; | 184 | continue; |
174 | 185 | ||
175 | bit_mask = 1 << IC_IDX(handler->gpio_n); | 186 | uint32_t bit = 1 << EIC_INDEX(h->gpio_n); |
176 | 187 | ||
177 | if (ints & bit_mask) { | 188 | if (ints & bit) { |
178 | if ((handler->flags & FLAG_TYPE_LEVEL) == 0) | 189 | /* Clear INTTYPE_EDGE interrupt, to clear INTTYPE_LEVEL |
179 | GPIOIC_INTSTAT(group) = bit_mask; /* clear */ | 190 | interrupts the source (line level) must be "cleared" */ |
191 | if (h->type == EIC_INTTYPE_EDGE) | ||
192 | EIC_INTSTAT(group) = bit; /* clear */ | ||
180 | 193 | ||
181 | if (handler->flags & FLAG_AUTOFLIP) | 194 | if (h->autoflip) |
182 | GPIOIC_INTLEVEL(group) ^= bit_mask; /* swap level */ | 195 | EIC_INTLEVEL(group) ^= bit; /* swap level */ |
183 | 196 | ||
184 | if (handler->isr) | 197 | if (h->isr) |
185 | handler->isr(); /* exec GPIO handler */ | 198 | h->isr(h); /* exec GPIO handler */ |
186 | |||
187 | GPIOIC_INTSTAT(group) = bit_mask; /* clear */ | ||
188 | } | 199 | } |
189 | } | 200 | } |
190 | } | 201 | } |
191 | 202 | ||
192 | void ICODE_ATTR INT_EXT0(void) | 203 | void ICODE_ATTR INT_EXT0(void) |
193 | { | 204 | { |
194 | gpio_handler(6); | 205 | eint_handler(6); |
195 | } | 206 | } |
196 | 207 | ||
197 | void ICODE_ATTR INT_EXT1(void) | 208 | void ICODE_ATTR INT_EXT1(void) |
198 | { | 209 | { |
199 | gpio_handler(5); | 210 | eint_handler(5); |
200 | } | 211 | } |
201 | 212 | ||
202 | void ICODE_ATTR INT_EXT2(void) | 213 | void ICODE_ATTR INT_EXT2(void) |
203 | { | 214 | { |
204 | gpio_handler(4); | 215 | eint_handler(4); |
205 | } | 216 | } |
206 | 217 | ||
207 | void ICODE_ATTR INT_EXT3(void) | 218 | void ICODE_ATTR INT_EXT3(void) |
208 | { | 219 | { |
209 | gpio_handler(3); | 220 | eint_handler(3); |
210 | } | 221 | } |
211 | 222 | ||
212 | void ICODE_ATTR INT_EXT6(void) | 223 | void ICODE_ATTR INT_EXT6(void) |
213 | { | 224 | { |
214 | gpio_handler(0); | 225 | eint_handler(0); |
215 | } | ||
216 | #endif | ||
217 | |||
218 | static uint32_t gpio_data[16] = | ||
219 | { | ||
220 | 0x5322222F, 0xEEEEEE00, 0x2332EEEE, 0x3333E222, | ||
221 | 0x33333333, 0x33333333, 0x3F000E33, 0xEEEEEEEE, | ||
222 | 0xEEEEEEEE, 0xEEEEEEEE, 0xE0EEEEEE, 0xEE00EE0E, | ||
223 | 0xEEEE0EEE, 0xEEEEEEEE, 0xEE2222EE, 0xEEEE0EEE | ||
224 | }; | ||
225 | |||
226 | void gpio_preinit(void) | ||
227 | { | ||
228 | for (int i = 0; i < 16; i++) { | ||
229 | PCON(i) = gpio_data[i]; | ||
230 | PUNB(i) = 0; | ||
231 | PUNC(i) = 0; | ||
232 | } | ||
233 | } | 226 | } |