dv-m68hc11spi.c 13 KB

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