sim: allow the environment configure option everywhere
[external/binutils.git] / sim / m68hc11 / dv-m68hc11spi.c
1 /*  dv-m68hc11spi.c -- Simulation of the 68HC11 SPI
2     Copyright (C) 2000-2016 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