1
0
Fork 0
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:
Amaury Pouly 2013-07-16 19:29:42 +02:00
parent 5ba7e2ca72
commit e5de5e09c1
5 changed files with 107 additions and 24 deletions

View file

@ -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__ */

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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__ */