openocd: fix SPDX tag format for files .c
[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 uint8_t *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 = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
114                         MAP_SHARED, dev_mem_fd, 0x80930000);
115         if (syscon == MAP_FAILED) {
116                 LOG_ERROR("mmap: %s", strerror(errno));
117                 return ERROR_JTAG_INIT_FAILED;
118         }
119
120         uint32_t devicecfg = *((volatile uint32_t *)((uintptr_t)syscon + 0x80));
121         *((volatile uint32_t *)((uintptr_t)syscon + 0xc0)) = 0xaa;
122         *((volatile uint32_t *)((uintptr_t)syscon + 0x80)) = devicecfg | 0x08000000;
123
124         munmap(syscon, 4096);
125
126         return ERROR_OK;
127 }
128
129 static int ep93xx_init(void)
130 {
131         int ret;
132
133         bitbang_interface = &ep93xx_bitbang;
134
135         ep93xx_zzzz.tv_sec = 0;
136         ep93xx_zzzz.tv_nsec = 10000000;
137
138         dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
139         if (dev_mem_fd < 0) {
140                 LOG_ERROR("open: %s", strerror(errno));
141                 return ERROR_JTAG_INIT_FAILED;
142         }
143
144         gpio_controller = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
145                                 MAP_SHARED, dev_mem_fd, 0x80840000);
146         if (gpio_controller == MAP_FAILED) {
147                 LOG_ERROR("mmap: %s", strerror(errno));
148                 close(dev_mem_fd);
149                 return ERROR_JTAG_INIT_FAILED;
150         }
151
152         ret = set_gonk_mode();
153         if (ret != ERROR_OK) {
154                 munmap(gpio_controller, 4096);
155                 close(dev_mem_fd);
156                 return ret;
157         }
158
159 #if 0
160         /* Use GPIO port A.  */
161         gpio_data_register = gpio_controller + 0x00;
162         gpio_data_direction_register = gpio_controller + 0x10;
163
164
165         /* Use GPIO port B.  */
166         gpio_data_register = gpio_controller + 0x04;
167         gpio_data_direction_register = gpio_controller + 0x14;
168
169         /* Use GPIO port C.  */
170         gpio_data_register = gpio_controller + 0x08;
171         gpio_data_direction_register = gpio_controller + 0x18;
172
173         /* Use GPIO port D.  */
174         gpio_data_register = gpio_controller + 0x0c;
175         gpio_data_direction_register = gpio_controller + 0x1c;
176 #endif
177
178         /* Use GPIO port C.  */
179         gpio_data_register = gpio_controller + 0x08;
180         gpio_data_direction_register = gpio_controller + 0x18;
181
182         LOG_INFO("gpio_data_register      = %p", gpio_data_register);
183         LOG_INFO("gpio_data_direction_reg = %p", gpio_data_direction_register);
184         /*
185          * Configure bit 0 (TDO) as an input, and bits 1-5 (TDI, TCK
186          * TMS, TRST, SRST) as outputs.  Drive TDI and TCK low, and
187          * TMS/TRST/SRST high.
188          */
189         output_value = TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT;
190         *gpio_data_register = output_value;
191         nanosleep(&ep93xx_zzzz, NULL);
192
193         /*
194          * Configure the direction register.  1 = output, 0 = input.
195          */
196         *gpio_data_direction_register =
197                 TDI_BIT | TCK_BIT | TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT;
198
199         nanosleep(&ep93xx_zzzz, NULL);
200         return ERROR_OK;
201 }
202
203 static int ep93xx_quit(void)
204 {
205
206         return ERROR_OK;
207 }