Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / sim / m68hc11 / dv-m68hc11spi.c
CommitLineData
e0709f50 1/* dv-m68hc11spi.c -- Simulation of the 68HC11 SPI
88b9d363 2 Copyright (C) 2000-2022 Free Software Foundation, Inc.
a685700c 3 Written by Stephane Carrez (stcarrez@nerim.fr)
e0709f50
AC
4 (From a driver model Contributed by Cygnus Solutions.)
5
6 This file is part of the program GDB, the GNU debugger.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
4744ac1b 10 the Free Software Foundation; either version 3 of the License, or
e0709f50 11 (at your option) any later version.
4744ac1b 12
e0709f50
AC
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
4744ac1b 17
e0709f50 18 You should have received a copy of the GNU General Public License
4744ac1b 19 along with this program. If not, see <http://www.gnu.org/licenses/>.
e0709f50
AC
20
21 */
22
6df01ab8
MF
23/* This must come before any other includes. */
24#include "defs.h"
e0709f50
AC
25
26#include "sim-main.h"
27#include "hw-main.h"
28#include "dv-sockser.h"
29#include "sim-assert.h"
30
31
32/* DEVICE
33
34 m68hc11spi - m68hc11 SPI interface
35
36
37 DESCRIPTION
38
39 Implements the m68hc11 Synchronous Serial Peripheral Interface
40 described in the m68hc11 user guide (Chapter 8 in pink book).
41 The SPI I/O controller is directly connected to the CPU
42 interrupt. The simulator implements:
43
44 - SPI clock emulation
45 - Data transfer
46 - Write collision detection
47
48
49 PROPERTIES
50
51 None
52
53
54 PORTS
55
56 reset (input)
57
58 Reset port. This port is only used to simulate a reset of the SPI
59 I/O controller. It should be connected to the RESET output of the cpu.
60
61 */
62
63
64
65/* port ID's */
66
67enum
68{
69 RESET_PORT
70};
71
72
73static const struct hw_port_descriptor m68hc11spi_ports[] =
74{
75 { "reset", RESET_PORT, 0, input_port, },
76 { NULL, },
77};
78
79
80/* SPI */
81struct m68hc11spi
82{
83 /* Information about next character to be transmited. */
84 unsigned char tx_char;
85 int tx_bit;
86 unsigned char mode;
87
88 unsigned char rx_char;
89 unsigned char rx_clear_scsr;
90 unsigned char clk_pin;
91
92 /* SPI clock rate (twice the real clock). */
93 unsigned int clock;
94
95 /* Periodic SPI event. */
96 struct hw_event* spi_event;
97};
98
99
100
101/* Finish off the partially created hw device. Attach our local
102 callbacks. Wire up our port names etc */
103
104static hw_io_read_buffer_method m68hc11spi_io_read_buffer;
105static hw_io_write_buffer_method m68hc11spi_io_write_buffer;
106static hw_port_event_method m68hc11spi_port_event;
107static hw_ioctl_method m68hc11spi_ioctl;
108
109#define M6811_SPI_FIRST_REG (M6811_SPCR)
110#define M6811_SPI_LAST_REG (M6811_SPDR)
111
112
113static void
114attach_m68hc11spi_regs (struct hw *me,
115 struct m68hc11spi *controller)
116{
63348d04 117 hw_attach_address (hw_parent (me), M6811_IO_LEVEL, io_map,
e0709f50
AC
118 M6811_SPI_FIRST_REG,
119 M6811_SPI_LAST_REG - M6811_SPI_FIRST_REG + 1,
120 me);
121}
122
123static void
124m68hc11spi_finish (struct hw *me)
125{
126 struct m68hc11spi *controller;
127
128 controller = HW_ZALLOC (me, struct m68hc11spi);
e0709f50
AC
129 set_hw_data (me, controller);
130 set_hw_io_read_buffer (me, m68hc11spi_io_read_buffer);
131 set_hw_io_write_buffer (me, m68hc11spi_io_write_buffer);
132 set_hw_ports (me, m68hc11spi_ports);
133 set_hw_port_event (me, m68hc11spi_port_event);
134#ifdef set_hw_ioctl
135 set_hw_ioctl (me, m68hc11spi_ioctl);
136#else
137 me->to_ioctl = m68hc11spi_ioctl;
138#endif
139
140 /* Attach ourself to our parent bus. */
141 attach_m68hc11spi_regs (me, controller);
142
143 /* Initialize to reset state. */
144 controller->spi_event = NULL;
145 controller->rx_clear_scsr = 0;
146}
147
148
149
150/* An event arrives on an interrupt port */
151
152static void
153m68hc11spi_port_event (struct hw *me,
154 int my_port,
155 struct hw *source,
156 int source_port,
157 int level)
158{
159 SIM_DESC sd;
160 struct m68hc11spi *controller;
6f64fd48 161 sim_cpu *cpu;
e0709f50
AC
162 unsigned8 val;
163
164 controller = hw_data (me);
165 sd = hw_system (me);
166 cpu = STATE_CPU (sd, 0);
167 switch (my_port)
168 {
169 case RESET_PORT:
170 {
171 HW_TRACE ((me, "SPI reset"));
172
173 /* Reset the state of SPI registers. */
174 controller->rx_clear_scsr = 0;
175 if (controller->spi_event)
176 {
177 hw_event_queue_deschedule (me, controller->spi_event);
178 controller->spi_event = 0;
179 }
180
181 val = 0;
182 m68hc11spi_io_write_buffer (me, &val, io_map,
183 (unsigned_word) M6811_SPCR, 1);
184 break;
185 }
186
187 default:
188 hw_abort (me, "Event on unknown port %d", my_port);
189 break;
190 }
191}
192
193static void
194set_bit_port (struct hw *me, sim_cpu *cpu, int port, int mask, int value)
195{
827ec39a
SC
196 uint8 val;
197
e0709f50 198 if (value)
827ec39a 199 val = cpu->ios[port] | mask;
e0709f50 200 else
827ec39a
SC
201 val = cpu->ios[port] & ~mask;
202
203 /* Set the new value and post an event to inform other devices
204 that pin 'port' changed. */
205 m68hc11cpu_set_port (me, cpu, port, val);
e0709f50
AC
206}
207
208
209/* When a character is sent/received by the SPI, the PD2..PD5 line
210 are driven by the following signals:
211
212 B7 B6
213 -----+---------+--------+---/-+-------
214 MOSI | | | | | |
215 MISO +---------+--------+---/-+
216 ____ ___
217 CLK _______/ \____/ \__ CPOL=0, CPHA=0
218 _______ ____ __
219 \____/ \___/ CPOL=1, CPHA=0
220 ____ ____ __
221 __/ \____/ \___/ CPOL=0, CPHA=1
222 __ ____ ___
223 \____/ \____/ \__ CPOL=1, CPHA=1
224
225 SS ___ ____
226 \__________________________//___/
227
228 MISO = PD2
229 MOSI = PD3
230 SCK = PD4
231 SS = PD5
232
233*/
234
4d72d17a
SC
235#define SPI_START_BYTE 0
236#define SPI_START_BIT 1
237#define SPI_MIDDLE_BIT 2
e0709f50 238
527aaa4a 239static void
e0709f50
AC
240m68hc11spi_clock (struct hw *me, void *data)
241{
242 SIM_DESC sd;
243 struct m68hc11spi* controller;
244 sim_cpu *cpu;
245 int check_interrupt = 0;
246
247 controller = hw_data (me);
248 sd = hw_system (me);
249 cpu = STATE_CPU (sd, 0);
250
251 /* Cleanup current event. */
252 if (controller->spi_event)
253 {
254 hw_event_queue_deschedule (me, controller->spi_event);
255 controller->spi_event = 0;
256 }
257
258 /* Change a bit of data at each two SPI event. */
259 if (controller->mode == SPI_START_BIT)
260 {
261 /* Reflect the bit value on bit 2 of port D. */
262 set_bit_port (me, cpu, M6811_PORTD, (1 << 2),
263 (controller->tx_char & (1 << controller->tx_bit)));
264 controller->tx_bit--;
265 controller->mode = SPI_MIDDLE_BIT;
266 }
4d72d17a 267 else if (controller->mode == SPI_MIDDLE_BIT)
e0709f50
AC
268 {
269 controller->mode = SPI_START_BIT;
270 }
271
4d72d17a
SC
272 if (controller->mode == SPI_START_BYTE)
273 {
274 /* Start a new SPI transfer. */
e0709f50 275
4d72d17a
SC
276 /* TBD: clear SS output. */
277 controller->mode = SPI_START_BIT;
278 controller->tx_bit = 7;
279 set_bit_port (me, cpu, M6811_PORTD, (1 << 4), ~controller->clk_pin);
280 }
281 else
282 {
283 /* Change the SPI clock at each event on bit 4 of port D. */
284 controller->clk_pin = ~controller->clk_pin;
285 set_bit_port (me, cpu, M6811_PORTD, (1 << 4), controller->clk_pin);
286 }
287
e0709f50
AC
288 /* Transmit is now complete for this byte. */
289 if (controller->mode == SPI_START_BIT && controller->tx_bit < 0)
290 {
291 controller->rx_clear_scsr = 0;
292 cpu->ios[M6811_SPSR] |= M6811_SPIF;
293 if (cpu->ios[M6811_SPCR] & M6811_SPIE)
294 check_interrupt = 1;
295 }
296 else
297 {
298 controller->spi_event = hw_event_queue_schedule (me, controller->clock,
299 m68hc11spi_clock,
300 NULL);
301 }
302
303 if (check_interrupt)
304 interrupts_update_pending (&cpu->cpu_interrupts);
305}
306
307/* Flags of the SPCR register. */
308io_reg_desc spcr_desc[] = {
309 { M6811_SPIE, "SPIE ", "Serial Peripheral Interrupt Enable" },
310 { M6811_SPE, "SPE ", "Serial Peripheral System Enable" },
311 { M6811_DWOM, "DWOM ", "Port D Wire-OR mode option" },
312 { M6811_MSTR, "MSTR ", "Master Mode Select" },
313 { M6811_CPOL, "CPOL ", "Clock Polarity" },
314 { M6811_CPHA, "CPHA ", "Clock Phase" },
315 { M6811_SPR1, "SPR1 ", "SPI Clock Rate Select" },
316 { M6811_SPR0, "SPR0 ", "SPI Clock Rate Select" },
317 { 0, 0, 0 }
318};
319
320
321/* Flags of the SPSR register. */
322io_reg_desc spsr_desc[] = {
323 { M6811_SPIF, "SPIF ", "SPI Transfer Complete flag" },
324 { M6811_WCOL, "WCOL ", "Write Collision" },
325 { M6811_MODF, "MODF ", "Mode Fault" },
326 { 0, 0, 0 }
327};
328
329static void
330m68hc11spi_info (struct hw *me)
331{
332 SIM_DESC sd;
333 uint16 base = 0;
334 sim_cpu *cpu;
335 struct m68hc11spi *controller;
336 uint8 val;
337
338 sd = hw_system (me);
339 cpu = STATE_CPU (sd, 0);
340 controller = hw_data (me);
341
342 sim_io_printf (sd, "M68HC11 SPI:\n");
343
344 base = cpu_get_io_base (cpu);
345
346 val = cpu->ios[M6811_SPCR];
347 print_io_byte (sd, "SPCR", spcr_desc, val, base + M6811_SPCR);
348 sim_io_printf (sd, "\n");
349
350 val = cpu->ios[M6811_SPSR];
351 print_io_byte (sd, "SPSR", spsr_desc, val, base + M6811_SPSR);
352 sim_io_printf (sd, "\n");
353
354 if (controller->spi_event)
355 {
356 signed64 t;
357
4d72d17a
SC
358 sim_io_printf (sd, " SPI has %d bits to send\n",
359 controller->tx_bit + 1);
e0709f50 360 t = hw_event_remain_time (me, controller->spi_event);
2990a9f4 361 sim_io_printf (sd, " SPI current bit-cycle finished in %s\n",
a685700c 362 cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE));
2990a9f4
SC
363
364 t += (controller->tx_bit + 1) * 2 * controller->clock;
365 sim_io_printf (sd, " SPI operation finished in %s\n",
a685700c 366 cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE));
e0709f50
AC
367 }
368}
369
370static int
371m68hc11spi_ioctl (struct hw *me,
372 hw_ioctl_request request,
373 va_list ap)
374{
375 m68hc11spi_info (me);
376 return 0;
377}
378
379/* generic read/write */
380
381static unsigned
382m68hc11spi_io_read_buffer (struct hw *me,
383 void *dest,
384 int space,
385 unsigned_word base,
386 unsigned nr_bytes)
387{
388 SIM_DESC sd;
389 struct m68hc11spi *controller;
390 sim_cpu *cpu;
391 unsigned8 val;
392
393 HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
394
395 sd = hw_system (me);
396 cpu = STATE_CPU (sd, 0);
397 controller = hw_data (me);
398
399 switch (base)
400 {
401 case M6811_SPSR:
402 controller->rx_clear_scsr = cpu->ios[M6811_SCSR]
403 & (M6811_SPIF | M6811_WCOL | M6811_MODF);
404
405 case M6811_SPCR:
406 val = cpu->ios[base];
407 break;
408
409 case M6811_SPDR:
410 if (controller->rx_clear_scsr)
411 {
412 cpu->ios[M6811_SPSR] &= ~controller->rx_clear_scsr;
413 controller->rx_clear_scsr = 0;
4d72d17a 414 interrupts_update_pending (&cpu->cpu_interrupts);
e0709f50
AC
415 }
416 val = controller->rx_char;
417 break;
418
419 default:
420 return 0;
421 }
422 *((unsigned8*) dest) = val;
423 return 1;
424}
425
426static unsigned
427m68hc11spi_io_write_buffer (struct hw *me,
428 const void *source,
429 int space,
430 unsigned_word base,
431 unsigned nr_bytes)
432{
433 SIM_DESC sd;
434 struct m68hc11spi *controller;
435 sim_cpu *cpu;
436 unsigned8 val;
437
438 HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
439
440 sd = hw_system (me);
441 cpu = STATE_CPU (sd, 0);
442 controller = hw_data (me);
443
444 val = *((const unsigned8*) source);
445 switch (base)
446 {
447 case M6811_SPCR:
448 cpu->ios[M6811_SPCR] = val;
449
450 /* The SPI clock rate is 2, 4, 16, 32 of the internal CPU clock.
451 We have to drive the clock pin and need a 2x faster clock. */
452 switch (val & (M6811_SPR1 | M6811_SPR0))
453 {
454 case 0:
455 controller->clock = 1;
456 break;
457
458 case 1:
459 controller->clock = 2;
460 break;
461
462 case 2:
463 controller->clock = 8;
464 break;
465
466 default:
467 controller->clock = 16;
468 break;
469 }
470
471 /* Set the clock pin. */
472 if ((val & M6811_CPOL)
473 && (controller->spi_event == 0
474 || ((val & M6811_CPHA) && controller->mode == 1)))
475 controller->clk_pin = 1;
476 else
477 controller->clk_pin = 0;
478
479 set_bit_port (me, cpu, M6811_PORTD, (1 << 4), controller->clk_pin);
480 break;
481
482 /* Can't write to SPSR. */
483 case M6811_SPSR:
484 break;
485
486 case M6811_SPDR:
487 if (!(cpu->ios[M6811_SPCR] & M6811_SPE))
488 {
489 return 0;
490 }
491
4d72d17a
SC
492 if (controller->rx_clear_scsr)
493 {
494 cpu->ios[M6811_SPSR] &= ~controller->rx_clear_scsr;
495 controller->rx_clear_scsr = 0;
496 interrupts_update_pending (&cpu->cpu_interrupts);
497 }
498
e0709f50
AC
499 /* If transfer is taking place, a write to SPDR
500 generates a collision. */
501 if (controller->spi_event)
502 {
503 cpu->ios[M6811_SPSR] |= M6811_WCOL;
504 break;
505 }
506
507 /* Refuse the write if there was no read of SPSR. */
508 /* ???? TBD. */
509
510 /* Prepare to send a byte. */
511 controller->tx_char = val;
4d72d17a 512 controller->mode = SPI_START_BYTE;
e0709f50
AC
513
514 /* Toggle clock pin internal value when CPHA is 0 so that
515 it will really change in the middle of a bit. */
516 if (!(cpu->ios[M6811_SPCR] & M6811_CPHA))
517 controller->clk_pin = ~controller->clk_pin;
518
519 cpu->ios[M6811_SPDR] = val;
520
521 /* Activate transmission. */
522 m68hc11spi_clock (me, NULL);
523 break;
524
525 default:
526 return 0;
527 }
528 return nr_bytes;
529}
530
531
532const struct hw_descriptor dv_m68hc11spi_descriptor[] = {
b93775f5
SC
533 { "m68hc11spi", m68hc11spi_finish },
534 { "m68hc12spi", m68hc11spi_finish },
e0709f50
AC
535 { NULL },
536};
537
This page took 1.394786 seconds and 4 git commands to generate.