38
38
#include "clkman_regs.h"
39
39
#include "ioman_regs.h"
40
40
#include "rtc_regs.h"
41
+ #include "usb_regs.h"
41
42
#include "wait_api.h"
42
43
43
44
#define REVISION_A3 2
44
45
#define REVISION_A4 3
45
46
47
+ // USB state to be restored upon wakeup
48
+ typedef struct {
49
+ uint32_t dev_cn ;
50
+ uint32_t dev_inten ;
51
+ uint32_t ep_base ;
52
+ uint32_t ep [MXC_USB_NUM_EP ];
53
+ } usb_state_t ;
54
+
46
55
static mxc_uart_regs_t * stdio_uart = (mxc_uart_regs_t * )STDIO_UART ;
56
+ static int restore_usb ;
57
+ static usb_state_t usb_state ;
47
58
48
59
void sleep (void )
49
60
{
@@ -54,28 +65,79 @@ void sleep(void)
54
65
__WFI ();
55
66
}
56
67
68
+ static void usb_sleep (void )
69
+ {
70
+ int i ;
71
+
72
+ if (MXC_USB -> cn & MXC_F_USB_CN_USB_EN ) {
73
+ // The USB module will not survive Deep Sleep.
74
+
75
+ // Save the USB state to restore it upon wakeup
76
+ usb_state .dev_cn = MXC_USB -> dev_cn ;
77
+ usb_state .dev_inten = MXC_USB -> dev_inten ;
78
+ usb_state .ep_base = MXC_USB -> ep_base ;
79
+ for (i = 0 ; i < MXC_USB_NUM_EP ; i ++ ) {
80
+ usb_state .ep [i ] = MXC_USB -> ep [i ] & (MXC_F_USB_EP_DIR | MXC_F_USB_EP_BUF2 | MXC_F_USB_EP_INT_EN | MXC_F_USB_EP_NAK_EN );
81
+ }
82
+ restore_usb = 1 ;
83
+
84
+ // Shut down the USB module.
85
+ MXC_USB -> dev_inten = 0 ;
86
+ MXC_USB -> dev_cn = 0 ;
87
+ MXC_USB -> cn = 0 ;
88
+ restore_usb = 1 ; // USB should be restored upon wakeup
89
+ }
90
+ else {
91
+ restore_usb = 0 ;
92
+ }
93
+ }
94
+
95
+ // Restore the USB module state.
96
+ static void usb_wakeup (void )
97
+ {
98
+ int i ;
99
+
100
+ if (restore_usb ) {
101
+ MXC_USB -> cn = MXC_F_USB_CN_USB_EN ;
102
+ MXC_USB -> dev_cn = MXC_F_USB_DEV_CN_URST ;
103
+ MXC_USB -> dev_cn = 0 ;
104
+ for (i = 0 ; i < MXC_USB_NUM_EP ; i ++ ) {
105
+ MXC_USB -> ep [i ] = usb_state .ep [i ];
106
+ }
107
+ MXC_USB -> ep_base = usb_state .ep_base ;
108
+ MXC_USB -> dev_cn = usb_state .dev_cn ;
109
+ MXC_USB -> dev_inten = usb_state .dev_inten ;
110
+ restore_usb = 0 ;
111
+ }
112
+ }
113
+
57
114
// Low-power stop mode
58
115
void deepsleep (void )
59
116
{
60
- /* Deep Sleep is not yet supported. */
61
- sleep ();
62
-
63
- #if 0
64
117
unsigned int part_rev = MXC_PWRMAN -> mask_id0 & MXC_F_PWRMAN_MASK_ID0_REVISION_ID ;
65
118
66
- // Deep sleep is not working properly on Revisions A3 and earlier
119
+ // Deep Sleep is not working properly on Revisions A3 and earlier
67
120
if (part_rev <= REVISION_A3 ) {
68
121
sleep ();
69
122
return ;
70
123
}
71
124
72
125
// Wait for all STDIO characters to be sent. The UART clock will stop.
73
- while ( (((stdio_uart -> tx_fifo_ctrl & MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY )
74
- >> MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY_POS ) > 0 ) ||
75
- (!(stdio_uart -> intfl & MXC_F_UART_INTFL_TX_DONE )) );
126
+ while ((stdio_uart -> tx_fifo_ctrl & MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY ) ||
127
+ !(stdio_uart -> intfl & MXC_F_UART_INTFL_TX_DONE ));
76
128
77
129
__disable_irq ();
78
130
131
+ // Do not enter Deep Sleep if connected to VBUS
132
+ if (MXC_USB -> dev_intfl & MXC_F_USB_DEV_INTFL_VBUS_ST ) {
133
+ __enable_irq ();
134
+ sleep ();
135
+ return ;
136
+ }
137
+
138
+ // The USB module will not survive Deep Sleep. Shut it down.
139
+ usb_sleep ();
140
+
79
141
// Make sure RTC is not pending before sleeping, if its still synchronizing
80
142
// we might not wake up.
81
143
while (MXC_RTCTMR -> ctrl & MXC_F_RTC_CTRL_PENDING );
@@ -104,17 +166,20 @@ void deepsleep(void)
104
166
MXC_PWRSEQ -> msk_flags |= MXC_F_PWRSEQ_MSK_FLAGS_PWR_TVDD12_RST_BAD ;
105
167
MXC_PWRSEQ -> reg0 &= ~(MXC_F_PWRSEQ_REG0_PWR_SVMTVDD12EN_RUN );
106
168
MXC_PWRSEQ -> reg0 |= MXC_F_PWRSEQ_REG0_PWR_SVMTVDD12EN_RUN ;
107
- MXC_PWRSEQ -> msk_flags &= ~( MXC_F_PWRSEQ_MSK_FLAGS_PWR_TVDD12_RST_BAD ) ;
169
+ MXC_PWRSEQ -> msk_flags &= ~MXC_F_PWRSEQ_MSK_FLAGS_PWR_TVDD12_RST_BAD ;
108
170
}
109
171
110
172
// Enable Retention controller
111
173
MXC_PWRSEQ -> retn_ctrl0 |= MXC_F_PWRSEQ_RETN_CTRL0_RETN_CTRL_EN ;
112
174
175
+ // Clear the firstboot bit, which is generated by a POR event and locks out LPx modes
176
+ MXC_PWRSEQ -> reg0 &= ~MXC_F_PWRSEQ_REG0_PWR_FIRST_BOOT ;
177
+
113
178
// Freeze GPIO using MBUS so that it doesn't flail while digital core is asleep
114
179
MXC_PWRSEQ -> reg1 |= MXC_F_PWRSEQ_REG1_PWR_MBUS_GATE ;
115
180
116
181
// Dummy read to make sure SSB writes are complete
117
- if ( MXC_PWRSEQ -> reg0 & MXC_F_PWRSEQ_REG0_PWR_SYS_REBOOT ) {}
182
+ MXC_PWRSEQ -> reg0 ;
118
183
119
184
if (part_rev == REVISION_A4 ) {
120
185
// Note: ARM deep-sleep requires a specific sequence to clear event latches,
@@ -134,7 +199,9 @@ void deepsleep(void)
134
199
// We'll wakeup here ...
135
200
136
201
// Unfreeze the GPIO by clearing MBUS_GATE
137
- MXC_PWRSEQ -> reg1 &= ~(MXC_F_PWRSEQ_REG1_PWR_MBUS_GATE );
202
+ MXC_PWRSEQ -> reg1 &= ~MXC_F_PWRSEQ_REG1_PWR_MBUS_GATE ;
203
+
204
+ usb_wakeup ();
138
205
139
206
// Clear power sequencer event flags (write-1-to-clear)
140
207
// RTC and GPIO flags are cleared in their interrupts handlers
@@ -153,5 +220,4 @@ void deepsleep(void)
153
220
MXC_F_PWRSEQ_FLAGS_PWR_TVDD12_BAD );
154
221
155
222
__enable_irq ();
156
- #endif
157
223
}
0 commit comments