exynos4210_uart.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. /*
  2. * Exynos4210 UART Emulation
  3. *
  4. * Copyright (C) 2011 Samsung Electronics Co Ltd.
  5. * Maksim Kozlov, <m.kozlov@samsung.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by the
  9. * Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful, but WITHOUT
  13. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  15. * for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program; if not, see <http://www.gnu.org/licenses/>.
  19. *
  20. */
  21. #include "qemu/osdep.h"
  22. #include "hw/sysbus.h"
  23. #include "migration/vmstate.h"
  24. #include "qapi/error.h"
  25. #include "qemu/error-report.h"
  26. #include "qemu/module.h"
  27. #include "qemu/timer.h"
  28. #include "chardev/char-fe.h"
  29. #include "chardev/char-serial.h"
  30. #include "hw/arm/exynos4210.h"
  31. #include "hw/irq.h"
  32. #include "hw/qdev-properties.h"
  33. #include "hw/qdev-properties-system.h"
  34. #include "trace.h"
  35. #include "qom/object.h"
  36. /*
  37. * Offsets for UART registers relative to SFR base address
  38. * for UARTn
  39. *
  40. */
  41. #define ULCON 0x0000 /* Line Control */
  42. #define UCON 0x0004 /* Control */
  43. #define UFCON 0x0008 /* FIFO Control */
  44. #define UMCON 0x000C /* Modem Control */
  45. #define UTRSTAT 0x0010 /* Tx/Rx Status */
  46. #define UERSTAT 0x0014 /* UART Error Status */
  47. #define UFSTAT 0x0018 /* FIFO Status */
  48. #define UMSTAT 0x001C /* Modem Status */
  49. #define UTXH 0x0020 /* Transmit Buffer */
  50. #define URXH 0x0024 /* Receive Buffer */
  51. #define UBRDIV 0x0028 /* Baud Rate Divisor */
  52. #define UFRACVAL 0x002C /* Divisor Fractional Value */
  53. #define UINTP 0x0030 /* Interrupt Pending */
  54. #define UINTSP 0x0034 /* Interrupt Source Pending */
  55. #define UINTM 0x0038 /* Interrupt Mask */
  56. /*
  57. * for indexing register in the uint32_t array
  58. *
  59. * 'reg' - register offset (see offsets definitions above)
  60. *
  61. */
  62. #define I_(reg) (reg / sizeof(uint32_t))
  63. typedef struct Exynos4210UartReg {
  64. const char *name; /* the only reason is the debug output */
  65. hwaddr offset;
  66. uint32_t reset_value;
  67. } Exynos4210UartReg;
  68. static const Exynos4210UartReg exynos4210_uart_regs[] = {
  69. {"ULCON", ULCON, 0x00000000},
  70. {"UCON", UCON, 0x00003000},
  71. {"UFCON", UFCON, 0x00000000},
  72. {"UMCON", UMCON, 0x00000000},
  73. {"UTRSTAT", UTRSTAT, 0x00000006}, /* RO */
  74. {"UERSTAT", UERSTAT, 0x00000000}, /* RO */
  75. {"UFSTAT", UFSTAT, 0x00000000}, /* RO */
  76. {"UMSTAT", UMSTAT, 0x00000000}, /* RO */
  77. {"UTXH", UTXH, 0x5c5c5c5c}, /* WO, undefined reset value*/
  78. {"URXH", URXH, 0x00000000}, /* RO */
  79. {"UBRDIV", UBRDIV, 0x00000000},
  80. {"UFRACVAL", UFRACVAL, 0x00000000},
  81. {"UINTP", UINTP, 0x00000000},
  82. {"UINTSP", UINTSP, 0x00000000},
  83. {"UINTM", UINTM, 0x00000000},
  84. };
  85. #define EXYNOS4210_UART_REGS_MEM_SIZE 0x3C
  86. /* UART FIFO Control */
  87. #define UFCON_FIFO_ENABLE 0x1
  88. #define UFCON_Rx_FIFO_RESET 0x2
  89. #define UFCON_Tx_FIFO_RESET 0x4
  90. #define UFCON_Tx_FIFO_TRIGGER_LEVEL_SHIFT 8
  91. #define UFCON_Tx_FIFO_TRIGGER_LEVEL (7 << UFCON_Tx_FIFO_TRIGGER_LEVEL_SHIFT)
  92. #define UFCON_Rx_FIFO_TRIGGER_LEVEL_SHIFT 4
  93. #define UFCON_Rx_FIFO_TRIGGER_LEVEL (7 << UFCON_Rx_FIFO_TRIGGER_LEVEL_SHIFT)
  94. /* Uart FIFO Status */
  95. #define UFSTAT_Rx_FIFO_COUNT 0xff
  96. #define UFSTAT_Rx_FIFO_FULL 0x100
  97. #define UFSTAT_Rx_FIFO_ERROR 0x200
  98. #define UFSTAT_Tx_FIFO_COUNT_SHIFT 16
  99. #define UFSTAT_Tx_FIFO_COUNT (0xff << UFSTAT_Tx_FIFO_COUNT_SHIFT)
  100. #define UFSTAT_Tx_FIFO_FULL_SHIFT 24
  101. #define UFSTAT_Tx_FIFO_FULL (1 << UFSTAT_Tx_FIFO_FULL_SHIFT)
  102. /* UART Interrupt Source Pending */
  103. #define UINTSP_RXD 0x1 /* Receive interrupt */
  104. #define UINTSP_ERROR 0x2 /* Error interrupt */
  105. #define UINTSP_TXD 0x4 /* Transmit interrupt */
  106. #define UINTSP_MODEM 0x8 /* Modem interrupt */
  107. /* UART Line Control */
  108. #define ULCON_IR_MODE_SHIFT 6
  109. #define ULCON_PARITY_SHIFT 3
  110. #define ULCON_STOP_BIT_SHIFT 1
  111. /* UART Tx/Rx Status */
  112. #define UTRSTAT_Rx_TIMEOUT 0x8
  113. #define UTRSTAT_TRANSMITTER_EMPTY 0x4
  114. #define UTRSTAT_Tx_BUFFER_EMPTY 0x2
  115. #define UTRSTAT_Rx_BUFFER_DATA_READY 0x1
  116. /* UART Error Status */
  117. #define UERSTAT_OVERRUN 0x1
  118. #define UERSTAT_PARITY 0x2
  119. #define UERSTAT_FRAME 0x4
  120. #define UERSTAT_BREAK 0x8
  121. typedef struct {
  122. uint8_t *data;
  123. uint32_t sp, rp; /* store and retrieve pointers */
  124. uint32_t size;
  125. } Exynos4210UartFIFO;
  126. #define TYPE_EXYNOS4210_UART "exynos4210.uart"
  127. OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210UartState, EXYNOS4210_UART)
  128. struct Exynos4210UartState {
  129. SysBusDevice parent_obj;
  130. MemoryRegion iomem;
  131. uint32_t reg[EXYNOS4210_UART_REGS_MEM_SIZE / sizeof(uint32_t)];
  132. Exynos4210UartFIFO rx;
  133. Exynos4210UartFIFO tx;
  134. QEMUTimer *fifo_timeout_timer;
  135. uint64_t wordtime; /* word time in ns */
  136. CharBackend chr;
  137. qemu_irq irq;
  138. qemu_irq dmairq;
  139. uint32_t channel;
  140. };
  141. /* Used only for tracing */
  142. static const char *exynos4210_uart_regname(hwaddr offset)
  143. {
  144. int i;
  145. for (i = 0; i < ARRAY_SIZE(exynos4210_uart_regs); i++) {
  146. if (offset == exynos4210_uart_regs[i].offset) {
  147. return exynos4210_uart_regs[i].name;
  148. }
  149. }
  150. return NULL;
  151. }
  152. static void fifo_store(Exynos4210UartFIFO *q, uint8_t ch)
  153. {
  154. q->data[q->sp] = ch;
  155. q->sp = (q->sp + 1) % q->size;
  156. }
  157. static uint8_t fifo_retrieve(Exynos4210UartFIFO *q)
  158. {
  159. uint8_t ret = q->data[q->rp];
  160. q->rp = (q->rp + 1) % q->size;
  161. return ret;
  162. }
  163. static int fifo_elements_number(const Exynos4210UartFIFO *q)
  164. {
  165. if (q->sp < q->rp) {
  166. return q->size - q->rp + q->sp;
  167. }
  168. return q->sp - q->rp;
  169. }
  170. static int fifo_empty_elements_number(const Exynos4210UartFIFO *q)
  171. {
  172. return q->size - fifo_elements_number(q);
  173. }
  174. static void fifo_reset(Exynos4210UartFIFO *q)
  175. {
  176. g_free(q->data);
  177. q->data = NULL;
  178. q->data = g_malloc0(q->size);
  179. q->sp = 0;
  180. q->rp = 0;
  181. }
  182. static uint32_t exynos4210_uart_FIFO_trigger_level(uint32_t channel,
  183. uint32_t reg)
  184. {
  185. uint32_t level;
  186. switch (channel) {
  187. case 0:
  188. level = reg * 32;
  189. break;
  190. case 1:
  191. case 4:
  192. level = reg * 8;
  193. break;
  194. case 2:
  195. case 3:
  196. level = reg * 2;
  197. break;
  198. default:
  199. level = 0;
  200. trace_exynos_uart_channel_error(channel);
  201. break;
  202. }
  203. return level;
  204. }
  205. static uint32_t
  206. exynos4210_uart_Tx_FIFO_trigger_level(const Exynos4210UartState *s)
  207. {
  208. uint32_t reg;
  209. reg = (s->reg[I_(UFCON)] & UFCON_Tx_FIFO_TRIGGER_LEVEL) >>
  210. UFCON_Tx_FIFO_TRIGGER_LEVEL_SHIFT;
  211. return exynos4210_uart_FIFO_trigger_level(s->channel, reg);
  212. }
  213. static uint32_t
  214. exynos4210_uart_Rx_FIFO_trigger_level(const Exynos4210UartState *s)
  215. {
  216. uint32_t reg;
  217. reg = ((s->reg[I_(UFCON)] & UFCON_Rx_FIFO_TRIGGER_LEVEL) >>
  218. UFCON_Rx_FIFO_TRIGGER_LEVEL_SHIFT) + 1;
  219. return exynos4210_uart_FIFO_trigger_level(s->channel, reg);
  220. }
  221. /*
  222. * Update Rx DMA busy signal if Rx DMA is enabled. For simplicity,
  223. * mark DMA as busy if DMA is enabled and the receive buffer is empty.
  224. */
  225. static void exynos4210_uart_update_dmabusy(Exynos4210UartState *s)
  226. {
  227. bool rx_dma_enabled = (s->reg[I_(UCON)] & 0x03) == 0x02;
  228. uint32_t count = fifo_elements_number(&s->rx);
  229. if (rx_dma_enabled && !count) {
  230. qemu_irq_raise(s->dmairq);
  231. trace_exynos_uart_dmabusy(s->channel);
  232. } else {
  233. qemu_irq_lower(s->dmairq);
  234. trace_exynos_uart_dmaready(s->channel);
  235. }
  236. }
  237. static void exynos4210_uart_update_irq(Exynos4210UartState *s)
  238. {
  239. /*
  240. * The Tx interrupt is always requested if the number of data in the
  241. * transmit FIFO is smaller than the trigger level.
  242. */
  243. if (s->reg[I_(UFCON)] & UFCON_FIFO_ENABLE) {
  244. uint32_t count = (s->reg[I_(UFSTAT)] & UFSTAT_Tx_FIFO_COUNT) >>
  245. UFSTAT_Tx_FIFO_COUNT_SHIFT;
  246. if (count <= exynos4210_uart_Tx_FIFO_trigger_level(s)) {
  247. s->reg[I_(UINTSP)] |= UINTSP_TXD;
  248. }
  249. /*
  250. * Rx interrupt if trigger level is reached or if rx timeout
  251. * interrupt is disabled and there is data in the receive buffer
  252. */
  253. count = fifo_elements_number(&s->rx);
  254. if ((count && !(s->reg[I_(UCON)] & 0x80)) ||
  255. count >= exynos4210_uart_Rx_FIFO_trigger_level(s)) {
  256. exynos4210_uart_update_dmabusy(s);
  257. s->reg[I_(UINTSP)] |= UINTSP_RXD;
  258. timer_del(s->fifo_timeout_timer);
  259. }
  260. } else if (s->reg[I_(UTRSTAT)] & UTRSTAT_Rx_BUFFER_DATA_READY) {
  261. exynos4210_uart_update_dmabusy(s);
  262. s->reg[I_(UINTSP)] |= UINTSP_RXD;
  263. }
  264. s->reg[I_(UINTP)] = s->reg[I_(UINTSP)] & ~s->reg[I_(UINTM)];
  265. if (s->reg[I_(UINTP)]) {
  266. qemu_irq_raise(s->irq);
  267. trace_exynos_uart_irq_raised(s->channel, s->reg[I_(UINTP)]);
  268. } else {
  269. qemu_irq_lower(s->irq);
  270. trace_exynos_uart_irq_lowered(s->channel);
  271. }
  272. }
  273. static void exynos4210_uart_timeout_int(void *opaque)
  274. {
  275. Exynos4210UartState *s = opaque;
  276. trace_exynos_uart_rx_timeout(s->channel, s->reg[I_(UTRSTAT)],
  277. s->reg[I_(UINTSP)]);
  278. if ((s->reg[I_(UTRSTAT)] & UTRSTAT_Rx_BUFFER_DATA_READY) ||
  279. (s->reg[I_(UCON)] & (1 << 11))) {
  280. s->reg[I_(UINTSP)] |= UINTSP_RXD;
  281. s->reg[I_(UTRSTAT)] |= UTRSTAT_Rx_TIMEOUT;
  282. exynos4210_uart_update_dmabusy(s);
  283. exynos4210_uart_update_irq(s);
  284. }
  285. }
  286. static void exynos4210_uart_update_parameters(Exynos4210UartState *s)
  287. {
  288. int speed, parity, data_bits, stop_bits;
  289. QEMUSerialSetParams ssp;
  290. uint64_t uclk_rate;
  291. if (s->reg[I_(UBRDIV)] == 0) {
  292. return;
  293. }
  294. if (s->reg[I_(ULCON)] & 0x20) {
  295. if (s->reg[I_(ULCON)] & 0x28) {
  296. parity = 'E';
  297. } else {
  298. parity = 'O';
  299. }
  300. } else {
  301. parity = 'N';
  302. }
  303. if (s->reg[I_(ULCON)] & 0x4) {
  304. stop_bits = 2;
  305. } else {
  306. stop_bits = 1;
  307. }
  308. data_bits = (s->reg[I_(ULCON)] & 0x3) + 5;
  309. uclk_rate = 24000000;
  310. speed = uclk_rate / ((16 * (s->reg[I_(UBRDIV)]) & 0xffff) +
  311. (s->reg[I_(UFRACVAL)] & 0x7) + 16);
  312. ssp.speed = speed;
  313. ssp.parity = parity;
  314. ssp.data_bits = data_bits;
  315. ssp.stop_bits = stop_bits;
  316. s->wordtime = NANOSECONDS_PER_SECOND * (data_bits + stop_bits + 1) / speed;
  317. qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
  318. trace_exynos_uart_update_params(
  319. s->channel, speed, parity, data_bits, stop_bits, s->wordtime);
  320. }
  321. static void exynos4210_uart_rx_timeout_set(Exynos4210UartState *s)
  322. {
  323. if (s->reg[I_(UCON)] & 0x80) {
  324. uint32_t timeout = ((s->reg[I_(UCON)] >> 12) & 0x0f) * s->wordtime;
  325. timer_mod(s->fifo_timeout_timer,
  326. qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + timeout);
  327. } else {
  328. timer_del(s->fifo_timeout_timer);
  329. }
  330. }
  331. static void exynos4210_uart_write(void *opaque, hwaddr offset,
  332. uint64_t val, unsigned size)
  333. {
  334. Exynos4210UartState *s = (Exynos4210UartState *)opaque;
  335. uint8_t ch;
  336. trace_exynos_uart_write(s->channel, offset,
  337. exynos4210_uart_regname(offset), val);
  338. switch (offset) {
  339. case ULCON:
  340. case UBRDIV:
  341. case UFRACVAL:
  342. s->reg[I_(offset)] = val;
  343. exynos4210_uart_update_parameters(s);
  344. break;
  345. case UFCON:
  346. s->reg[I_(UFCON)] = val;
  347. if (val & UFCON_Rx_FIFO_RESET) {
  348. fifo_reset(&s->rx);
  349. s->reg[I_(UFCON)] &= ~UFCON_Rx_FIFO_RESET;
  350. trace_exynos_uart_rx_fifo_reset(s->channel);
  351. }
  352. if (val & UFCON_Tx_FIFO_RESET) {
  353. fifo_reset(&s->tx);
  354. s->reg[I_(UFCON)] &= ~UFCON_Tx_FIFO_RESET;
  355. trace_exynos_uart_tx_fifo_reset(s->channel);
  356. }
  357. break;
  358. case UTXH:
  359. if (qemu_chr_fe_backend_connected(&s->chr)) {
  360. s->reg[I_(UTRSTAT)] &= ~(UTRSTAT_TRANSMITTER_EMPTY |
  361. UTRSTAT_Tx_BUFFER_EMPTY);
  362. ch = (uint8_t)val;
  363. /* XXX this blocks entire thread. Rewrite to use
  364. * qemu_chr_fe_write and background I/O callbacks */
  365. qemu_chr_fe_write_all(&s->chr, &ch, 1);
  366. trace_exynos_uart_tx(s->channel, ch);
  367. s->reg[I_(UTRSTAT)] |= UTRSTAT_TRANSMITTER_EMPTY |
  368. UTRSTAT_Tx_BUFFER_EMPTY;
  369. s->reg[I_(UINTSP)] |= UINTSP_TXD;
  370. exynos4210_uart_update_irq(s);
  371. }
  372. break;
  373. case UINTP:
  374. s->reg[I_(UINTP)] &= ~val;
  375. s->reg[I_(UINTSP)] &= ~val;
  376. trace_exynos_uart_intclr(s->channel, s->reg[I_(UINTP)]);
  377. exynos4210_uart_update_irq(s);
  378. break;
  379. case UTRSTAT:
  380. if (val & UTRSTAT_Rx_TIMEOUT) {
  381. s->reg[I_(UTRSTAT)] &= ~UTRSTAT_Rx_TIMEOUT;
  382. }
  383. break;
  384. case UERSTAT:
  385. case UFSTAT:
  386. case UMSTAT:
  387. case URXH:
  388. trace_exynos_uart_ro_write(
  389. s->channel, exynos4210_uart_regname(offset), offset);
  390. break;
  391. case UINTSP:
  392. s->reg[I_(UINTSP)] &= ~val;
  393. break;
  394. case UINTM:
  395. s->reg[I_(UINTM)] = val;
  396. exynos4210_uart_update_irq(s);
  397. break;
  398. case UCON:
  399. case UMCON:
  400. default:
  401. s->reg[I_(offset)] = val;
  402. break;
  403. }
  404. }
  405. static uint64_t exynos4210_uart_read(void *opaque, hwaddr offset,
  406. unsigned size)
  407. {
  408. Exynos4210UartState *s = (Exynos4210UartState *)opaque;
  409. uint32_t res;
  410. switch (offset) {
  411. case UERSTAT: /* Read Only */
  412. res = s->reg[I_(UERSTAT)];
  413. s->reg[I_(UERSTAT)] = 0;
  414. trace_exynos_uart_read(s->channel, offset,
  415. exynos4210_uart_regname(offset), res);
  416. return res;
  417. case UFSTAT: /* Read Only */
  418. s->reg[I_(UFSTAT)] = fifo_elements_number(&s->rx) & 0xff;
  419. if (fifo_empty_elements_number(&s->rx) == 0) {
  420. s->reg[I_(UFSTAT)] |= UFSTAT_Rx_FIFO_FULL;
  421. s->reg[I_(UFSTAT)] &= ~0xff;
  422. }
  423. trace_exynos_uart_read(s->channel, offset,
  424. exynos4210_uart_regname(offset),
  425. s->reg[I_(UFSTAT)]);
  426. return s->reg[I_(UFSTAT)];
  427. case URXH:
  428. if (s->reg[I_(UFCON)] & UFCON_FIFO_ENABLE) {
  429. if (fifo_elements_number(&s->rx)) {
  430. res = fifo_retrieve(&s->rx);
  431. trace_exynos_uart_rx(s->channel, res);
  432. if (!fifo_elements_number(&s->rx)) {
  433. s->reg[I_(UTRSTAT)] &= ~UTRSTAT_Rx_BUFFER_DATA_READY;
  434. } else {
  435. s->reg[I_(UTRSTAT)] |= UTRSTAT_Rx_BUFFER_DATA_READY;
  436. }
  437. } else {
  438. trace_exynos_uart_rx_error(s->channel);
  439. s->reg[I_(UINTSP)] |= UINTSP_ERROR;
  440. exynos4210_uart_update_irq(s);
  441. res = 0;
  442. }
  443. } else {
  444. s->reg[I_(UTRSTAT)] &= ~UTRSTAT_Rx_BUFFER_DATA_READY;
  445. res = s->reg[I_(URXH)];
  446. }
  447. qemu_chr_fe_accept_input(&s->chr);
  448. exynos4210_uart_update_dmabusy(s);
  449. trace_exynos_uart_read(s->channel, offset,
  450. exynos4210_uart_regname(offset), res);
  451. return res;
  452. case UTXH:
  453. trace_exynos_uart_wo_read(s->channel, exynos4210_uart_regname(offset),
  454. offset);
  455. break;
  456. default:
  457. trace_exynos_uart_read(s->channel, offset,
  458. exynos4210_uart_regname(offset),
  459. s->reg[I_(offset)]);
  460. return s->reg[I_(offset)];
  461. }
  462. trace_exynos_uart_read(s->channel, offset, exynos4210_uart_regname(offset),
  463. 0);
  464. return 0;
  465. }
  466. static const MemoryRegionOps exynos4210_uart_ops = {
  467. .read = exynos4210_uart_read,
  468. .write = exynos4210_uart_write,
  469. .endianness = DEVICE_NATIVE_ENDIAN,
  470. .valid = {
  471. .max_access_size = 4,
  472. .unaligned = false
  473. },
  474. };
  475. static int exynos4210_uart_can_receive(void *opaque)
  476. {
  477. Exynos4210UartState *s = (Exynos4210UartState *)opaque;
  478. if (s->reg[I_(UFCON)] & UFCON_FIFO_ENABLE) {
  479. return fifo_empty_elements_number(&s->rx);
  480. } else {
  481. return !(s->reg[I_(UTRSTAT)] & UTRSTAT_Rx_BUFFER_DATA_READY);
  482. }
  483. }
  484. static void exynos4210_uart_receive(void *opaque, const uint8_t *buf, int size)
  485. {
  486. Exynos4210UartState *s = (Exynos4210UartState *)opaque;
  487. int i;
  488. if (s->reg[I_(UFCON)] & UFCON_FIFO_ENABLE) {
  489. if (fifo_empty_elements_number(&s->rx) < size) {
  490. size = fifo_empty_elements_number(&s->rx);
  491. s->reg[I_(UINTSP)] |= UINTSP_ERROR;
  492. }
  493. for (i = 0; i < size; i++) {
  494. fifo_store(&s->rx, buf[i]);
  495. }
  496. exynos4210_uart_rx_timeout_set(s);
  497. } else {
  498. s->reg[I_(URXH)] = buf[0];
  499. }
  500. s->reg[I_(UTRSTAT)] |= UTRSTAT_Rx_BUFFER_DATA_READY;
  501. exynos4210_uart_update_irq(s);
  502. }
  503. static void exynos4210_uart_event(void *opaque, QEMUChrEvent event)
  504. {
  505. Exynos4210UartState *s = (Exynos4210UartState *)opaque;
  506. if (event == CHR_EVENT_BREAK) {
  507. /* When the RxDn is held in logic 0, then a null byte is pushed into the
  508. * fifo */
  509. fifo_store(&s->rx, '\0');
  510. s->reg[I_(UERSTAT)] |= UERSTAT_BREAK;
  511. exynos4210_uart_update_irq(s);
  512. }
  513. }
  514. static void exynos4210_uart_reset(DeviceState *dev)
  515. {
  516. Exynos4210UartState *s = EXYNOS4210_UART(dev);
  517. int i;
  518. for (i = 0; i < ARRAY_SIZE(exynos4210_uart_regs); i++) {
  519. s->reg[I_(exynos4210_uart_regs[i].offset)] =
  520. exynos4210_uart_regs[i].reset_value;
  521. }
  522. fifo_reset(&s->rx);
  523. fifo_reset(&s->tx);
  524. trace_exynos_uart_rxsize(s->channel, s->rx.size);
  525. }
  526. static int exynos4210_uart_post_load(void *opaque, int version_id)
  527. {
  528. Exynos4210UartState *s = (Exynos4210UartState *)opaque;
  529. exynos4210_uart_update_parameters(s);
  530. exynos4210_uart_rx_timeout_set(s);
  531. return 0;
  532. }
  533. static const VMStateDescription vmstate_exynos4210_uart_fifo = {
  534. .name = "exynos4210.uart.fifo",
  535. .version_id = 1,
  536. .minimum_version_id = 1,
  537. .fields = (const VMStateField[]) {
  538. VMSTATE_UINT32(sp, Exynos4210UartFIFO),
  539. VMSTATE_UINT32(rp, Exynos4210UartFIFO),
  540. VMSTATE_VBUFFER_UINT32(data, Exynos4210UartFIFO, 1, NULL, size),
  541. VMSTATE_END_OF_LIST()
  542. }
  543. };
  544. static const VMStateDescription vmstate_exynos4210_uart = {
  545. .name = "exynos4210.uart",
  546. .version_id = 1,
  547. .minimum_version_id = 1,
  548. .post_load = exynos4210_uart_post_load,
  549. .fields = (const VMStateField[]) {
  550. VMSTATE_STRUCT(rx, Exynos4210UartState, 1,
  551. vmstate_exynos4210_uart_fifo, Exynos4210UartFIFO),
  552. VMSTATE_UINT32_ARRAY(reg, Exynos4210UartState,
  553. EXYNOS4210_UART_REGS_MEM_SIZE / sizeof(uint32_t)),
  554. VMSTATE_END_OF_LIST()
  555. }
  556. };
  557. DeviceState *exynos4210_uart_create(hwaddr addr,
  558. int fifo_size,
  559. int channel,
  560. Chardev *chr,
  561. qemu_irq irq)
  562. {
  563. DeviceState *dev;
  564. SysBusDevice *bus;
  565. dev = qdev_new(TYPE_EXYNOS4210_UART);
  566. qdev_prop_set_chr(dev, "chardev", chr);
  567. qdev_prop_set_uint32(dev, "channel", channel);
  568. qdev_prop_set_uint32(dev, "rx-size", fifo_size);
  569. qdev_prop_set_uint32(dev, "tx-size", fifo_size);
  570. bus = SYS_BUS_DEVICE(dev);
  571. sysbus_realize_and_unref(bus, &error_fatal);
  572. if (addr != (hwaddr)-1) {
  573. sysbus_mmio_map(bus, 0, addr);
  574. }
  575. sysbus_connect_irq(bus, 0, irq);
  576. return dev;
  577. }
  578. static void exynos4210_uart_init(Object *obj)
  579. {
  580. SysBusDevice *dev = SYS_BUS_DEVICE(obj);
  581. Exynos4210UartState *s = EXYNOS4210_UART(dev);
  582. s->wordtime = NANOSECONDS_PER_SECOND * 10 / 9600;
  583. /* memory mapping */
  584. memory_region_init_io(&s->iomem, obj, &exynos4210_uart_ops, s,
  585. "exynos4210.uart", EXYNOS4210_UART_REGS_MEM_SIZE);
  586. sysbus_init_mmio(dev, &s->iomem);
  587. sysbus_init_irq(dev, &s->irq);
  588. sysbus_init_irq(dev, &s->dmairq);
  589. }
  590. static void exynos4210_uart_realize(DeviceState *dev, Error **errp)
  591. {
  592. Exynos4210UartState *s = EXYNOS4210_UART(dev);
  593. s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
  594. exynos4210_uart_timeout_int, s);
  595. qemu_chr_fe_set_handlers(&s->chr, exynos4210_uart_can_receive,
  596. exynos4210_uart_receive, exynos4210_uart_event,
  597. NULL, s, NULL, true);
  598. }
  599. static const Property exynos4210_uart_properties[] = {
  600. DEFINE_PROP_CHR("chardev", Exynos4210UartState, chr),
  601. DEFINE_PROP_UINT32("channel", Exynos4210UartState, channel, 0),
  602. DEFINE_PROP_UINT32("rx-size", Exynos4210UartState, rx.size, 16),
  603. DEFINE_PROP_UINT32("tx-size", Exynos4210UartState, tx.size, 16),
  604. };
  605. static void exynos4210_uart_class_init(ObjectClass *klass, void *data)
  606. {
  607. DeviceClass *dc = DEVICE_CLASS(klass);
  608. dc->realize = exynos4210_uart_realize;
  609. device_class_set_legacy_reset(dc, exynos4210_uart_reset);
  610. device_class_set_props(dc, exynos4210_uart_properties);
  611. dc->vmsd = &vmstate_exynos4210_uart;
  612. }
  613. static const TypeInfo exynos4210_uart_info = {
  614. .name = TYPE_EXYNOS4210_UART,
  615. .parent = TYPE_SYS_BUS_DEVICE,
  616. .instance_size = sizeof(Exynos4210UartState),
  617. .instance_init = exynos4210_uart_init,
  618. .class_init = exynos4210_uart_class_init,
  619. };
  620. static void exynos4210_uart_register(void)
  621. {
  622. type_register_static(&exynos4210_uart_info);
  623. }
  624. type_init(exynos4210_uart_register)