+#define KWBOOT_HDR_RSP_TIMEO 10000 /* ms */
+
+/* ARM code making baudrate changing function return to original exec address */
+static unsigned char kwboot_pre_baud_code[] = {
+ /* exec_addr: */
+ 0x00, 0x00, 0x00, 0x00, /* .word 0 */
+ 0x0c, 0xe0, 0x1f, 0xe5, /* ldr lr, exec_addr */
+};
+
+/* ARM code for binary header injection to change baudrate */
+static unsigned char kwboot_baud_code[] = {
+ /* ; #define UART_BASE 0xd0012000 */
+ /* ; #define THR 0x00 */
+ /* ; #define DLL 0x00 */
+ /* ; #define DLH 0x04 */
+ /* ; #define LCR 0x0c */
+ /* ; #define DLAB 0x80 */
+ /* ; #define LSR 0x14 */
+ /* ; #define THRE 0x20 */
+ /* ; #define TEMT 0x40 */
+ /* ; #define DIV_ROUND(a, b) ((a + b/2) / b) */
+ /* ; */
+ /* ; u32 set_baudrate(u32 old_b, u32 new_b) { */
+ /* ; const u8 *str = "$baudratechange"; */
+ /* ; u8 c; */
+ /* ; do { */
+ /* ; c = *str++; */
+ /* ; writel(UART_BASE + THR, c); */
+ /* ; } while (c); */
+ /* ; while */
+ /* ; (!(readl(UART_BASE + LSR) & TEMT)); */
+ /* ; u32 lcr = readl(UART_BASE + LCR); */
+ /* ; writel(UART_BASE + LCR, lcr | DLAB); */
+ /* ; u8 old_dll = readl(UART_BASE + DLL); */
+ /* ; u8 old_dlh = readl(UART_BASE + DLH); */
+ /* ; u16 old_dl = old_dll | (old_dlh << 8); */
+ /* ; u32 clk = old_b * old_dl; */
+ /* ; u16 new_dl = DIV_ROUND(clk, new_b); */
+ /* ; u8 new_dll = new_dl & 0xff; */
+ /* ; u8 new_dlh = (new_dl >> 8) & 0xff; */
+ /* ; writel(UART_BASE + DLL, new_dll); */
+ /* ; writel(UART_BASE + DLH, new_dlh); */
+ /* ; writel(UART_BASE + LCR, lcr & ~DLAB); */
+ /* ; msleep(1); */
+ /* ; return 0; */
+ /* ; } */
+
+ 0xfe, 0x5f, 0x2d, 0xe9, /* push { r1 - r12, lr } */
+
+ /* ; r0 = UART_BASE */
+ 0x02, 0x0a, 0xa0, 0xe3, /* mov r0, #0x2000 */
+ 0x01, 0x00, 0x4d, 0xe3, /* movt r0, #0xd001 */
+
+ /* ; r2 = address of preamble string */
+ 0xd0, 0x20, 0x8f, 0xe2, /* adr r2, preamble */
+
+ /* ; Send preamble string over UART */
+ /* .Lloop_preamble: */
+ /* */
+ /* ; Wait until Transmitter Holding is Empty */
+ /* .Lloop_thre: */
+ /* ; r1 = UART_BASE[LSR] & THRE */
+ 0x14, 0x10, 0x90, 0xe5, /* ldr r1, [r0, #0x14] */
+ 0x20, 0x00, 0x11, 0xe3, /* tst r1, #0x20 */
+ 0xfc, 0xff, 0xff, 0x0a, /* beq .Lloop_thre */
+
+ /* ; Put character into Transmitter FIFO */
+ /* ; r1 = *r2++ */
+ 0x01, 0x10, 0xd2, 0xe4, /* ldrb r1, [r2], #1 */
+ /* ; UART_BASE[THR] = r1 */
+ 0x00, 0x10, 0x80, 0xe5, /* str r1, [r0, #0x0] */
+
+ /* ; Loop until end of preamble string */
+ 0x00, 0x00, 0x51, 0xe3, /* cmp r1, #0 */
+ 0xf8, 0xff, 0xff, 0x1a, /* bne .Lloop_preamble */
+
+ /* ; Wait until Transmitter FIFO is Empty */
+ /* .Lloop_txempty: */
+ /* ; r1 = UART_BASE[LSR] & TEMT */
+ 0x14, 0x10, 0x90, 0xe5, /* ldr r1, [r0, #0x14] */
+ 0x40, 0x00, 0x11, 0xe3, /* tst r1, #0x40 */
+ 0xfc, 0xff, 0xff, 0x0a, /* beq .Lloop_txempty */
+
+ /* ; Set Divisor Latch Access Bit */
+ /* ; UART_BASE[LCR] |= DLAB */
+ 0x0c, 0x10, 0x90, 0xe5, /* ldr r1, [r0, #0x0c] */
+ 0x80, 0x10, 0x81, 0xe3, /* orr r1, r1, #0x80 */
+ 0x0c, 0x10, 0x80, 0xe5, /* str r1, [r0, #0x0c] */
+
+ /* ; Read current Divisor Latch */
+ /* ; r1 = UART_BASE[DLH]<<8 | UART_BASE[DLL] */
+ 0x00, 0x10, 0x90, 0xe5, /* ldr r1, [r0, #0x00] */
+ 0xff, 0x10, 0x01, 0xe2, /* and r1, r1, #0xff */
+ 0x01, 0x20, 0xa0, 0xe1, /* mov r2, r1 */
+ 0x04, 0x10, 0x90, 0xe5, /* ldr r1, [r0, #0x04] */
+ 0xff, 0x10, 0x01, 0xe2, /* and r1, r1, #0xff */
+ 0x41, 0x14, 0xa0, 0xe1, /* asr r1, r1, #8 */
+ 0x02, 0x10, 0x81, 0xe1, /* orr r1, r1, r2 */
+
+ /* ; Read old baudrate value */
+ /* ; r2 = old_baudrate */
+ 0x8c, 0x20, 0x9f, 0xe5, /* ldr r2, old_baudrate */
+
+ /* ; Calculate base clock */
+ /* ; r1 = r2 * r1 */
+ 0x92, 0x01, 0x01, 0xe0, /* mul r1, r2, r1 */
+
+ /* ; Read new baudrate value */
+ /* ; r2 = baudrate */
+ 0x88, 0x20, 0x9f, 0xe5, /* ldr r2, baudrate */
+
+ /* ; Calculate new Divisor Latch */
+ /* ; r1 = DIV_ROUND(r1, r2) = */
+ /* ; = (r1 + r2/2) / r2 */
+ 0xa2, 0x10, 0x81, 0xe0, /* add r1, r1, r2, lsr #1 */
+ 0x02, 0x40, 0xa0, 0xe1, /* mov r4, r2 */
+ 0xa1, 0x00, 0x54, 0xe1, /* cmp r4, r1, lsr #1 */
+ /* .Lloop_div1: */
+ 0x84, 0x40, 0xa0, 0x91, /* movls r4, r4, lsl #1 */
+ 0xa1, 0x00, 0x54, 0xe1, /* cmp r4, r1, lsr #1 */
+ 0xfc, 0xff, 0xff, 0x9a, /* bls .Lloop_div1 */
+ 0x00, 0x30, 0xa0, 0xe3, /* mov r3, #0 */
+ /* .Lloop_div2: */
+ 0x04, 0x00, 0x51, 0xe1, /* cmp r1, r4 */
+ 0x04, 0x10, 0x41, 0x20, /* subhs r1, r1, r4 */
+ 0x03, 0x30, 0xa3, 0xe0, /* adc r3, r3, r3 */
+ 0xa4, 0x40, 0xa0, 0xe1, /* mov r4, r4, lsr #1 */
+ 0x02, 0x00, 0x54, 0xe1, /* cmp r4, r2 */
+ 0xf9, 0xff, 0xff, 0x2a, /* bhs .Lloop_div2 */
+ 0x03, 0x10, 0xa0, 0xe1, /* mov r1, r3 */
+
+ /* ; Set new Divisor Latch Low */
+ /* ; UART_BASE[DLL] = r1 & 0xff */
+ 0x01, 0x20, 0xa0, 0xe1, /* mov r2, r1 */
+ 0xff, 0x20, 0x02, 0xe2, /* and r2, r2, #0xff */
+ 0x00, 0x20, 0x80, 0xe5, /* str r2, [r0, #0x00] */
+
+ /* ; Set new Divisor Latch High */
+ /* ; UART_BASE[DLH] = r1>>8 & 0xff */
+ 0x41, 0x24, 0xa0, 0xe1, /* asr r2, r1, #8 */
+ 0xff, 0x20, 0x02, 0xe2, /* and r2, r2, #0xff */
+ 0x04, 0x20, 0x80, 0xe5, /* str r2, [r0, #0x04] */
+
+ /* ; Clear Divisor Latch Access Bit */
+ /* ; UART_BASE[LCR] &= ~DLAB */
+ 0x0c, 0x10, 0x90, 0xe5, /* ldr r1, [r0, #0x0c] */
+ 0x80, 0x10, 0xc1, 0xe3, /* bic r1, r1, #0x80 */
+ 0x0c, 0x10, 0x80, 0xe5, /* str r1, [r0, #0x0c] */
+
+ /* ; Sleep 1ms ~~ 600000 cycles at 1200 MHz */
+ /* ; r1 = 600000 */
+ 0x9f, 0x1d, 0xa0, 0xe3, /* mov r1, #0x27c0 */
+ 0x09, 0x10, 0x40, 0xe3, /* movt r1, #0x0009 */
+ /* .Lloop_sleep: */
+ 0x01, 0x10, 0x41, 0xe2, /* sub r1, r1, #1 */
+ 0x00, 0x00, 0x51, 0xe3, /* cmp r1, #0 */
+ 0xfc, 0xff, 0xff, 0x1a, /* bne .Lloop_sleep */
+
+ /* ; Return 0 - no error */
+ 0x00, 0x00, 0xa0, 0xe3, /* mov r0, #0 */
+ 0xfe, 0x9f, 0xbd, 0xe8, /* pop { r1 - r12, pc } */
+
+ /* ; Preamble string */
+ /* preamble: */
+ 0x24, 0x62, 0x61, 0x75, /* .asciz "$baudratechange" */
+ 0x64, 0x72, 0x61, 0x74,
+ 0x65, 0x63, 0x68, 0x61,
+ 0x6e, 0x67, 0x65, 0x00,
+
+ /* ; Placeholder for old baudrate value */
+ /* old_baudrate: */
+ 0x00, 0x00, 0x00, 0x00, /* .word 0 */
+
+ /* ; Placeholder for new baudrate value */
+ /* new_baudrate: */
+ 0x00, 0x00, 0x00, 0x00, /* .word 0 */
+};
+
+#define KWBOOT_BAUDRATE_BIN_HEADER_SZ (sizeof(kwboot_baud_code) + \
+ sizeof(struct opt_hdr_v1) + 8)
+
+static const char kwb_baud_magic[16] = "$baudratechange";