e7c993b3bc7945af076cee7e02c53ee67eabe519
[fw/openocd] / src / jtag / drivers / ep93xx.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4  *   Copyright (C) 2005 by Dominic Rath                                    *
5  *   Dominic.Rath@gmx.de                                                   *
6  ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include <jtag/interface.h>
13 #include "bitbang.h"
14
15 #define TDO_BIT         1
16 #define TDI_BIT         2
17 #define TCK_BIT         4
18 #define TMS_BIT         8
19 #define TRST_BIT        16
20 #define SRST_BIT        32
21 #define VCC_BIT         64
22
23 #include <sys/mman.h>
24
25 static uint8_t output_value;
26 static int dev_mem_fd;
27 static void *gpio_controller;
28 static volatile uint8_t *gpio_data_register;
29 static volatile uint8_t *gpio_data_direction_register;
30
31 /* low level command set
32  */
33 static bb_value_t ep93xx_read(void);
34 static int ep93xx_write(int tck, int tms, int tdi);
35 static int ep93xx_reset(int trst, int srst);
36
37 static int ep93xx_init(void);
38 static int ep93xx_quit(void);
39
40 struct timespec ep93xx_zzzz;
41
42 static struct jtag_interface ep93xx_interface = {
43         .supported = DEBUG_CAP_TMS_SEQ,
44         .execute_queue = bitbang_execute_queue,
45 };
46
47 struct adapter_driver ep93xx_adapter_driver = {
48         .name = "ep93xx",
49         .transports = jtag_only,
50
51         .init = ep93xx_init,
52         .quit = ep93xx_quit,
53         .reset = ep93xx_reset,
54
55         .jtag_ops = &ep93xx_interface,
56 };
57
58 static struct bitbang_interface ep93xx_bitbang = {
59         .read = ep93xx_read,
60         .write = ep93xx_write,
61         .blink = 0,
62 };
63
64 static bb_value_t ep93xx_read(void)
65 {
66         return (*gpio_data_register & TDO_BIT) ? BB_HIGH : BB_LOW;
67 }
68
69 static int ep93xx_write(int tck, int tms, int tdi)
70 {
71         if (tck)
72                 output_value |= TCK_BIT;
73         else
74                 output_value &= ~TCK_BIT;
75
76         if (tms)
77                 output_value |= TMS_BIT;
78         else
79                 output_value &= ~TMS_BIT;
80
81         if (tdi)
82                 output_value |= TDI_BIT;
83         else
84                 output_value &= ~TDI_BIT;
85
86         *gpio_data_register = output_value;
87         nanosleep(&ep93xx_zzzz, NULL);
88
89         return ERROR_OK;
90 }
91
92 /* (1) assert or (0) deassert reset lines */
93 static int ep93xx_reset(int trst, int srst)
94 {
95         if (trst == 0)
96                 output_value |= TRST_BIT;
97         else if (trst == 1)
98                 output_value &= ~TRST_BIT;
99
100         if (srst == 0)
101                 output_value |= SRST_BIT;
102         else if (srst == 1)
103                 output_value &= ~SRST_BIT;
104
105         *gpio_data_register = output_value;
106         nanosleep(&ep93xx_zzzz, NULL);
107
108         return ERROR_OK;
109 }
110
111 static int set_gonk_mode(void)
112 {
113         void *syscon;
114         uint32_t devicecfg;
115
116         syscon = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
117                         MAP_SHARED, dev_mem_fd, 0x80930000);
118         if (syscon == MAP_FAILED) {
119                 LOG_ERROR("mmap: %s", strerror(errno));
120                 return ERROR_JTAG_INIT_FAILED;
121         }
122
123         devicecfg = *((volatile int *)(syscon + 0x80));
124         *((volatile int *)(syscon + 0xc0)) = 0xaa;
125         *((volatile int *)(syscon + 0x80)) = devicecfg | 0x08000000;
126
127         munmap(syscon, 4096);
128
129         return ERROR_OK;
130 }
131
132 static int ep93xx_init(void)
133 {
134         int ret;
135
136         bitbang_interface = &ep93xx_bitbang;
137
138         ep93xx_zzzz.tv_sec = 0;
139         ep93xx_zzzz.tv_nsec = 10000000;
140
141         dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
142         if (dev_mem_fd < 0) {
143                 LOG_ERROR("open: %s", strerror(errno));
144                 return ERROR_JTAG_INIT_FAILED;
145         }
146
147         gpio_controller = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
148                                 MAP_SHARED, dev_mem_fd, 0x80840000);
149         if (gpio_controller == MAP_FAILED) {
150                 LOG_ERROR("mmap: %s", strerror(errno));
151                 close(dev_mem_fd);
152                 return ERROR_JTAG_INIT_FAILED;
153         }
154
155         ret = set_gonk_mode();
156         if (ret != ERROR_OK) {
157                 munmap(gpio_controller, 4096);
158                 close(dev_mem_fd);
159                 return ret;
160         }
161
162 #if 0
163         /* Use GPIO port A.  */
164         gpio_data_register = gpio_controller + 0x00;
165         gpio_data_direction_register = gpio_controller + 0x10;
166
167
168         /* Use GPIO port B.  */
169         gpio_data_register = gpio_controller + 0x04;
170         gpio_data_direction_register = gpio_controller + 0x14;
171
172         /* Use GPIO port C.  */
173         gpio_data_register = gpio_controller + 0x08;
174         gpio_data_direction_register = gpio_controller + 0x18;
175
176         /* Use GPIO port D.  */
177         gpio_data_register = gpio_controller + 0x0c;
178         gpio_data_direction_register = gpio_controller + 0x1c;
179 #endif
180
181         /* Use GPIO port C.  */
182         gpio_data_register = gpio_controller + 0x08;
183         gpio_data_direction_register = gpio_controller + 0x18;
184
185         LOG_INFO("gpio_data_register      = %p", gpio_data_register);
186         LOG_INFO("gpio_data_direction_reg = %p", gpio_data_direction_register);
187         /*
188          * Configure bit 0 (TDO) as an input, and bits 1-5 (TDI, TCK
189          * TMS, TRST, SRST) as outputs.  Drive TDI and TCK low, and
190          * TMS/TRST/SRST high.
191          */
192         output_value = TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT;
193         *gpio_data_register = output_value;
194         nanosleep(&ep93xx_zzzz, NULL);
195
196         /*
197          * Configure the direction register.  1 = output, 0 = input.
198          */
199         *gpio_data_direction_register =
200                 TDI_BIT | TCK_BIT | TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT;
201
202         nanosleep(&ep93xx_zzzz, NULL);
203         return ERROR_OK;
204 }
205
206 static int ep93xx_quit(void)
207 {
208
209         return ERROR_OK;
210 }