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