6fe759d34490446274ccc8e65e097527d87f5e69
[deliverable/binutils-gdb.git] / sim / m68hc11 / dv-m68hc11spi.c
1 /* dv-m68hc11spi.c -- Simulation of the 68HC11 SPI
2 Copyright (C) 2000-2021 Free Software Foundation, Inc.
3 Written by Stephane Carrez (stcarrez@nerim.fr)
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
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
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.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20
21 */
22
23 /* This must come before any other includes. */
24 #include "defs.h"
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
67 enum
68 {
69 RESET_PORT
70 };
71
72
73 static const struct hw_port_descriptor m68hc11spi_ports[] =
74 {
75 { "reset", RESET_PORT, 0, input_port, },
76 { NULL, },
77 };
78
79
80 /* SPI */
81 struct 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
104 static hw_io_read_buffer_method m68hc11spi_io_read_buffer;
105 static hw_io_write_buffer_method m68hc11spi_io_write_buffer;
106 static hw_port_event_method m68hc11spi_port_event;
107 static hw_ioctl_method m68hc11spi_ioctl;
108
109 #define M6811_SPI_FIRST_REG (M6811_SPCR)
110 #define M6811_SPI_LAST_REG (M6811_SPDR)
111
112
113 static void
114 attach_m68hc11spi_regs (struct hw *me,
115 struct m68hc11spi *controller)
116 {
117 hw_attach_address (hw_parent (me), M6811_IO_LEVEL, io_map,
118 M6811_SPI_FIRST_REG,
119 M6811_SPI_LAST_REG - M6811_SPI_FIRST_REG + 1,
120 me);
121 }
122
123 static void
124 m68hc11spi_finish (struct hw *me)
125 {
126 struct m68hc11spi *controller;
127
128 controller = HW_ZALLOC (me, struct m68hc11spi);
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
152 static void
153 m68hc11spi_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;
161 sim_cpu *cpu;
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
193 static void
194 set_bit_port (struct hw *me, sim_cpu *cpu, int port, int mask, int value)
195 {
196 uint8 val;
197
198 if (value)
199 val = cpu->ios[port] | mask;
200 else
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);
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
235 #define SPI_START_BYTE 0
236 #define SPI_START_BIT 1
237 #define SPI_MIDDLE_BIT 2
238
239 static void
240 m68hc11spi_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 }
267 else if (controller->mode == SPI_MIDDLE_BIT)
268 {
269 controller->mode = SPI_START_BIT;
270 }
271
272 if (controller->mode == SPI_START_BYTE)
273 {
274 /* Start a new SPI transfer. */
275
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
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. */
308 io_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. */
322 io_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
329 static void
330 m68hc11spi_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
358 sim_io_printf (sd, " SPI has %d bits to send\n",
359 controller->tx_bit + 1);
360 t = hw_event_remain_time (me, controller->spi_event);
361 sim_io_printf (sd, " SPI current bit-cycle finished in %s\n",
362 cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE));
363
364 t += (controller->tx_bit + 1) * 2 * controller->clock;
365 sim_io_printf (sd, " SPI operation finished in %s\n",
366 cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE));
367 }
368 }
369
370 static int
371 m68hc11spi_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
381 static unsigned
382 m68hc11spi_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;
414 interrupts_update_pending (&cpu->cpu_interrupts);
415 }
416 val = controller->rx_char;
417 break;
418
419 default:
420 return 0;
421 }
422 *((unsigned8*) dest) = val;
423 return 1;
424 }
425
426 static unsigned
427 m68hc11spi_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
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
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;
512 controller->mode = SPI_START_BYTE;
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
532 const struct hw_descriptor dv_m68hc11spi_descriptor[] = {
533 { "m68hc11spi", m68hc11spi_finish },
534 { "m68hc12spi", m68hc11spi_finish },
535 { NULL },
536 };
537
This page took 0.038594 seconds and 3 git commands to generate.