diff options
Diffstat (limited to 'firmware/target/mips/ingenic_x1000/gpio-x1000.c')
-rw-r--r-- | firmware/target/mips/ingenic_x1000/gpio-x1000.c | 88 |
1 files changed, 71 insertions, 17 deletions
diff --git a/firmware/target/mips/ingenic_x1000/gpio-x1000.c b/firmware/target/mips/ingenic_x1000/gpio-x1000.c index 40e4c5e631..14195359df 100644 --- a/firmware/target/mips/ingenic_x1000/gpio-x1000.c +++ b/firmware/target/mips/ingenic_x1000/gpio-x1000.c | |||
@@ -20,37 +20,91 @@ | |||
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | 21 | ||
22 | #include "gpio-x1000.h" | 22 | #include "gpio-x1000.h" |
23 | #include "kernel.h" | 23 | |
24 | const struct gpio_setting gpio_settings[PIN_COUNT] = { | ||
25 | #define DEFINE_GPIO(_name, _gpio, _func) \ | ||
26 | {.gpio = _gpio, .func = _func}, | ||
27 | #define DEFINE_PINGROUP(...) | ||
28 | #include "gpio-target.h" | ||
29 | #undef DEFINE_GPIO | ||
30 | #undef DEFINE_PINGROUP | ||
31 | }; | ||
32 | |||
33 | const struct pingroup_setting pingroup_settings[PINGROUP_COUNT] = { | ||
34 | #define DEFINE_GPIO(...) | ||
35 | #define DEFINE_PINGROUP(_name, _port, _pins, _func) \ | ||
36 | {.port = _port, .pins = _pins, .func = _func}, | ||
37 | #include "gpio-target.h" | ||
38 | #undef DEFINE_GPIO | ||
39 | #undef DEFINE_PINGROUP | ||
40 | }; | ||
41 | |||
42 | const char* const gpio_names[PIN_COUNT] = { | ||
43 | #define DEFINE_GPIO(_name, ...) #_name, | ||
44 | #define DEFINE_PINGROUP(...) | ||
45 | #include "gpio-target.h" | ||
46 | #undef DEFINE_GPIO | ||
47 | #undef DEFINE_PINGROUP | ||
48 | }; | ||
49 | |||
50 | const char* const pingroup_names[PINGROUP_COUNT] = { | ||
51 | #define DEFINE_GPIO(...) | ||
52 | #define DEFINE_PINGROUP(_name, ...) #_name, | ||
53 | #include "gpio-target.h" | ||
54 | #undef DEFINE_GPIO | ||
55 | #undef DEFINE_PINGROUP | ||
56 | }; | ||
24 | 57 | ||
25 | void gpio_init(void) | 58 | void gpio_init(void) |
26 | { | 59 | { |
60 | /* Apply all initial GPIO settings */ | ||
61 | for(int i = 0; i < PINGROUP_COUNT; ++i) { | ||
62 | const struct pingroup_setting* d = &pingroup_settings[i]; | ||
63 | if(d->pins != 0) | ||
64 | gpioz_configure(d->port, d->pins, d->func); | ||
65 | } | ||
66 | |||
67 | for(int i = 0; i < PIN_COUNT; ++i) { | ||
68 | const struct gpio_setting* d = &gpio_settings[i]; | ||
69 | if(d->gpio != GPIO_NONE) | ||
70 | gpioz_configure(GPION_PORT(d->gpio), GPION_MASK(d->gpio), d->func); | ||
71 | } | ||
72 | |||
27 | /* Any GPIO pins left in an IRQ trigger state need to be switched off, | 73 | /* Any GPIO pins left in an IRQ trigger state need to be switched off, |
28 | * because the drivers won't be ready to handle the interrupts until they | 74 | * because the drivers won't be ready to handle the interrupts until they |
29 | * get initialized later in the boot. */ | 75 | * get initialized later in the boot. */ |
30 | for(int i = 0; i < 4; ++i) { | 76 | for(int i = 0; i < 4; ++i) { |
31 | uint32_t intbits = REG_GPIO_INT(i); | 77 | uint32_t intbits = REG_GPIO_INT(i); |
32 | if(intbits) { | 78 | if(intbits) { |
33 | gpio_config(i, intbits, GPIO_INPUT); | 79 | gpioz_configure(i, intbits, GPIOF_INPUT); |
34 | jz_clr(GPIO_FLAG(i), intbits); | 80 | jz_clr(GPIO_FLAG(i), intbits); |
35 | } | 81 | } |
36 | } | 82 | } |
37 | } | 83 | } |
38 | 84 | ||
39 | void gpio_config(int port, unsigned pinmask, int func) | 85 | void gpioz_configure(int port, uint32_t pins, int func) |
40 | { | 86 | { |
41 | unsigned intr = REG_GPIO_INT(port); | 87 | uint32_t intr = REG_GPIO_INT(port); |
42 | unsigned mask = REG_GPIO_MSK(port); | 88 | uint32_t mask = REG_GPIO_MSK(port); |
43 | unsigned pat1 = REG_GPIO_PAT1(port); | 89 | uint32_t pat1 = REG_GPIO_PAT1(port); |
44 | unsigned pat0 = REG_GPIO_PAT0(port); | 90 | uint32_t pat0 = REG_GPIO_PAT0(port); |
45 | 91 | ||
46 | if(func & 8) jz_set(GPIO_INT(GPIO_Z), (intr & pinmask) ^ pinmask); | 92 | /* Note: GPIO Z has _only_ set and clear registers, which are used to |
47 | else jz_clr(GPIO_INT(GPIO_Z), (~intr & pinmask) ^ pinmask); | 93 | * atomically manipulate the selected GPIO port when we write GID2LD. |
48 | if(func & 4) jz_set(GPIO_MSK(GPIO_Z), (mask & pinmask) ^ pinmask); | 94 | * So there's not really any direct setting or clearing going on here... |
49 | else jz_clr(GPIO_MSK(GPIO_Z), (~mask & pinmask) ^ pinmask); | 95 | */ |
50 | if(func & 2) jz_set(GPIO_PAT1(GPIO_Z), (pat1 & pinmask) ^ pinmask); | 96 | if(func & GPIO_F_INT) jz_set(GPIO_INT(GPIO_Z), (intr & pins) ^ pins); |
51 | else jz_clr(GPIO_PAT1(GPIO_Z), (~pat1 & pinmask) ^ pinmask); | 97 | else jz_clr(GPIO_INT(GPIO_Z), (~intr & pins) ^ pins); |
52 | if(func & 1) jz_set(GPIO_PAT0(GPIO_Z), (pat0 & pinmask) ^ pinmask); | 98 | if(func & GPIO_F_MASK) jz_set(GPIO_MSK(GPIO_Z), (mask & pins) ^ pins); |
53 | else jz_clr(GPIO_PAT0(GPIO_Z), (~pat0 & pinmask) ^ pinmask); | 99 | else jz_clr(GPIO_MSK(GPIO_Z), (~mask & pins) ^ pins); |
100 | if(func & GPIO_F_PAT1) jz_set(GPIO_PAT1(GPIO_Z), (pat1 & pins) ^ pins); | ||
101 | else jz_clr(GPIO_PAT1(GPIO_Z), (~pat1 & pins) ^ pins); | ||
102 | if(func & GPIO_F_PAT0) jz_set(GPIO_PAT0(GPIO_Z), (pat0 & pins) ^ pins); | ||
103 | else jz_clr(GPIO_PAT0(GPIO_Z), (~pat0 & pins) ^ pins); | ||
54 | REG_GPIO_Z_GID2LD = port; | 104 | REG_GPIO_Z_GID2LD = port; |
55 | gpio_set_pull(port, pinmask, func & 16); | 105 | |
106 | if(func & GPIO_F_PULL) | ||
107 | jz_set(GPIO_PULL(port), pins); | ||
108 | else | ||
109 | jz_clr(GPIO_PULL(port), pins); | ||
56 | } | 110 | } |