summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-07-16 19:29:42 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-07-16 19:29:42 +0200
commite5de5e09c1ca6788d155393af0d906a9402ea7bc (patch)
tree14aa5a0d78ae96d233bdffe96e3207ba27a4631e
parent5ba7e2ca72412a4e58a76f43738f6309b533e03f (diff)
downloadrockbox-e5de5e09c1ca6788d155393af0d906a9402ea7bc.tar.gz
rockbox-e5de5e09c1ca6788d155393af0d906a9402ea7bc.zip
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
-rw-r--r--utils/hwstub/hwstub_protocol.h32
-rw-r--r--utils/hwstub/lib/hwstub.c21
-rw-r--r--utils/hwstub/lib/hwstub.h5
-rw-r--r--utils/hwstub/stub/stmp/target.c67
-rw-r--r--utils/hwstub/stub/target.h6
5 files changed, 107 insertions, 24 deletions
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__ */