From e5de5e09c1ca6788d155393af0d906a9402ea7bc Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Tue, 16 Jul 2013 19:29:42 +0200 Subject: hwstub: enhance exit protocol and implement on stmp Rename STOP command to EXIT, introduce ATEXIT, this gives better control over the exit of the stub. Add stmp implementation. Change-Id: I45442c8b88b9330d12ef439417ca5ffa1520477a --- utils/hwstub/hwstub_protocol.h | 32 ++++++++++++++------ utils/hwstub/lib/hwstub.c | 21 +++++++------ utils/hwstub/lib/hwstub.h | 5 +-- utils/hwstub/stub/stmp/target.c | 67 ++++++++++++++++++++++++++++++++++++++++- utils/hwstub/stub/target.h | 6 +++- 5 files changed, 107 insertions(+), 24 deletions(-) (limited to 'utils/hwstub') diff --git a/utils/hwstub/hwstub_protocol.h b/utils/hwstub/hwstub_protocol.h index f47ce3b5db..99131aa70c 100644 --- a/utils/hwstub/hwstub_protocol.h +++ b/utils/hwstub/hwstub_protocol.h @@ -27,7 +27,7 @@ #define HWSTUB_VERSION_MAJOR 2 #define HWSTUB_VERSION_MINOR 11 -#define HWSTUB_VERSION_REV 1 +#define HWSTUB_VERSION_REV 2 #define HWSTUB_USB_VID 0xfee1 #define HWSTUB_USB_PID 0xdead @@ -46,7 +46,8 @@ #define HWSTUB_RW_MEM 2 /* optional */ #define HWSTUB_CALL 3 /* optional */ #define HWSTUB_JUMP 4 /* optional */ -#define HWSTUB_STOP 5 /* optional */ +#define HWSTUB_EXIT 5 /* optional */ +#define HWSTUB_ATEXIT 6 /* optional */ /** * HWSTUB_GET_INFO: get some information about an aspect of the device. @@ -91,7 +92,7 @@ struct usb_resp_info_stmp_t #define HWSTUB_FEATURE_MEM (1 << 1) #define HWSTUB_FEATURE_CALL (1 << 2) #define HWSTUB_FEATURE_JUMP (1 << 3) -#define HWSTUB_FEATURE_STOP (1 << 4) +#define HWSTUB_FEATURE_EXIT (1 << 4) struct usb_resp_info_features_t { @@ -129,12 +130,23 @@ struct usb_resp_info_target_t * the transfer is either a read or a write. */ /** - * HWSTUB_STOP: only if has HWSTUB_FEATURE_STOP. - * Stop hwstub. Several methods can be employed (not all may be supported). - * The method is stored in wValue and interpreted as follows: - * - reboot: immediately reboot the device - * - off: wait for USB disconnection and power off */ -#define HWSTUB_STOP_REBOOT 0 -#define HWSTUB_STOP_OFF 1 + * HWSTUB_EXIT: only if has HWSTUB_FEATURE_EXIT. + * Stop hwstub now, performing the atexit action. Default exit action + * is target dependent. */ + +/** + * HWSTUB_ATEXIT: only if has HWSTUB_FEATURE_EXIT. + * Sets the action to perform at exit. Exit happens by sending HWSTUB_EXIT + * or on USB disconnection. The following actions are available: + * - nop: don't do anything, wait for next connection + * - reboot: reboot the device + * - off: power off + * NOTE the power off action might have to wait for USB disconnection as some + * targets cannot power off while plugged. + * NOTE appart from nop which is mandatory, all other methods can be + * unavailable and thus the atexit command can fail. */ +#define HWSTUB_ATEXIT_REBOOT 0 +#define HWSTUB_ATEXIT_OFF 1 +#define HWSTUB_ATEXIT_NOP 2 #endif /* __HWSTUB_PROTOCOL__ */ diff --git a/utils/hwstub/lib/hwstub.c b/utils/hwstub/lib/hwstub.c index 92010e710b..41842fb181 100644 --- a/utils/hwstub/lib/hwstub.c +++ b/utils/hwstub/lib/hwstub.c @@ -158,17 +158,18 @@ const char *hwstub_get_rev_string(struct usb_resp_info_stmp_t *stmp) } } -int hwstub_aes_otp(struct hwstub_device_t *dev, void *buf, size_t sz, uint16_t param) +int hwstub_atexit(struct hwstub_device_t *dev, int method) { - int ret = libusb_control_transfer(dev->handle, + return libusb_control_transfer(dev->handle, + LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | + LIBUSB_ENDPOINT_OUT, HWSTUB_ATEXIT, 0, method, NULL, 0, + 1000); +} + +int hwstub_exit(struct hwstub_device_t *dev) +{ + return libusb_control_transfer(dev->handle, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | - LIBUSB_ENDPOINT_OUT, HWSTUB_AES_OTP, param, 0, buf, sz, + LIBUSB_ENDPOINT_OUT, HWSTUB_EXIT, 0, 0, NULL, 0, 1000); - if(ret <0 || (unsigned)ret != sz) - return -1; - int xfer; - ret = libusb_interrupt_transfer(dev->handle, dev->int_in, buf, sz, &xfer, 1000); - if(ret < 0 || (unsigned)xfer != sz) - return -1; - return ret; } diff --git a/utils/hwstub/lib/hwstub.h b/utils/hwstub/lib/hwstub.h index ed058dfa3b..f89bce5de9 100644 --- a/utils/hwstub/lib/hwstub.h +++ b/utils/hwstub/lib/hwstub.h @@ -57,8 +57,9 @@ int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *bu /* Returns <0 on error */ int hwstub_call(struct hwstub_device_t *dev, uint32_t addr); int hwstub_jump(struct hwstub_device_t *dev, uint32_t addr); -/* Returns <0 on error. The size must be a multiple of 16. */ -int hwstub_aes_otp(struct hwstub_device_t *dev, void *buf, size_t sz, uint16_t param); +/* Returns <0 on error */ +int hwstub_atexit(struct hwstub_device_t *dev, int action); +int hwstub_exit(struct hwstub_device_t *dev); const char *hwstub_get_product_string(struct usb_resp_info_stmp_t *stmp); const char *hwstub_get_rev_string(struct usb_resp_info_stmp_t *stmp); diff --git a/utils/hwstub/stub/stmp/target.c b/utils/hwstub/stub/stmp/target.c index 11516e5492..da46d50779 100644 --- a/utils/hwstub/stub/stmp/target.c +++ b/utils/hwstub/stub/stmp/target.c @@ -49,7 +49,35 @@ enum stmp_family_t STMP3780 }; -enum stmp_family_t g_stmp_family = UNKNOWN; +static enum stmp_family_t g_stmp_family = UNKNOWN; +static int g_atexit = HWSTUB_ATEXIT_OFF; + +/** + * + * Power + * + */ + +#define HW_POWER_BASE 0x80044000 + +void power_off(void) +{ + switch(g_stmp_family) + { + case STMP3600: + *(volatile uint32_t *)(HW_POWER_BASE + 0xc0) = 0x3e770014; + break; + case STMP3700: + case STMP3770: + *(volatile uint32_t *)(HW_POWER_BASE + 0xe0) = 0x3e770003; + break; + case STMP3780: + *(volatile uint32_t *)(HW_POWER_BASE + 0x100) = 0x3e770003; + break; + default: + break; + } +} /** * @@ -86,6 +114,25 @@ enum stmp_family_t g_stmp_family = UNKNOWN; #define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE (1 << 30) #define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK120M_GATE (1 << 31) +void clkctrl_reset(void) +{ + switch(g_stmp_family) + { + case STMP3600: + *(volatile uint32_t *)(HW_POWER_BASE + 0xc0) = 0x3e770002; + break; + case STMP3700: + case STMP3770: + *(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xf0) = 0x1; + break; + case STMP3780: + *(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x100) = 0x1; + break; + default: + break; + } +} + /** * * Digctl @@ -205,6 +252,24 @@ int target_get_info(int info, void **buffer) return -1; } +int target_atexit(int method) +{ + g_atexit = method; + return 0; +} + void target_exit(void) { + switch(g_atexit) + { + case HWSTUB_ATEXIT_OFF: + power_off(); + // fallthrough in case of return + case HWSTUB_ATEXIT_REBOOT: + clkctrl_reset(); + // fallthrough in case of return + case HWSTUB_ATEXIT_NOP: + default: + return; + } } diff --git a/utils/hwstub/stub/target.h b/utils/hwstub/stub/target.h index 3f1551c72d..56c960741f 100644 --- a/utils/hwstub/stub/target.h +++ b/utils/hwstub/stub/target.h @@ -23,9 +23,13 @@ #include "protocol.h" +/* do target specific init */ void target_init(void); +/* exit, performing the atexit action (default is target specific) */ void target_exit(void); -/* return actual size or -1 if error */ +/* get information, return actual size or -1 if error */ int target_get_info(int info, void **buffer); +/* set atexit action or return -1 on error */ +int target_atexit(int action); #endif /* __TARGET_H__ */ -- cgit v1.2.3