1/*  dv-m68hc11spi.c -- Simulation of the 68HC11 SPI
2    Copyright (C) 2000, 2002, 2003, 2007 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
65enum
66{
67  RESET_PORT
68};
69
70
71static const struct hw_port_descriptor m68hc11spi_ports[] =
72{
73  { "reset", RESET_PORT, 0, input_port, },
74  { NULL, },
75};
76
77
78/* SPI */
79struct 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
102static hw_io_read_buffer_method m68hc11spi_io_read_buffer;
103static hw_io_write_buffer_method m68hc11spi_io_write_buffer;
104static hw_port_event_method m68hc11spi_port_event;
105static hw_ioctl_method m68hc11spi_ioctl;
106
107#define M6811_SPI_FIRST_REG (M6811_SPCR)
108#define M6811_SPI_LAST_REG  (M6811_SPDR)
109
110
111static void
112attach_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
121static void
122m68hc11spi_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
150static void
151m68hc11spi_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
191static void
192set_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
237void
238m68hc11spi_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.  */
306io_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.  */
320io_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
327static void
328m68hc11spi_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
368static int
369m68hc11spi_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
379static unsigned
380m68hc11spi_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
424static unsigned
425m68hc11spi_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
530const struct hw_descriptor dv_m68hc11spi_descriptor[] = {
531  { "m68hc11spi", m68hc11spi_finish },
532  { "m68hc12spi", m68hc11spi_finish },
533  { NULL },
534};
535
536