1 /* swdp-m0sub.c
2  *
3  * Copyright 2015 Brian Swetland <swetland@frotz.net>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <app.h>
19 #include <lk/debug.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <printf.h>
23 
24 #include <platform.h>
25 #include <arch/arm.h>
26 #include <kernel/thread.h>
27 
28 #include <platform/lpc43xx-gpio.h>
29 #include <platform/lpc43xx-sgpio.h>
30 #include <platform/lpc43xx-clocks.h>
31 
32 #include "rswdp.h"
33 
34 #include "lpclink2.h"
35 
gpio_init(void)36 static void gpio_init(void) {
37     pin_config(PIN_LED, PIN_MODE(0) | PIN_PLAIN);
38     pin_config(PIN_RESET, PIN_MODE(4) | PIN_PLAIN);
39     pin_config(PIN_RESET_TXEN, PIN_MODE(4) | PIN_PLAIN);
40     pin_config(PIN_TMS_TXEN, PIN_MODE(0) | PIN_PLAIN);
41 
42     pin_config(PIN_TDO, PIN_MODE(6) | PIN_PLAIN | PIN_INPUT | PIN_FAST);
43     pin_config(PIN_TCK, PIN_MODE(6) | PIN_PLAIN | PIN_FAST);
44     pin_config(PIN_TDI, PIN_MODE(6) | PIN_PLAIN | PIN_FAST);
45     pin_config(PIN_TMS, PIN_MODE(6) | PIN_PLAIN | PIN_FAST);
46 
47     gpio_set(GPIO_LED, 0);
48     gpio_set(GPIO_RESET, 1);
49     gpio_set(GPIO_RESET_TXEN, 0);
50     gpio_set(GPIO_TMS_TXEN, 1);
51 
52     gpio_config(GPIO_LED, GPIO_OUTPUT);
53     gpio_config(GPIO_RESET, GPIO_OUTPUT);
54     gpio_config(GPIO_RESET_TXEN, GPIO_OUTPUT);
55     gpio_config(GPIO_TMS_TXEN, GPIO_OUTPUT);
56 }
57 
58 #define POS_TDO     10
59 #define POS_TCK     11
60 #define POS_TDI     12
61 #define POS_TMS     14
62 
63 #define BIT_TDO     (1 << POS_TDO)
64 #define BIT_TCK     (1 << POS_TCK)
65 #define BIT_TDI     (1 << POS_TDI)
66 #define BIT_TMS     (1 << POS_TMS)
67 
jtag_init(void)68 void jtag_init(void) {
69     gpio_init();
70 
71     writel(BASE_CLK_SEL(CLK_PLL1), BASE_PERIPH_CLK);
72     spin(1000);
73 
74     // configure for SGPIO_OUT/OEN control
75     writel(CFG_OUT_GPIO | CFG_OE_GPIO, SGPIO_OUT_CFG(POS_TDO));
76     writel(CFG_OUT_GPIO | CFG_OE_GPIO, SGPIO_OUT_CFG(POS_TCK));
77     writel(CFG_OUT_GPIO | CFG_OE_GPIO, SGPIO_OUT_CFG(POS_TDI));
78     writel(CFG_OUT_GPIO | CFG_OE_GPIO, SGPIO_OUT_CFG(POS_TMS));
79 
80     // TCK=0 TDI=0 TMS=0 TDO=input
81     writel(0, SGPIO_OUT);
82     writel(BIT_TCK | BIT_TDI | BIT_TMS, SGPIO_OEN);
83 }
84 
jtag_tick(unsigned tms,unsigned tdi)85 static unsigned jtag_tick(unsigned tms, unsigned tdi) {
86     unsigned x = (tms << POS_TMS) | (tdi << POS_TDI);
87     unsigned v;
88     writel(x, SGPIO_OUT);
89     writel(x, SGPIO_OUT);
90     writel(x, SGPIO_OUT);
91     x |= BIT_TCK;
92     v = readl(SGPIO_IN);
93     writel(x, SGPIO_OUT);
94     writel(x, SGPIO_OUT);
95     writel(x, SGPIO_OUT);
96     writel(x, SGPIO_OUT);
97     writel(x, SGPIO_OUT);
98     writel(x, SGPIO_OUT);
99     x ^= BIT_TCK;
100     writel(x, SGPIO_OUT);
101     return (v >> POS_TDO) & 1;
102 }
103 
jtag_io(unsigned count,unsigned tms,unsigned tdi,unsigned * tdo)104 int jtag_io(unsigned count, unsigned tms, unsigned tdi, unsigned *tdo) {
105     unsigned n = 0;
106     unsigned bit = 0;
107     while (count > 0) {
108         n |= (jtag_tick(tms & 1, tdi & 1) << bit);
109         bit++;
110         count--;
111         tms >>= 1;
112         tdi >>= 1;
113     }
114     *tdo = n;
115     return 0;
116 }
117