forked from len0rd/rockbox
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
This commit is contained in:
parent
5ba7e2ca72
commit
e5de5e09c1
5 changed files with 107 additions and 24 deletions
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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_AES_OTP, param, 0, buf, sz,
|
||||
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_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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue