summaryrefslogtreecommitdiff
path: root/rbutil/mkimxboot/dualboot/dualboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'rbutil/mkimxboot/dualboot/dualboot.c')
-rw-r--r--rbutil/mkimxboot/dualboot/dualboot.c64
1 files changed, 61 insertions, 3 deletions
diff --git a/rbutil/mkimxboot/dualboot/dualboot.c b/rbutil/mkimxboot/dualboot/dualboot.c
index f75673efbe..3cca59bb8a 100644
--- a/rbutil/mkimxboot/dualboot/dualboot.c
+++ b/rbutil/mkimxboot/dualboot/dualboot.c
@@ -20,6 +20,8 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21#include "regs-pinctrl.h" 21#include "regs-pinctrl.h"
22#include "regs-power.h" 22#include "regs-power.h"
23#include "regs-lradc.h"
24#include "regs-digctl.h"
23 25
24#define BOOT_ROM_CONTINUE 0 /* continue boot */ 26#define BOOT_ROM_CONTINUE 0 /* continue boot */
25#define BOOT_ROM_SECTION 1 /* switch to new section *result_id */ 27#define BOOT_ROM_SECTION 1 /* switch to new section *result_id */
@@ -59,6 +61,28 @@ static inline int __attribute__((always_inline)) read_pswitch(void)
59#endif 61#endif
60} 62}
61 63
64/* only works for channels <=7, always divide by 2, never accumulates */
65static inline void __attribute__((always_inline)) setup_lradc(int src)
66{
67 BF_CLR(LRADC_CTRL0, SFTRST);
68 BF_CLR(LRADC_CTRL0, CLKGATE);
69 /* don't bother changing the source, we are early enough at boot so that
70 * channel x is mapped to source x */
71 HW_LRADC_CHn_CLR(src) = BM_OR2(LRADC_CHn, NUM_SAMPLES, ACCUMULATE);
72 BF_SETV(LRADC_CTRL2, DIVIDE_BY_TWO, 1 << src);
73}
74
75#define BP_LRADC_CTRL1_LRADCx_IRQ(x) (x)
76#define BM_LRADC_CTRL1_LRADCx_IRQ(x) (1 << (x))
77
78static inline int __attribute__((always_inline)) read_lradc(int src)
79{
80 BF_CLR(LRADC_CTRL1, LRADCx_IRQ(src));
81 BF_SETV(LRADC_CTRL0, SCHEDULE, 1 << src);
82 while(!BF_RD(LRADC_CTRL1, LRADCx_IRQ(src)));
83 return BF_RDn(LRADC_CHn, src, VALUE);
84}
85
62static inline void __attribute__((noreturn)) power_down() 86static inline void __attribute__((noreturn)) power_down()
63{ 87{
64#ifdef SANSA_FUZEPLUS 88#ifdef SANSA_FUZEPLUS
@@ -120,11 +144,45 @@ static int boot_decision(int context)
120 return !read_gpio(2, 7) ? BOOT_OF : BOOT_ROCK; 144 return !read_gpio(2, 7) ? BOOT_OF : BOOT_ROCK;
121} 145}
122#elif defined(SONY_NWZE360) || defined(SONY_NWZE370) 146#elif defined(SONY_NWZE360) || defined(SONY_NWZE370)
147static int local_decision(void)
148{
149 /* read keys and pswitch */
150 int val = read_lradc(0);
151 /* if hold is on, power off
152 * if back is pressed, boot to OF
153 * if play is pressed, boot RB
154 * otherwise power off */
155 if(read_gpio(0, 9) == 0)
156 return BOOT_STOP;
157 if(val >= 1050 && val < 1150)
158 return BOOT_OF;
159 if(val >= 1420 && val < 1520)
160 return BOOT_ROCK;
161 return BOOT_STOP;
162}
163
123static int boot_decision(int context) 164static int boot_decision(int context)
124{ 165{
125 /* Power button set PSWITCH to 3, all other buttons to 1. So any 166 setup_lradc(0); // setup LRADC channel 0 to read keys
126 * button press will boot OF */ 167 HW_PINCTRL_PULLn_SET(0) = 1 << 9; // enable pullup on hold key (B0P09)
127 return read_pswitch() == 1 ? BOOT_OF : BOOT_ROCK; 168 /* make a decision */
169 int decision = local_decision();
170 /* in USB or alarm context, stick to it */
171 if(context == CONTEXT_USB || context == CONTEXT_RTC)
172 {
173 /* never power down so replace power off decision by rockbox */
174 return decision == BOOT_STOP ? BOOT_ROCK : decision;
175 }
176 /* otherwise start a 1 second timeout. Any decision change
177 * will result in power down */
178 uint32_t tmo = HW_DIGCTL_MICROSECONDS + 1000000;
179 while(HW_DIGCTL_MICROSECONDS < tmo)
180 {
181 int new_dec = local_decision();
182 if(new_dec != decision)
183 return BOOT_STOP;
184 }
185 return decision;
128} 186}
129#else 187#else
130#warning You should define a target specific boot decision function 188#warning You should define a target specific boot decision function