summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c')
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c161
1 files changed, 79 insertions, 82 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
index 4f2bd9d931..097e81d7a3 100644
--- a/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
@@ -49,121 +49,86 @@ static struct spi_node mc13783_spi =
49 0, /* SPI clock - no wait states */ 49 0, /* SPI clock - no wait states */
50}; 50};
51 51
52static int mc13783_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)]; 52extern const struct mc13783_event_list mc13783_event_list;
53
54static int mc13783_thread_stack[3*DEFAULT_STACK_SIZE/sizeof(int)];
53static const char *mc13783_thread_name = "pmic"; 55static const char *mc13783_thread_name = "pmic";
54static struct wakeup mc13783_wake; 56static struct wakeup mc13783_wake;
57
58/* Tracking for which interrupts are enabled */
59static uint32_t pmic_int_enabled[2] =
60 { 0x00000000, 0x00000000 };
61
62static const unsigned char pmic_intm_regs[2] =
63 { MC13783_INTERRUPT_MASK0, MC13783_INTERRUPT_MASK1 };
64
65static const unsigned char pmic_ints_regs[2] =
66 { MC13783_INTERRUPT_STATUS0, MC13783_INTERRUPT_STATUS1 };
67
55#ifdef PMIC_DRIVER_CLOSE 68#ifdef PMIC_DRIVER_CLOSE
56static bool pmic_close = false; 69static bool pmic_close = false;
57static struct thread_entry *mc13783_thread_p = NULL; 70static struct thread_entry *mc13783_thread_p = NULL;
58#endif 71#endif
59 72
60/* The next two functions are rather target-specific but they'll just be left
61 * here for the moment */
62static void mc13783_interrupt_thread(void) 73static void mc13783_interrupt_thread(void)
63{ 74{
64 const unsigned char status_regs[2] =
65 {
66 MC13783_INTERRUPT_STATUS0,
67 MC13783_INTERRUPT_STATUS1,
68 };
69 uint32_t pending[2]; 75 uint32_t pending[2];
70 uint32_t value;
71
72 mc13783_read_regset(status_regs, pending, 2);
73 mc13783_write_regset(status_regs, pending, 2);
74
75 gpio_enable_event(MC13783_GPIO_NUM, MC13783_EVENT_ID);
76
77 if (pending[1] & MC13783_TODAI) /* only needs to be polled on startup */
78 mc13783_alarm_start();
79
80 /* Check initial states for events with a sense bit */
81 value = mc13783_read(MC13783_INTERRUPT_SENSE0);
82 usb_set_status(value & MC13783_USB4V4S);
83 set_charger_inserted(value & MC13783_CHGDETS);
84
85 value = mc13783_read(MC13783_INTERRUPT_SENSE1);
86 button_power_set_state((value & MC13783_ONOFD1S) == 0);
87#ifdef HAVE_HEADPHONE_DETECTION
88 set_headphones_inserted((value & MC13783_ONOFD2S) == 0);
89#endif
90 76
91 pending[0] = pending[1] = 0xffffff; 77 /* Enable mc13783 GPIO event */
92 mc13783_write_regset(status_regs, pending, 2); 78 gpio_enable_event(MC13783_EVENT_ID);
93 79
94 /* Enable desired PMIC interrupts - some are unmasked in the drivers that
95 * handle a specific task */
96 mc13783_clear(MC13783_INTERRUPT_MASK0, MC13783_CHGDETM);
97 mc13783_clear(MC13783_INTERRUPT_MASK1, MC13783_ONOFD1M |
98 MC13783_ONOFD2M);
99
100 while (1) 80 while (1)
101 { 81 {
82 const struct mc13783_event *event, *event_last;
83
102 wakeup_wait(&mc13783_wake, TIMEOUT_BLOCK); 84 wakeup_wait(&mc13783_wake, TIMEOUT_BLOCK);
103 85
104#ifdef PMIC_DRIVER_CLOSE 86#ifdef PMIC_DRIVER_CLOSE
105 if (pmic_close) 87 if (pmic_close)
106 { 88 break;
107 gpio_disable_event(MC13783_GPIO_NUM, MC13783_EVENT_ID);
108 return;
109 }
110#endif 89#endif
111 90
112 mc13783_read_regset(status_regs, pending, 2); 91 mc13783_read_regset(pmic_ints_regs, pending, 2);
113 mc13783_write_regset(status_regs, pending, 2);
114
115 if (pending[0])
116 {
117 /* Handle ...PENDING0 */
118
119 /* Handle interrupts without a sense bit */
120 if (pending[0] & MC13783_ADCDONEI)
121 adc_done();
122 92
123 /* Handle interrupts that have a sense bit that needs to 93 /* Only clear interrupts being dispatched */
124 * be checked */ 94 pending[0] &= pmic_int_enabled[0];
125 if (pending[0] & (MC13783_CHGDETI | MC13783_USB4V4I)) 95 pending[1] &= pmic_int_enabled[1];
126 {
127 value = mc13783_read(MC13783_INTERRUPT_SENSE0);
128 96
129 if (pending[0] & MC13783_CHGDETI) 97 mc13783_write_regset(pmic_ints_regs, pending, 2);
130 set_charger_inserted(value & MC13783_CHGDETS);
131 98
132 if (pending[0] & MC13783_USB4V4I) 99 event = mc13783_event_list.events;
133 usb_set_status(value & MC13783_USB4V4S); 100 event_last = event + mc13783_event_list.count;
134 }
135 }
136 101
137 if (pending[1]) 102 /* .count is surely expected to be > 0 */
103 do
138 { 104 {
139 /* Handle ...PENDING1 */ 105 enum mc13783_event_sets set = event->set;
140 106 uint32_t pnd = pending[set];
141 /* Handle interrupts without a sense bit */ 107 uint32_t mask = event->mask;
142 /* ... */
143 108
144 /* Handle interrupts that have a sense bit that needs to 109 if (pnd & mask)
145 * be checked */
146 if (pending[1] & (MC13783_ONOFD1I | MC13783_ONOFD2I))
147 { 110 {
148 value = mc13783_read(MC13783_INTERRUPT_SENSE1); 111 event->callback();
149 112 pnd &= ~mask;
150 if (pending[1] & MC13783_ONOFD1I) 113 pending[set] = pnd;
151 button_power_set_state((value & MC13783_ONOFD1S) == 0);
152#ifdef HAVE_HEADPHONE_DETECTION
153 if (pending[1] & MC13783_ONOFD2I)
154 set_headphones_inserted((value & MC13783_ONOFD2S) == 0);
155#endif
156 } 114 }
115
116 if ((pending[0] | pending[1]) == 0)
117 break; /* Teminate early if nothing more to service */
157 } 118 }
119 while (++event < event_last);
158 } 120 }
121
122#ifdef PMIC_DRIVER_CLOSE
123 gpio_disable_event(MC13783_EVENT_ID);
124#endif
159} 125}
160 126
161/* GPIO interrupt handler for mc13783 */ 127/* GPIO interrupt handler for mc13783 */
162int mc13783_event(void) 128void mc13783_event(void)
163{ 129{
164 MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE); 130 MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE);
165 wakeup_signal(&mc13783_wake); 131 wakeup_signal(&mc13783_wake);
166 return 1; /* Yes, it's handled */
167} 132}
168 133
169void mc13783_init(void) 134void mc13783_init(void)
@@ -174,8 +139,8 @@ void mc13783_init(void)
174 /* Enable the PMIC SPI module */ 139 /* Enable the PMIC SPI module */
175 spi_enable_module(&mc13783_spi); 140 spi_enable_module(&mc13783_spi);
176 141
177 /* Mask any PMIC interrupts for now - poll initial status in thread 142 /* Mask any PMIC interrupts for now - modules will enable them as
178 * and enable them there */ 143 * required */
179 mc13783_write(MC13783_INTERRUPT_MASK0, 0xffffff); 144 mc13783_write(MC13783_INTERRUPT_MASK0, 0xffffff);
180 mc13783_write(MC13783_INTERRUPT_MASK1, 0xffffff); 145 mc13783_write(MC13783_INTERRUPT_MASK1, 0xffffff);
181 146
@@ -203,7 +168,39 @@ void mc13783_close(void)
203 wakeup_signal(&mc13783_wake); 168 wakeup_signal(&mc13783_wake);
204 thread_wait(thread); 169 thread_wait(thread);
205} 170}
206#endif 171#endif /* PMIC_DRIVER_CLOSE */
172
173bool mc13783_enable_event(enum mc13783_event_ids id)
174{
175 const struct mc13783_event * const event =
176 &mc13783_event_list.events[id];
177 int set = event->set;
178 uint32_t mask = event->mask;
179
180 spi_lock(&mc13783_spi);
181
182 pmic_int_enabled[set] |= mask;
183 mc13783_clear(pmic_intm_regs[set], mask);
184
185 spi_unlock(&mc13783_spi);
186
187 return true;
188}
189
190void mc13783_disable_event(enum mc13783_event_ids id)
191{
192 const struct mc13783_event * const event =
193 &mc13783_event_list.events[id];
194 int set = event->set;
195 uint32_t mask = event->mask;
196
197 spi_lock(&mc13783_spi);
198
199 pmic_int_enabled[set] &= ~mask;
200 mc13783_set(pmic_intm_regs[set], mask);
201
202 spi_unlock(&mc13783_spi);
203}
207 204
208uint32_t mc13783_set(unsigned address, uint32_t bits) 205uint32_t mc13783_set(unsigned address, uint32_t bits)
209{ 206{