embox

Форк
0
373 строки · 10.6 Кб
1
/**
2
 * @file socfpga.c
3
 * @brief
4
 * @author Denis Deryugin <deryugin.denis@gmail.com>
5
 * @version
6
 * @date 24.01.2020
7
 */
8
#include <errno.h>
9
#include <string.h>
10
#include <unistd.h>
11

12
#include <drivers/common/memory.h>
13
#include <drivers/fpga.h>
14
#include <embox/unit.h>
15
#include <framework/mod/options.h>
16
#include <kernel/irq.h>
17
#include <kernel/panic.h>
18
#include <hal/reg.h>
19
#include <util/log.h>
20

21
#define SOCFPGA_L3_REGS             0xFF800000
22
#define SOCFPGA_L3_REMAP            (SOCFPGA_L3_REGS + 0x00)
23
#define SOCFPGA_SDRAM_REGS          0xFFC20000
24
#define SOCFPGA_SDRAM_CONFIG        (SOCFPGA_SDRAM_REGS + 0x5080)
25
#define SOCFPGA_RESETMGR_REGS       0xFFD05000
26
#define SOCFPGA_RESETMGR_AXI_BRIDGE (SOCFPGA_RESETMGR_REGS + 0x1C)
27
#define SOCFPGA_SYSMGR_REGS         0xFFD08000
28
#define SOCFPGA_SYSMGR_INTF         (SOCFPGA_SYSMGR_REGS + 0x28)
29

30
#define SOCFPGA_MGR_STAT            0x00
31
# define SOCFPGA_MODE_MASK          0x7
32
# define SOCFPGA_MODE_OFF           0x0
33
# define SOCFPGA_MODE_RESET         0x1
34
# define SOCFPGA_MODE_CONFIG        0x2
35
# define SOCFPGA_MODE_INIT          0x3
36
# define SOCFPGA_MODE_USER          0x4
37
# define SOCFPGA_MODE_UNKNOWN       0x5
38
#define SOCFPGA_MGR_CTRL            0x04
39
# define SOCFPGA_CTRL_EN            (1 << 0)
40
# define SOCFPGA_CTRL_NCE           (1 << 1)
41
# define SOCFPGA_CTRL_NCONFIGPULL   (1 << 2)
42
# define SOCFPGA_CTRL_CDRATIO_OFFT  6
43
# define SOCFPGA_CTRL_AXICFEN       (1 << 8)
44
# define SOCFPGA_CTRL_CFGWDTH       (1 << 9)
45
#define SOCFPGA_MGR_DCLKCNT         0x08
46
#define SOCFPGA_MGR_DCLKSTAT        0x0C
47
# define SOCFPGA_DCLKSTAT_DONE      (1 << 0) /* W1C */
48
#define SOCFPGA_MGR_GPO             0x10
49
#define SOCFPGA_MGR_GPI             0x14
50
#define SOCFPGA_MGR_MISCI           0x18
51

52
#define SOCFPGA_MGR_GPIO_INTEN          0x830
53
#define SOCFPGA_MGR_GPIO_INTMASK        0x834
54
#define SOCFPGA_MGR_GPIO_INTTYPE_LEVEL  0x838
55
#define SOCFPGA_MGR_GPIO_INT_POLARITY   0x83c
56
#define SOCFPGA_MGR_GPIO_INTSTATUS      0x840
57
#define SOCFPGA_MGR_GPIO_RAW_INTSTATUS  0x848
58
#define SOCFPGA_MGR_GPIO_PORTA_EOI      0x84c
59
#define SOCFPGA_MGR_GPIO_EXT_PORTA      0x850
60
# define SOCFPGA_GPIO_EXT_PORTA_NSP     (1 << 9)
61
# define SOCFPGA_GPIO_EXT_PORTA_CDP     (1 << 10)
62
#define SOCFPGA_MGR_GPIO_LS_SYNC        0x860
63
#define SOCFPGA_MGR_GPIO_VER_ID_CODE    0x86C
64
#define SOCFPGA_MGR_GPIO_CONFIG_REG2    0x870
65
#define SOCFPGA_MGR_GPIO_CONFIG_REG1    0x874
66

67
#define TIMEOUT 10000
68

69
/**
70
 * @brief Reproduce `bridge_enable_handoff` command from u-boot
71
 */
72
static void bridge_enable_handoff(void) {
73
#if 0
74
	/* This code reprocudes "bridge_enable_handoff" from u-boot */
75

76
	/* Pointer to some u-boot function. TODO: disassemble to figure out
77
	 * what is being done here */
78
	static const int (*fpga2sdram_apply)(void) = (void *) 0x3ff7d52c;
79
	REG32_STORE(SOCFPGA_SYSMGR_INTF, 0);
80
	fpga2sdram_apply();
81
	REG32_STORE(SOCFPGA_SDRAM_CONFIG, 0);
82
	REG32_STORE(SOCFPGA_RESETMGR_AXI_BRIDGE, 0);
83
	REG32_STORE(SOCFPGA_L3_REMAP, 0x19);
84
#endif
85
}
86

87
struct socfpga {
88
	uintptr_t mgr_base;
89
	uintptr_t mgr_data_addr;
90
};
91

92
static void socfpga_or(struct socfpga *socfpga, int offt, uint32_t val) {
93
	uint32_t tmp = REG32_LOAD(socfpga->mgr_base + offt);
94

95
	REG32_STORE(socfpga->mgr_base + offt, val | tmp);
96
}
97

98
static void socfpga_clear(struct socfpga *socfpga, int offt, uint32_t val) {
99
	uint32_t tmp = REG32_LOAD(socfpga->mgr_base + offt);
100

101
	REG32_STORE(socfpga->mgr_base + offt, tmp & ~val);
102
}
103

104
static uint32_t socfpga_read(struct socfpga *socfpga, int offt) {
105
	return REG32_LOAD(socfpga->mgr_base + offt);
106
}
107

108
static void socfpga_write(struct socfpga *socfpga, int offt, uint32_t val) {
109
	REG32_STORE(socfpga->mgr_base + offt, val);
110
}
111

112
static void socfpga_data_write(struct socfpga *socfpga, uint32_t val) {
113
	REG32_STORE(socfpga->mgr_data_addr, val);
114
}
115

116
static void socfpga_regdump(struct socfpga *socfpga) {
117
	log_debug(" STAT             %08x",
118
			socfpga_read(socfpga, SOCFPGA_MGR_STAT));
119
	log_debug(" CTRL             %08x",
120
			socfpga_read(socfpga, SOCFPGA_MGR_CTRL));
121
	log_debug(" DCLKCNT          %08x",
122
			socfpga_read(socfpga, SOCFPGA_MGR_DCLKCNT));
123
	log_debug(" DCLKSTAT         %08x",
124
			socfpga_read(socfpga, SOCFPGA_MGR_DCLKSTAT));
125
	log_debug(" GPO              %08x",
126
			socfpga_read(socfpga, SOCFPGA_MGR_GPO));
127
	log_debug(" GPI              %08x",
128
			socfpga_read(socfpga, SOCFPGA_MGR_GPI));
129
	log_debug(" MISCI            %08x",
130
			socfpga_read(socfpga, SOCFPGA_MGR_MISCI));
131
	log_debug(" GPIO_INTEN       %08x",
132
			socfpga_read(socfpga, SOCFPGA_MGR_GPIO_INTEN));
133
	log_debug(" GPIO_INTMASK     %08x",
134
			socfpga_read(socfpga, SOCFPGA_MGR_GPIO_INTMASK));
135
	log_debug(" GPIO_INTTYPE_LEV %08x",
136
			socfpga_read(socfpga, SOCFPGA_MGR_GPIO_INTTYPE_LEVEL));
137
	log_debug(" GPIO_INT_POLARIT %08x",
138
			socfpga_read(socfpga, SOCFPGA_MGR_GPIO_INT_POLARITY));
139
	log_debug(" GPIO_INTSTATUS   %08x",
140
			socfpga_read(socfpga, SOCFPGA_MGR_GPIO_INTSTATUS));
141
	log_debug(" GPIO_RAW_INTSTAT %08x",
142
			socfpga_read(socfpga, SOCFPGA_MGR_GPIO_RAW_INTSTATUS));
143
	log_debug(" GPIO_PORTA_EOI   %08x",
144
			socfpga_read(socfpga, SOCFPGA_MGR_GPIO_PORTA_EOI));
145
	log_debug(" GPIO_EXT_PORTA   %08x",
146
			socfpga_read(socfpga, SOCFPGA_MGR_GPIO_EXT_PORTA));
147
	log_debug(" GPIO_LS_SYNC     %08x",
148
			socfpga_read(socfpga, SOCFPGA_MGR_GPIO_LS_SYNC));
149
	log_debug(" GPIO_VER_ID_CODE %08x",
150
			socfpga_read(socfpga, SOCFPGA_MGR_GPIO_VER_ID_CODE));
151
	log_debug(" GPIO_CONFIG_REG2 %08x",
152
			socfpga_read(socfpga, SOCFPGA_MGR_GPIO_CONFIG_REG2));
153
	log_debug(" GPIO_CONFIG_REG1 %08x",
154
			socfpga_read(socfpga, SOCFPGA_MGR_GPIO_CONFIG_REG1));
155
}
156

157
static uint32_t socfpga_mode(struct socfpga *socfpga) {
158
	uint32_t ret =
159
		socfpga_read(socfpga, SOCFPGA_MGR_STAT) & SOCFPGA_MODE_MASK;
160
	switch (ret) {
161
	case SOCFPGA_MODE_MASK:
162
	case SOCFPGA_MODE_OFF:
163
	case SOCFPGA_MODE_RESET:
164
	case SOCFPGA_MODE_CONFIG:
165
	case SOCFPGA_MODE_INIT:
166
	case SOCFPGA_MODE_USER:
167
	case SOCFPGA_MODE_UNKNOWN:
168
		return ret;
169
	default:
170
		log_error("incorrect socfpga state: 0x%x", ret);
171
		return 0;
172
	}
173
}
174

175
static int socfpga_mode_wait(struct socfpga *socfpga, uint32_t mode) {
176
	int t = TIMEOUT;
177

178
	while (t--) {
179
		if (socfpga_mode(socfpga) == mode) {
180
			break;
181
		}
182

183
		usleep(100);
184
	}
185

186
	if (t <= 0) {
187
		log_error("FPGA reset timeout!");
188
		return -ETIMEDOUT;
189
	}
190

191
	return 0;
192
}
193

194
static int socfpga_reset(struct socfpga *socfpga) {
195
	/* Enable FPGA.
196
	 * Note: this step is not mentioned in datasheet,
197
	 * but is done in Linux driver */
198
	socfpga_or(socfpga, SOCFPGA_MGR_CTRL,
199
			SOCFPGA_CTRL_EN);
200

201
	/* Enter reset state */
202
	socfpga_or(socfpga, SOCFPGA_MGR_CTRL,
203
			SOCFPGA_CTRL_NCONFIGPULL);
204

205
	if (socfpga_mode_wait(socfpga, SOCFPGA_MODE_RESET)) {
206
		return -ETIMEDOUT;
207
	}
208

209
	/* Exit reset phase */
210
	socfpga_clear(socfpga, SOCFPGA_MGR_CTRL,
211
			SOCFPGA_CTRL_NCONFIGPULL);
212

213
	return 0;
214
}
215

216

217
/**
218
 * @brief Corresponds to Power Up Phase, Reset Phase in docs
219
 */
220
static int socfpga_config_init(struct fpga *fpga) {
221
	struct socfpga *socfpga = fpga->priv;
222
	uint32_t tmp;
223
	int err;
224

225
	/* TODO: figure out what values should be actualy passed.
226
	 * According to manual, "You must set the cdratio and
227
	 * cfgwdth bits appropriatly" */
228
	tmp = socfpga_read(socfpga, SOCFPGA_MGR_CTRL);
229
	tmp &= ~SOCFPGA_CTRL_CDRATIO_OFFT;
230
	tmp &= ~SOCFPGA_CTRL_CFGWDTH;
231
	/* TODO: Set correct values */
232
	socfpga_write(socfpga, SOCFPGA_MGR_CTRL, tmp);
233

234
	err = socfpga_reset(socfpga);
235
	if (err != 0) {
236
		return err;
237
	}
238

239
	err = socfpga_mode_wait(socfpga, SOCFPGA_MODE_CONFIG);
240
	if (err != 0) {
241
		return -ETIMEDOUT;
242
	}
243

244
	/* Enable data transfer to FPGA */
245
	socfpga_or(socfpga, SOCFPGA_MGR_CTRL, SOCFPGA_CTRL_AXICFEN);
246

247
	return 0;
248
}
249

250
/**
251
 * @brief Corresponds to Configuration Phase in docs
252
 */
253
static int socfpga_config_write(struct fpga *fpga, const uint8_t *buf, size_t len) {
254
	struct socfpga *socfpga = fpga->priv;
255
	uint32_t *buf32 = (uint32_t *) buf;
256
	uint32_t tmp;
257

258
	while (len > sizeof(uint32_t)) {
259
		socfpga_data_write(socfpga, *buf32);
260
		buf32++;
261
		len -= 4;
262
	}
263

264
	if (len) {
265
		tmp = 0;
266
		memcpy(buf32, &tmp, len);
267
		socfpga_data_write(socfpga, tmp);
268
	}
269

270
	return 0;
271
}
272

273
/**
274
 * @brief Corresponds to Initialization Phase and User Mode in docs
275
 */
276
static int socfpga_config_complete(struct fpga *fpga) {
277
	struct socfpga *socfpga = fpga->priv;
278
	int err;
279
	int timeout = TIMEOUT;
280
	uint32_t tmp;
281

282
	/* Wait for config write done */
283
	while (timeout-- >= 0) {
284
		tmp = socfpga_read(socfpga, SOCFPGA_MGR_GPIO_EXT_PORTA);
285
		if ((tmp & SOCFPGA_GPIO_EXT_PORTA_NSP) &&
286
			(tmp & SOCFPGA_GPIO_EXT_PORTA_CDP)) {
287
			break;
288
		}
289
		usleep(100);
290
	}
291

292
	if (timeout <= 0) {
293
		log_error("Timeout waiting for config write finish!");
294
		return -ETIMEDOUT;
295
	}
296

297
	/* Disable data transfer */
298
	socfpga_clear(socfpga, SOCFPGA_MGR_CTRL, SOCFPGA_CTRL_AXICFEN);
299

300
	/* Send 4 clocks to FPGA.
301
	 * Note: This is not mentioned in docs, but for some reason
302
	 * HPS LED control example fails without this */
303
	socfpga_write(socfpga, SOCFPGA_MGR_DCLKSTAT,
304
			SOCFPGA_DCLKSTAT_DONE); /* W1C */
305
	socfpga_write(socfpga, SOCFPGA_MGR_DCLKCNT, 4);
306
	timeout = TIMEOUT;
307
	while (timeout-- >= 0) {
308
		tmp = socfpga_read(socfpga, SOCFPGA_MGR_DCLKSTAT);
309
		if (tmp & SOCFPGA_DCLKSTAT_DONE) {
310
			break;
311
		}
312
		usleep(100);
313
	}
314
	if (timeout <= 0) {
315
		log_error("Timeout waiting for dclk!");
316
		return -ETIMEDOUT;
317
	}
318

319
	err = socfpga_mode_wait(socfpga, SOCFPGA_MODE_USER);
320
	if (err != 0) {
321
		log_error("Timeout switching to User Mode!");
322
		return err;
323
	}
324

325
	/* Disconnect FPGA manager. Note: this is not required by
326
	 * the manual, but is done in Linux driver */
327
	socfpga_clear(socfpga, SOCFPGA_MGR_CTRL, SOCFPGA_CTRL_EN);
328

329
	return 0;
330
}
331

332
static struct fpga_ops socfpga_fpga_ops = {
333
	.config_init     = socfpga_config_init,
334
	.config_write    = socfpga_config_write,
335
	.config_complete = socfpga_config_complete,
336
};
337

338
#define FPGA_MGR_BASE OPTION_GET(NUMBER, mgr_base_addr)
339
#define FPGA_MGR_DATA OPTION_GET(NUMBER, mgr_data_addr)
340
static struct socfpga socfpga0 = {
341
	.mgr_base      = FPGA_MGR_BASE,
342
	.mgr_data_addr = FPGA_MGR_DATA,
343
};
344
PERIPH_MEMORY_DEFINE(socfpga_mgr,      FPGA_MGR_BASE, 0x878);
345
PERIPH_MEMORY_DEFINE(socfpga_mgr_data, FPGA_MGR_DATA, 0x4);
346

347
/* TODO: this mapping should be moved to corresponding modules, but
348
 * for now there are no modules for L3, SDRAM and System Manager, so
349
 * these mappings are places where are they needed */
350
PERIPH_MEMORY_DEFINE(socfpga_l3,       SOCFPGA_L3_REGS,       0x1000);
351
PERIPH_MEMORY_DEFINE(socfpga_sdram,    SOCFPGA_SDRAM_REGS,    0x6000);
352
PERIPH_MEMORY_DEFINE(socfpga_resetmgr, SOCFPGA_RESETMGR_REGS, 0x1000);
353
PERIPH_MEMORY_DEFINE(socfpga_sysmgr,   SOCFPGA_SYSMGR_REGS,   0x1000);
354

355
static irq_return_t socfpga_irq_handler(unsigned int irq_nr, void *data) {
356
	log_debug("enter irq");
357
	return IRQ_HANDLED;
358
}
359

360
EMBOX_UNIT_INIT(socfpga_init);
361
static int socfpga_init(void) {
362
	bridge_enable_handoff();
363

364
	fpga_register(&socfpga_fpga_ops, &socfpga0);
365

366
	socfpga_regdump(&socfpga0);
367

368
	return irq_attach(OPTION_GET(NUMBER, irq_num),
369
	                  socfpga_irq_handler,
370
	                  0,
371
	                  NULL,
372
	                  "socfpga IRQ handler");
373
}
374

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.