2
0

sh_serial.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. /*
  2. * QEMU SCI/SCIF serial port emulation
  3. *
  4. * Copyright (c) 2007 Magnus Damm
  5. *
  6. * Based on serial.c - QEMU 16450 UART emulation
  7. * Copyright (c) 2003-2004 Fabrice Bellard
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a copy
  10. * of this software and associated documentation files (the "Software"), to deal
  11. * in the Software without restriction, including without limitation the rights
  12. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. * copies of the Software, and to permit persons to whom the Software is
  14. * furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. * THE SOFTWARE.
  26. */
  27. #include "hw.h"
  28. #include "sh.h"
  29. #include "char/char.h"
  30. #include "exec/address-spaces.h"
  31. //#define DEBUG_SERIAL
  32. #define SH_SERIAL_FLAG_TEND (1 << 0)
  33. #define SH_SERIAL_FLAG_TDE (1 << 1)
  34. #define SH_SERIAL_FLAG_RDF (1 << 2)
  35. #define SH_SERIAL_FLAG_BRK (1 << 3)
  36. #define SH_SERIAL_FLAG_DR (1 << 4)
  37. #define SH_RX_FIFO_LENGTH (16)
  38. typedef struct {
  39. MemoryRegion iomem;
  40. MemoryRegion iomem_p4;
  41. MemoryRegion iomem_a7;
  42. uint8_t smr;
  43. uint8_t brr;
  44. uint8_t scr;
  45. uint8_t dr; /* ftdr / tdr */
  46. uint8_t sr; /* fsr / ssr */
  47. uint16_t fcr;
  48. uint8_t sptr;
  49. uint8_t rx_fifo[SH_RX_FIFO_LENGTH]; /* frdr / rdr */
  50. uint8_t rx_cnt;
  51. uint8_t rx_tail;
  52. uint8_t rx_head;
  53. int freq;
  54. int feat;
  55. int flags;
  56. int rtrg;
  57. CharDriverState *chr;
  58. qemu_irq eri;
  59. qemu_irq rxi;
  60. qemu_irq txi;
  61. qemu_irq tei;
  62. qemu_irq bri;
  63. } sh_serial_state;
  64. static void sh_serial_clear_fifo(sh_serial_state * s)
  65. {
  66. memset(s->rx_fifo, 0, SH_RX_FIFO_LENGTH);
  67. s->rx_cnt = 0;
  68. s->rx_head = 0;
  69. s->rx_tail = 0;
  70. }
  71. static void sh_serial_write(void *opaque, hwaddr offs,
  72. uint64_t val, unsigned size)
  73. {
  74. sh_serial_state *s = opaque;
  75. unsigned char ch;
  76. #ifdef DEBUG_SERIAL
  77. printf("sh_serial: write offs=0x%02x val=0x%02x\n",
  78. offs, val);
  79. #endif
  80. switch(offs) {
  81. case 0x00: /* SMR */
  82. s->smr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0x7b : 0xff);
  83. return;
  84. case 0x04: /* BRR */
  85. s->brr = val;
  86. return;
  87. case 0x08: /* SCR */
  88. /* TODO : For SH7751, SCIF mask should be 0xfb. */
  89. s->scr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0xfa : 0xff);
  90. if (!(val & (1 << 5)))
  91. s->flags |= SH_SERIAL_FLAG_TEND;
  92. if ((s->feat & SH_SERIAL_FEAT_SCIF) && s->txi) {
  93. qemu_set_irq(s->txi, val & (1 << 7));
  94. }
  95. if (!(val & (1 << 6))) {
  96. qemu_set_irq(s->rxi, 0);
  97. }
  98. return;
  99. case 0x0c: /* FTDR / TDR */
  100. if (s->chr) {
  101. ch = val;
  102. qemu_chr_fe_write(s->chr, &ch, 1);
  103. }
  104. s->dr = val;
  105. s->flags &= ~SH_SERIAL_FLAG_TDE;
  106. return;
  107. #if 0
  108. case 0x14: /* FRDR / RDR */
  109. ret = 0;
  110. break;
  111. #endif
  112. }
  113. if (s->feat & SH_SERIAL_FEAT_SCIF) {
  114. switch(offs) {
  115. case 0x10: /* FSR */
  116. if (!(val & (1 << 6)))
  117. s->flags &= ~SH_SERIAL_FLAG_TEND;
  118. if (!(val & (1 << 5)))
  119. s->flags &= ~SH_SERIAL_FLAG_TDE;
  120. if (!(val & (1 << 4)))
  121. s->flags &= ~SH_SERIAL_FLAG_BRK;
  122. if (!(val & (1 << 1)))
  123. s->flags &= ~SH_SERIAL_FLAG_RDF;
  124. if (!(val & (1 << 0)))
  125. s->flags &= ~SH_SERIAL_FLAG_DR;
  126. if (!(val & (1 << 1)) || !(val & (1 << 0))) {
  127. if (s->rxi) {
  128. qemu_set_irq(s->rxi, 0);
  129. }
  130. }
  131. return;
  132. case 0x18: /* FCR */
  133. s->fcr = val;
  134. switch ((val >> 6) & 3) {
  135. case 0:
  136. s->rtrg = 1;
  137. break;
  138. case 1:
  139. s->rtrg = 4;
  140. break;
  141. case 2:
  142. s->rtrg = 8;
  143. break;
  144. case 3:
  145. s->rtrg = 14;
  146. break;
  147. }
  148. if (val & (1 << 1)) {
  149. sh_serial_clear_fifo(s);
  150. s->sr &= ~(1 << 1);
  151. }
  152. return;
  153. case 0x20: /* SPTR */
  154. s->sptr = val & 0xf3;
  155. return;
  156. case 0x24: /* LSR */
  157. return;
  158. }
  159. }
  160. else {
  161. switch(offs) {
  162. #if 0
  163. case 0x0c:
  164. ret = s->dr;
  165. break;
  166. case 0x10:
  167. ret = 0;
  168. break;
  169. #endif
  170. case 0x1c:
  171. s->sptr = val & 0x8f;
  172. return;
  173. }
  174. }
  175. fprintf(stderr, "sh_serial: unsupported write to 0x%02"
  176. HWADDR_PRIx "\n", offs);
  177. abort();
  178. }
  179. static uint64_t sh_serial_read(void *opaque, hwaddr offs,
  180. unsigned size)
  181. {
  182. sh_serial_state *s = opaque;
  183. uint32_t ret = ~0;
  184. #if 0
  185. switch(offs) {
  186. case 0x00:
  187. ret = s->smr;
  188. break;
  189. case 0x04:
  190. ret = s->brr;
  191. break;
  192. case 0x08:
  193. ret = s->scr;
  194. break;
  195. case 0x14:
  196. ret = 0;
  197. break;
  198. }
  199. #endif
  200. if (s->feat & SH_SERIAL_FEAT_SCIF) {
  201. switch(offs) {
  202. case 0x00: /* SMR */
  203. ret = s->smr;
  204. break;
  205. case 0x08: /* SCR */
  206. ret = s->scr;
  207. break;
  208. case 0x10: /* FSR */
  209. ret = 0;
  210. if (s->flags & SH_SERIAL_FLAG_TEND)
  211. ret |= (1 << 6);
  212. if (s->flags & SH_SERIAL_FLAG_TDE)
  213. ret |= (1 << 5);
  214. if (s->flags & SH_SERIAL_FLAG_BRK)
  215. ret |= (1 << 4);
  216. if (s->flags & SH_SERIAL_FLAG_RDF)
  217. ret |= (1 << 1);
  218. if (s->flags & SH_SERIAL_FLAG_DR)
  219. ret |= (1 << 0);
  220. if (s->scr & (1 << 5))
  221. s->flags |= SH_SERIAL_FLAG_TDE | SH_SERIAL_FLAG_TEND;
  222. break;
  223. case 0x14:
  224. if (s->rx_cnt > 0) {
  225. ret = s->rx_fifo[s->rx_tail++];
  226. s->rx_cnt--;
  227. if (s->rx_tail == SH_RX_FIFO_LENGTH)
  228. s->rx_tail = 0;
  229. if (s->rx_cnt < s->rtrg)
  230. s->flags &= ~SH_SERIAL_FLAG_RDF;
  231. }
  232. break;
  233. #if 0
  234. case 0x18:
  235. ret = s->fcr;
  236. break;
  237. #endif
  238. case 0x1c:
  239. ret = s->rx_cnt;
  240. break;
  241. case 0x20:
  242. ret = s->sptr;
  243. break;
  244. case 0x24:
  245. ret = 0;
  246. break;
  247. }
  248. }
  249. else {
  250. switch(offs) {
  251. #if 0
  252. case 0x0c:
  253. ret = s->dr;
  254. break;
  255. case 0x10:
  256. ret = 0;
  257. break;
  258. case 0x14:
  259. ret = s->rx_fifo[0];
  260. break;
  261. #endif
  262. case 0x1c:
  263. ret = s->sptr;
  264. break;
  265. }
  266. }
  267. #ifdef DEBUG_SERIAL
  268. printf("sh_serial: read offs=0x%02x val=0x%x\n",
  269. offs, ret);
  270. #endif
  271. if (ret & ~((1 << 16) - 1)) {
  272. fprintf(stderr, "sh_serial: unsupported read from 0x%02"
  273. HWADDR_PRIx "\n", offs);
  274. abort();
  275. }
  276. return ret;
  277. }
  278. static int sh_serial_can_receive(sh_serial_state *s)
  279. {
  280. return s->scr & (1 << 4);
  281. }
  282. static void sh_serial_receive_break(sh_serial_state *s)
  283. {
  284. if (s->feat & SH_SERIAL_FEAT_SCIF)
  285. s->sr |= (1 << 4);
  286. }
  287. static int sh_serial_can_receive1(void *opaque)
  288. {
  289. sh_serial_state *s = opaque;
  290. return sh_serial_can_receive(s);
  291. }
  292. static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size)
  293. {
  294. sh_serial_state *s = opaque;
  295. if (s->feat & SH_SERIAL_FEAT_SCIF) {
  296. int i;
  297. for (i = 0; i < size; i++) {
  298. if (s->rx_cnt < SH_RX_FIFO_LENGTH) {
  299. s->rx_fifo[s->rx_head++] = buf[i];
  300. if (s->rx_head == SH_RX_FIFO_LENGTH) {
  301. s->rx_head = 0;
  302. }
  303. s->rx_cnt++;
  304. if (s->rx_cnt >= s->rtrg) {
  305. s->flags |= SH_SERIAL_FLAG_RDF;
  306. if (s->scr & (1 << 6) && s->rxi) {
  307. qemu_set_irq(s->rxi, 1);
  308. }
  309. }
  310. }
  311. }
  312. } else {
  313. s->rx_fifo[0] = buf[0];
  314. }
  315. }
  316. static void sh_serial_event(void *opaque, int event)
  317. {
  318. sh_serial_state *s = opaque;
  319. if (event == CHR_EVENT_BREAK)
  320. sh_serial_receive_break(s);
  321. }
  322. static const MemoryRegionOps sh_serial_ops = {
  323. .read = sh_serial_read,
  324. .write = sh_serial_write,
  325. .endianness = DEVICE_NATIVE_ENDIAN,
  326. };
  327. void sh_serial_init(MemoryRegion *sysmem,
  328. hwaddr base, int feat,
  329. uint32_t freq, CharDriverState *chr,
  330. qemu_irq eri_source,
  331. qemu_irq rxi_source,
  332. qemu_irq txi_source,
  333. qemu_irq tei_source,
  334. qemu_irq bri_source)
  335. {
  336. sh_serial_state *s;
  337. s = g_malloc0(sizeof(sh_serial_state));
  338. s->feat = feat;
  339. s->flags = SH_SERIAL_FLAG_TEND | SH_SERIAL_FLAG_TDE;
  340. s->rtrg = 1;
  341. s->smr = 0;
  342. s->brr = 0xff;
  343. s->scr = 1 << 5; /* pretend that TX is enabled so early printk works */
  344. s->sptr = 0;
  345. if (feat & SH_SERIAL_FEAT_SCIF) {
  346. s->fcr = 0;
  347. }
  348. else {
  349. s->dr = 0xff;
  350. }
  351. sh_serial_clear_fifo(s);
  352. memory_region_init_io(&s->iomem, &sh_serial_ops, s,
  353. "serial", 0x100000000ULL);
  354. memory_region_init_alias(&s->iomem_p4, "serial-p4", &s->iomem,
  355. 0, 0x28);
  356. memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4);
  357. memory_region_init_alias(&s->iomem_a7, "serial-a7", &s->iomem,
  358. 0, 0x28);
  359. memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
  360. s->chr = chr;
  361. if (chr)
  362. qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
  363. sh_serial_event, s);
  364. s->eri = eri_source;
  365. s->rxi = rxi_source;
  366. s->txi = txi_source;
  367. s->tei = tei_source;
  368. s->bri = bri_source;
  369. }