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