diff options
Diffstat (limited to 'utils/hwstub/stub/stmp')
-rw-r--r-- | utils/hwstub/stub/stmp/target.c | 132 |
1 files changed, 42 insertions, 90 deletions
diff --git a/utils/hwstub/stub/stmp/target.c b/utils/hwstub/stub/stmp/target.c index 98f65da625..8d48707088 100644 --- a/utils/hwstub/stub/stmp/target.c +++ b/utils/hwstub/stub/stmp/target.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include "target.h" | 22 | #include "target.h" |
23 | #include "system.h" | 23 | #include "system.h" |
24 | #include "logf.h" | 24 | #include "logf.h" |
25 | #include "memory.h" | ||
25 | 26 | ||
26 | #define __REG_SET(reg) (*((volatile uint32_t *)(® + 1))) | 27 | #define __REG_SET(reg) (*((volatile uint32_t *)(® + 1))) |
27 | #define __REG_CLR(reg) (*((volatile uint32_t *)(® + 2))) | 28 | #define __REG_CLR(reg) (*((volatile uint32_t *)(® + 2))) |
@@ -50,34 +51,6 @@ enum stmp_family_t | |||
50 | }; | 51 | }; |
51 | 52 | ||
52 | static enum stmp_family_t g_stmp_family = UNKNOWN; | 53 | static enum stmp_family_t g_stmp_family = UNKNOWN; |
53 | static int g_atexit = HWSTUB_ATEXIT_OFF; | ||
54 | |||
55 | /** | ||
56 | * | ||
57 | * Power | ||
58 | * | ||
59 | */ | ||
60 | |||
61 | #define HW_POWER_BASE 0x80044000 | ||
62 | |||
63 | void power_off(void) | ||
64 | { | ||
65 | switch(g_stmp_family) | ||
66 | { | ||
67 | case STMP3600: | ||
68 | *(volatile uint32_t *)(HW_POWER_BASE + 0xc0) = 0x3e770014; | ||
69 | break; | ||
70 | case STMP3700: | ||
71 | case STMP3770: | ||
72 | *(volatile uint32_t *)(HW_POWER_BASE + 0xe0) = 0x3e770001; | ||
73 | break; | ||
74 | case STMP3780: | ||
75 | *(volatile uint32_t *)(HW_POWER_BASE + 0x100) = 0x3e770001; | ||
76 | break; | ||
77 | default: | ||
78 | break; | ||
79 | } | ||
80 | } | ||
81 | 54 | ||
82 | /** | 55 | /** |
83 | * | 56 | * |
@@ -114,25 +87,6 @@ void power_off(void) | |||
114 | #define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE (1 << 30) | 87 | #define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE (1 << 30) |
115 | #define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK120M_GATE (1 << 31) | 88 | #define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK120M_GATE (1 << 31) |
116 | 89 | ||
117 | void clkctrl_reset(void) | ||
118 | { | ||
119 | switch(g_stmp_family) | ||
120 | { | ||
121 | case STMP3600: | ||
122 | *(volatile uint32_t *)(HW_POWER_BASE + 0xc0) = 0x3e770002; | ||
123 | break; | ||
124 | case STMP3700: | ||
125 | case STMP3770: | ||
126 | *(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xf0) = 0x1; | ||
127 | break; | ||
128 | case STMP3780: | ||
129 | *(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x120) = 0x1; | ||
130 | break; | ||
131 | default: | ||
132 | break; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | /** | 90 | /** |
137 | * | 91 | * |
138 | * Digctl | 92 | * Digctl |
@@ -143,11 +97,18 @@ void clkctrl_reset(void) | |||
143 | #define HW_DIGCTL_BASE 0x8001C000 | 97 | #define HW_DIGCTL_BASE 0x8001C000 |
144 | #define HW_DIGCTL_CTRL (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0)) | 98 | #define HW_DIGCTL_CTRL (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0)) |
145 | #define HW_DIGCTL_CTRL__USB_CLKGATE (1 << 2) | 99 | #define HW_DIGCTL_CTRL__USB_CLKGATE (1 << 2) |
100 | #define HW_DIGCTL_CTRL__PACKAGE_SENSE_ENABLE_STMP3600 (1 << 0) | ||
101 | |||
102 | #define HW_DIGCTL_STATUS (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0x10)) | ||
103 | #define HW_DIGCTL_STATUS__PACKAGE_TYPE_BP 1 | ||
104 | #define HW_DIGCTL_STATUS__PACKAGE_TYPE_BM (7 << 1) | ||
105 | #define HW_DIGCTL_STATUS__PACKAGE_TYPE_STMP3600_BP 1 | ||
106 | #define HW_DIGCTL_STATUS__PACKAGE_TYPE_STMP3600_BM (1 << 1) | ||
146 | 107 | ||
147 | /* STMP3700+ */ | 108 | /* STMP3700+ */ |
148 | #define HW_DIGCTL_MICROSECONDS (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xC0)) | 109 | #define HW_DIGCTL_MICROSECONDS (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xC0)) |
149 | /* STMP3600 */ | 110 | /* STMP3600 */ |
150 | #define HW_DIGCTL_MICROSECONDS2 (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xB0)) | 111 | #define HW_DIGCTL_MICROSECONDS_STMP3600 (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xB0)) |
151 | 112 | ||
152 | #define HW_DIGCTL_CHIPID (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0x310)) | 113 | #define HW_DIGCTL_CHIPID (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0x310)) |
153 | #define HW_DIGCTL_CHIPID__PRODUCT_CODE_BP 16 | 114 | #define HW_DIGCTL_CHIPID__PRODUCT_CODE_BP 16 |
@@ -177,8 +138,25 @@ void clkctrl_reset(void) | |||
177 | #define HW_RTC_CTRL (*(volatile uint32_t *)(HW_RTC_BASE + 0)) | 138 | #define HW_RTC_CTRL (*(volatile uint32_t *)(HW_RTC_BASE + 0)) |
178 | #define HW_RTC_CTRL__WATCHDOGEN (1 << 4) | 139 | #define HW_RTC_CTRL__WATCHDOGEN (1 << 4) |
179 | 140 | ||
141 | struct hwstub_target_desc_t __attribute__((aligned(2))) target_descriptor = | ||
142 | { | ||
143 | sizeof(struct hwstub_target_desc_t), | ||
144 | HWSTUB_DT_TARGET, | ||
145 | HWSTUB_TARGET_STMP, | ||
146 | "STMP3600 / STMP3700 / STMP3780 (i.MX233)" | ||
147 | }; | ||
148 | |||
149 | static struct hwstub_stmp_desc_t __attribute__((aligned(2))) stmp_descriptor = | ||
150 | { | ||
151 | sizeof(struct hwstub_stmp_desc_t), | ||
152 | HWSTUB_DT_STMP, | ||
153 | 0, 0, 0 | ||
154 | }; | ||
155 | |||
180 | void target_init(void) | 156 | void target_init(void) |
181 | { | 157 | { |
158 | stmp_descriptor.wChipID = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE); | ||
159 | stmp_descriptor.bRevision = __XTRACT(HW_DIGCTL_CHIPID, REVISION); | ||
182 | /* detect family */ | 160 | /* detect family */ |
183 | uint16_t product_code = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE); | 161 | uint16_t product_code = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE); |
184 | if(product_code >= 0x3600 && product_code < 0x3700) | 162 | if(product_code >= 0x3600 && product_code < 0x3700) |
@@ -208,6 +186,7 @@ void target_init(void) | |||
208 | 186 | ||
209 | if(g_stmp_family == STMP3600) | 187 | if(g_stmp_family == STMP3600) |
210 | { | 188 | { |
189 | stmp_descriptor.bPackage = __XTRACT(HW_DIGCTL_STATUS, PACKAGE_TYPE); | ||
211 | /* CPU clock is always derived from PLL, if we switch to PLL, cpu will | 190 | /* CPU clock is always derived from PLL, if we switch to PLL, cpu will |
212 | * run at 480 MHz unprepared ! That's bad so prepare to run at slow sleed | 191 | * run at 480 MHz unprepared ! That's bad so prepare to run at slow sleed |
213 | * (1.2MHz) for a safe transition */ | 192 | * (1.2MHz) for a safe transition */ |
@@ -230,7 +209,13 @@ void target_init(void) | |||
230 | __REG_CLR(HW_CLKCTRL_UTMICLKCTRL) = HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE; | 209 | __REG_CLR(HW_CLKCTRL_UTMICLKCTRL) = HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE; |
231 | } | 210 | } |
232 | else | 211 | else |
212 | { | ||
213 | __REG_SET(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__PACKAGE_SENSE_ENABLE_STMP3600; | ||
214 | stmp_descriptor.bPackage = __XTRACT(HW_DIGCTL_STATUS, PACKAGE_TYPE_STMP3600); | ||
215 | __REG_CLR(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__PACKAGE_SENSE_ENABLE_STMP3600; | ||
216 | |||
233 | __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__POWER; | 217 | __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__POWER; |
218 | } | ||
234 | /* enable USB PHY PLL */ | 219 | /* enable USB PHY PLL */ |
235 | __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS; | 220 | __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS; |
236 | /* power up USB PHY */ | 221 | /* power up USB PHY */ |
@@ -240,57 +225,24 @@ void target_init(void) | |||
240 | __REG_CLR(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__USB_CLKGATE; | 225 | __REG_CLR(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__USB_CLKGATE; |
241 | } | 226 | } |
242 | 227 | ||
243 | static struct usb_resp_info_stmp_t g_stmp; | 228 | void target_get_desc(int desc, void **buffer) |
244 | static struct usb_resp_info_target_t g_target = | ||
245 | { | ||
246 | .id = HWSTUB_TARGET_STMP, | ||
247 | .name = "STMP3600 / STMP3700 / STMP3780 (i.MX233)" | ||
248 | }; | ||
249 | |||
250 | int target_get_info(int info, void **buffer) | ||
251 | { | 229 | { |
252 | if(info == HWSTUB_INFO_STMP) | 230 | if(desc == HWSTUB_DT_STMP) |
253 | { | 231 | *buffer = &stmp_descriptor; |
254 | g_stmp.chipid = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE); | ||
255 | g_stmp.rev = __XTRACT(HW_DIGCTL_CHIPID, REVISION); | ||
256 | g_stmp.is_supported = g_stmp_family != 0; | ||
257 | *buffer = &g_stmp; | ||
258 | return sizeof(g_stmp); | ||
259 | } | ||
260 | else if(info == HWSTUB_INFO_TARGET) | ||
261 | { | ||
262 | *buffer = &g_target; | ||
263 | return sizeof(g_target); | ||
264 | } | ||
265 | else | 232 | else |
266 | return -1; | 233 | *buffer = NULL; |
267 | } | 234 | } |
268 | 235 | ||
269 | int target_atexit(int method) | 236 | void target_get_config_desc(void *buffer, int *size) |
270 | { | 237 | { |
271 | g_atexit = method; | 238 | memcpy(buffer, &stmp_descriptor, sizeof(stmp_descriptor)); |
272 | return 0; | 239 | *size += sizeof(stmp_descriptor); |
273 | } | ||
274 | |||
275 | void target_exit(void) | ||
276 | { | ||
277 | switch(g_atexit) | ||
278 | { | ||
279 | case HWSTUB_ATEXIT_OFF: | ||
280 | power_off(); | ||
281 | // fallthrough in case of return | ||
282 | case HWSTUB_ATEXIT_REBOOT: | ||
283 | clkctrl_reset(); | ||
284 | // fallthrough in case of return | ||
285 | case HWSTUB_ATEXIT_NOP: | ||
286 | default: | ||
287 | return; | ||
288 | } | ||
289 | } | 240 | } |
290 | 241 | ||
291 | void target_udelay(int us) | 242 | void target_udelay(int us) |
292 | { | 243 | { |
293 | volatile uint32_t *reg = g_stmp_family == STMP3600 ? &HW_DIGCTL_MICROSECONDS2 : &HW_DIGCTL_MICROSECONDS; | 244 | volatile uint32_t *reg = g_stmp_family == STMP3600 ? |
245 | &HW_DIGCTL_MICROSECONDS_STMP3600 : &HW_DIGCTL_MICROSECONDS; | ||
294 | uint32_t cur = *reg; | 246 | uint32_t cur = *reg; |
295 | uint32_t end = cur + us; | 247 | uint32_t end = cur + us; |
296 | if(cur < end) | 248 | if(cur < end) |