1 /* dv-m68hc11spi.c -- Simulation of the 68HC11 SPI
2 Copyright (C) 2000, 2002, 2003, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
5 (From a driver model Contributed by Cygnus Solutions.)
7 This file is part of the program GDB, the GNU debugger.
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
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
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.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "dv-sockser.h"
28 #include "sim-assert.h"
33 m68hc11spi - m68hc11 SPI interface
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:
45 - Write collision detection
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.
72 static const struct hw_port_descriptor m68hc11spi_ports[] =
74 { "reset", RESET_PORT, 0, input_port, },
82 /* Information about next character to be transmited. */
83 unsigned char tx_char;
87 unsigned char rx_char;
88 unsigned char rx_clear_scsr;
89 unsigned char clk_pin;
91 /* SPI clock rate (twice the real clock). */
94 /* Periodic SPI event. */
95 struct hw_event* spi_event;
100 /* Finish off the partially created hw device. Attach our local
101 callbacks. Wire up our port names etc */
103 static hw_io_read_buffer_method m68hc11spi_io_read_buffer;
104 static hw_io_write_buffer_method m68hc11spi_io_write_buffer;
105 static hw_port_event_method m68hc11spi_port_event;
106 static hw_ioctl_method m68hc11spi_ioctl;
108 #define M6811_SPI_FIRST_REG (M6811_SPCR)
109 #define M6811_SPI_LAST_REG (M6811_SPDR)
113 attach_m68hc11spi_regs (struct hw *me,
114 struct m68hc11spi *controller)
116 hw_attach_address (hw_parent (me), M6811_IO_LEVEL, io_map,
118 M6811_SPI_LAST_REG - M6811_SPI_FIRST_REG + 1,
123 m68hc11spi_finish (struct hw *me)
125 struct m68hc11spi *controller;
127 controller = HW_ZALLOC (me, struct m68hc11spi);
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);
134 set_hw_ioctl (me, m68hc11spi_ioctl);
136 me->to_ioctl = m68hc11spi_ioctl;
139 /* Attach ourself to our parent bus. */
140 attach_m68hc11spi_regs (me, controller);
142 /* Initialize to reset state. */
143 controller->spi_event = NULL;
144 controller->rx_clear_scsr = 0;
149 /* An event arrives on an interrupt port */
152 m68hc11spi_port_event (struct hw *me,
159 struct m68hc11spi *controller;
163 controller = hw_data (me);
165 cpu = STATE_CPU (sd, 0);
170 HW_TRACE ((me, "SPI reset"));
172 /* Reset the state of SPI registers. */
173 controller->rx_clear_scsr = 0;
174 if (controller->spi_event)
176 hw_event_queue_deschedule (me, controller->spi_event);
177 controller->spi_event = 0;
181 m68hc11spi_io_write_buffer (me, &val, io_map,
182 (unsigned_word) M6811_SPCR, 1);
187 hw_abort (me, "Event on unknown port %d", my_port);
193 set_bit_port (struct hw *me, sim_cpu *cpu, int port, int mask, int value)
198 val = cpu->ios[port] | mask;
200 val = cpu->ios[port] & ~mask;
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);
208 /* When a character is sent/received by the SPI, the PD2..PD5 line
209 are driven by the following signals:
212 -----+---------+--------+---/-+-------
214 MISO +---------+--------+---/-+
216 CLK _______/ \____/ \__ CPOL=0, CPHA=0
218 \____/ \___/ CPOL=1, CPHA=0
220 __/ \____/ \___/ CPOL=0, CPHA=1
222 \____/ \____/ \__ CPOL=1, CPHA=1
225 \__________________________//___/
234 #define SPI_START_BYTE 0
235 #define SPI_START_BIT 1
236 #define SPI_MIDDLE_BIT 2
239 m68hc11spi_clock (struct hw *me, void *data)
242 struct m68hc11spi* controller;
244 int check_interrupt = 0;
246 controller = hw_data (me);
248 cpu = STATE_CPU (sd, 0);
250 /* Cleanup current event. */
251 if (controller->spi_event)
253 hw_event_queue_deschedule (me, controller->spi_event);
254 controller->spi_event = 0;
257 /* Change a bit of data at each two SPI event. */
258 if (controller->mode == SPI_START_BIT)
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;
266 else if (controller->mode == SPI_MIDDLE_BIT)
268 controller->mode = SPI_START_BIT;
271 if (controller->mode == SPI_START_BYTE)
273 /* Start a new SPI transfer. */
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);
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);
287 /* Transmit is now complete for this byte. */
288 if (controller->mode == SPI_START_BIT && controller->tx_bit < 0)
290 controller->rx_clear_scsr = 0;
291 cpu->ios[M6811_SPSR] |= M6811_SPIF;
292 if (cpu->ios[M6811_SPCR] & M6811_SPIE)
297 controller->spi_event = hw_event_queue_schedule (me, controller->clock,
303 interrupts_update_pending (&cpu->cpu_interrupts);
306 /* Flags of the SPCR register. */
307 io_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" },
320 /* Flags of the SPSR register. */
321 io_reg_desc spsr_desc[] = {
322 { M6811_SPIF, "SPIF ", "SPI Transfer Complete flag" },
323 { M6811_WCOL, "WCOL ", "Write Collision" },
324 { M6811_MODF, "MODF ", "Mode Fault" },
329 m68hc11spi_info (struct hw *me)
334 struct m68hc11spi *controller;
338 cpu = STATE_CPU (sd, 0);
339 controller = hw_data (me);
341 sim_io_printf (sd, "M68HC11 SPI:\n");
343 base = cpu_get_io_base (cpu);
345 val = cpu->ios[M6811_SPCR];
346 print_io_byte (sd, "SPCR", spcr_desc, val, base + M6811_SPCR);
347 sim_io_printf (sd, "\n");
349 val = cpu->ios[M6811_SPSR];
350 print_io_byte (sd, "SPSR", spsr_desc, val, base + M6811_SPSR);
351 sim_io_printf (sd, "\n");
353 if (controller->spi_event)
357 sim_io_printf (sd, " SPI has %d bits to send\n",
358 controller->tx_bit + 1);
359 t = hw_event_remain_time (me, controller->spi_event);
360 sim_io_printf (sd, " SPI current bit-cycle finished in %s\n",
361 cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE));
363 t += (controller->tx_bit + 1) * 2 * controller->clock;
364 sim_io_printf (sd, " SPI operation finished in %s\n",
365 cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE));
370 m68hc11spi_ioctl (struct hw *me,
371 hw_ioctl_request request,
374 m68hc11spi_info (me);
378 /* generic read/write */
381 m68hc11spi_io_read_buffer (struct hw *me,
388 struct m68hc11spi *controller;
392 HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
395 cpu = STATE_CPU (sd, 0);
396 controller = hw_data (me);
401 controller->rx_clear_scsr = cpu->ios[M6811_SCSR]
402 & (M6811_SPIF | M6811_WCOL | M6811_MODF);
405 val = cpu->ios[base];
409 if (controller->rx_clear_scsr)
411 cpu->ios[M6811_SPSR] &= ~controller->rx_clear_scsr;
412 controller->rx_clear_scsr = 0;
413 interrupts_update_pending (&cpu->cpu_interrupts);
415 val = controller->rx_char;
421 *((unsigned8*) dest) = val;
426 m68hc11spi_io_write_buffer (struct hw *me,
433 struct m68hc11spi *controller;
437 HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
440 cpu = STATE_CPU (sd, 0);
441 controller = hw_data (me);
443 val = *((const unsigned8*) source);
447 cpu->ios[M6811_SPCR] = val;
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))
454 controller->clock = 1;
458 controller->clock = 2;
462 controller->clock = 8;
466 controller->clock = 16;
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;
476 controller->clk_pin = 0;
478 set_bit_port (me, cpu, M6811_PORTD, (1 << 4), controller->clk_pin);
481 /* Can't write to SPSR. */
486 if (!(cpu->ios[M6811_SPCR] & M6811_SPE))
491 if (controller->rx_clear_scsr)
493 cpu->ios[M6811_SPSR] &= ~controller->rx_clear_scsr;
494 controller->rx_clear_scsr = 0;
495 interrupts_update_pending (&cpu->cpu_interrupts);
498 /* If transfer is taking place, a write to SPDR
499 generates a collision. */
500 if (controller->spi_event)
502 cpu->ios[M6811_SPSR] |= M6811_WCOL;
506 /* Refuse the write if there was no read of SPSR. */
509 /* Prepare to send a byte. */
510 controller->tx_char = val;
511 controller->mode = SPI_START_BYTE;
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;
518 cpu->ios[M6811_SPDR] = val;
520 /* Activate transmission. */
521 m68hc11spi_clock (me, NULL);
531 const struct hw_descriptor dv_m68hc11spi_descriptor[] = {
532 { "m68hc11spi", m68hc11spi_finish },
533 { "m68hc12spi", m68hc11spi_finish },