sync with tizen_2.2
[sdk/emulator/qemu.git] / hw / exynos4210_i2s.c
1 /*
2  * Samsung exynos4210 I2S driver
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5  *  Vorobiov Stanislav <s.vorobiov@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
22 #include "exynos4210_i2s.h"
23 #include "exec-memory.h"
24
25 /* #define DEBUG_I2S */
26
27 #ifdef DEBUG_I2S
28 #define DPRINTF(fmt, ...) \
29     do { \
30         fprintf(stdout, "I2S: [%s:%d] " fmt, __func__, __LINE__, \
31             ## __VA_ARGS__); \
32     } while (0)
33 #else
34 #define DPRINTF(fmt, ...) do {} while (0)
35 #endif
36
37 /* Registers */
38 #define IISCON       0x00
39 #define IISMOD       0x04
40 #define IISFIC       0x08
41 #define IISPSR       0x0C
42 #define IISTXD       0x10
43 #define IISRXD       0x14
44 #define IISFICS      0x18
45 #define IISTXDS      0x1C
46 #define IISAHB       0x20
47 #define IISSTR0      0x24
48 #define IISSIZE      0x28
49 #define IISTRNCNT    0x2C
50 #define IISLVL0ADDR  0x30
51 #define IISLVL1ADDR  0x34
52 #define IISLVL2ADDR  0x38
53 #define IISLVL3ADDR  0x3C
54 #define IISSTR1      0x40
55
56 #define I2S_REGS_MEM_SIZE 0x44
57 #define I2S_REGS_NUM (I2S_REGS_MEM_SIZE >> 2)
58
59 #define I_(reg) (reg / sizeof(uint32_t))
60
61 /* Interface Control Register */
62 #define IISCON_I2SACTIVE    (1 << 0)
63 #define IISCON_RXDMACTIVE   (1 << 1)
64 #define IISCON_TXDMACTIVE   (1 << 2)
65 #define IISCON_RXCHPAUSE    (1 << 3)
66 #define IISCON_TXCHPAUSE    (1 << 4)
67 #define IISCON_RXDMAPAUSE   (1 << 5)
68 #define IISCON_TXDMAPAUSE   (1 << 6)
69 #define IISCON_FRXFULL      (1 << 7)
70 #define IISCON_FTX0FULL     (1 << 8)
71 #define IISCON_FRXEMPT      (1 << 9)
72 #define IISCON_FTX0EMPT     (1 << 10)
73 #define IISCON_LRI          (1 << 11)
74 #define IISCON_FTX1FULL     (1 << 12)
75 #define IISCON_FTX2FULL     (1 << 13)
76 #define IISCON_FTX1EMPT     (1 << 14)
77 #define IISCON_FTX2EMPT     (1 << 15)
78 #define IISCON_FTXURINTEN   (1 << 16)
79 #define IISCON_FTXURSTATUS  (1 << 17)
80 #define IISCON_TXSDMACTIVE  (1 << 18)
81 #define IISCON_TXSDMAPAUSE  (1 << 20)
82 #define IISCON_FTXSFULL     (1 << 21)
83 #define IISCON_FTXSEMPT     (1 << 22)
84 #define IISCON_FTXSURINTEN  (1 << 23)
85 #define IISCON_FTXSURSTATUS (1 << 24)
86 #define IISCON_FRXOFINTEN   (1 << 25)
87 #define IISCON_FRXOFSTATUS  (1 << 26)
88 #define IISCON_SW_RST       (1 << 31)
89
90 #define IISCON_WRITE_MASK   (0x8295007F)
91
92 /* AHB DMA Control Register */
93 #define IISAHB_WRITE_MASK     0xFF0000FB
94 #define IISAHB_LVL3EN         (1 << 27)
95 #define IISAHB_LVL2EN         (1 << 26)
96 #define IISAHB_LVL1EN         (1 << 25)
97 #define IISAHB_LVL0EN         (1 << 24)
98 #define IISAHB_LVL3INT        (1 << 23)
99 #define IISAHB_LVL2INT        (1 << 22)
100 #define IISAHB_LVL1INT        (1 << 21)
101 #define IISAHB_LVL0INT        (1 << 20)
102 #define IISAHB_LVL3CLR        (1 << 19)
103 #define IISAHB_LVL2CLR        (1 << 18)
104 #define IISAHB_LVL1CLR        (1 << 17)
105 #define IISAHB_LVL0CLR        (1 << 16)
106 #define IISAHB_DMA_STRADDRRST (1 << 7)
107 #define IISAHB_DMA_STRADDRTOG (1 << 6)
108 #define IISAHB_DMARLD         (1 << 5)
109 #define IISAHB_INTMASK        (1 << 3)
110 #define IISAHB_DMAINT         (1 << 2)
111 #define IISAHB_DMACLR         (1 << 1)
112 #define IISAHB_DMAEN          (1 << 0)
113
114 /* AHB DMA Size Register */
115 #define IISSIZE_TRNS_SIZE_OFFSET  16
116 #define IISSIZE_TRNS_SIZE_MASK    0xFFFF
117
118 /* AHB DMA Transfer Count Register */
119 #define IISTRNCNT_OFFSET 0
120 #define IISTRNCNT_MASK   0xFFFFFF
121
122 typedef struct {
123     const char *name;
124     target_phys_addr_t offset;
125     uint32_t reset_value;
126 } Exynos4210I2SReg;
127
128 static Exynos4210I2SReg exynos4210_i2s_regs[I2S_REGS_NUM] = {
129     {"IISCON",         IISCON,         0x00000000},
130     {"IISMOD",         IISMOD,         0x00000000},
131     {"IISFIC",         IISFIC,         0x00000000},
132     {"IISPSR",         IISPSR,         0x00000000},
133     {"IISTXD",         IISTXD,         0x00000000},
134     {"IISRXD",         IISRXD,         0x00000000},
135     {"IISFICS",        IISFICS,        0x00000000},
136     {"IISTXDS",        IISTXDS,        0x00000000},
137     {"IISAHB",         IISAHB,         0x00000000},
138     {"IISSTR0",        IISSTR0,        0x00000000},
139     {"IISSIZE",        IISSIZE,        0x7FFF0000},
140     {"IISTRNCNT",      IISTRNCNT,      0x00000000},
141     {"IISLVL0ADDR",    IISLVL0ADDR,    0x00000000},
142     {"IISLVL1ADDR",    IISLVL1ADDR,    0x00000000},
143     {"IISLVL2ADDR",    IISLVL2ADDR,    0x00000000},
144     {"IISLVL3ADDR",    IISLVL3ADDR,    0x00000000},
145     {"IISSTR1",        IISSTR1,        0x00000000},
146 };
147
148 static struct {
149     uint32_t ahb_en_bit;
150     uint32_t ahb_int_bit;
151     uint32_t ahb_clr_bit;
152     int reg_offset;
153 } lvl_regs[] = {
154     { IISAHB_LVL3EN, IISAHB_LVL3INT, IISAHB_LVL3CLR, IISLVL3ADDR },
155     { IISAHB_LVL2EN, IISAHB_LVL2INT, IISAHB_LVL2CLR, IISLVL2ADDR },
156     { IISAHB_LVL1EN, IISAHB_LVL1INT, IISAHB_LVL1CLR, IISLVL1ADDR },
157     { IISAHB_LVL0EN, IISAHB_LVL0INT, IISAHB_LVL0CLR, IISLVL0ADDR },
158 };
159
160 #define TYPE_EXYNOS4210_I2S_BUS "exynos4210-i2s"
161
162 typedef struct {
163     BusState qbus;
164
165     MemoryRegion iomem;
166     qemu_irq irq;
167     uint32_t reg[I2S_REGS_NUM];
168 } Exynos4210I2SBus;
169
170 static Exynos4210I2SSlave *get_slave(Exynos4210I2SBus *bus)
171 {
172     BusChild *kid = QTAILQ_FIRST(&bus->qbus.children);
173     DeviceState *dev;
174
175     if (kid) {
176         dev = kid->child;
177         if (dev) {
178             return EXYNOS4210_I2S_SLAVE_FROM_QDEV(dev);
179         }
180     }
181
182     return NULL;
183 }
184
185 static void reset_internal(BusState *qbus, bool reset_slave)
186 {
187     Exynos4210I2SBus *bus = DO_UPCAST(Exynos4210I2SBus, qbus, qbus);
188     Exynos4210I2SSlave *s;
189     int i;
190
191     DPRINTF("enter\n");
192
193     qemu_irq_lower(bus->irq);
194
195     for (i = 0; i < ARRAY_SIZE(exynos4210_i2s_regs); i++) {
196         bus->reg[i] = exynos4210_i2s_regs[i].reset_value;
197     }
198
199     if (reset_slave) {
200         s = get_slave(bus);
201
202         if (s != NULL) {
203             device_reset(&s->qdev);
204         }
205     }
206 }
207
208 static uint32_t get_dma_size_words(Exynos4210I2SBus *bus)
209 {
210     return (bus->reg[I_(IISSIZE)] >> IISSIZE_TRNS_SIZE_OFFSET) &
211             IISSIZE_TRNS_SIZE_MASK;
212 }
213
214 static uint32_t get_dma_trncnt_words(Exynos4210I2SBus *bus)
215 {
216     return (bus->reg[I_(IISTRNCNT)] >> IISTRNCNT_OFFSET) &
217             IISTRNCNT_MASK;
218 }
219
220 static void set_dma_trncnt_words(Exynos4210I2SBus *bus, uint32_t trncnt_words)
221 {
222     bus->reg[I_(IISTRNCNT)] &= ~(IISTRNCNT_MASK << IISTRNCNT_OFFSET);
223     bus->reg[I_(IISTRNCNT)] |=
224         ((trncnt_words & IISTRNCNT_MASK) << IISTRNCNT_OFFSET);
225 }
226
227 static int exynos4210_i2s_bus_reset(BusState *qbus);
228
229 static void exynos4210_i2s_bus_class_init(ObjectClass *klass, void *data)
230 {
231     BusClass *k = BUS_CLASS(klass);
232
233     k->reset    = exynos4210_i2s_bus_reset;
234 }
235
236 static struct TypeInfo exynos4210_i2s_bus_info = {
237     .name          = TYPE_EXYNOS4210_I2S_BUS,
238     .parent        = TYPE_BUS,
239     .instance_size = sizeof(Exynos4210I2SBus),
240     .class_init    = exynos4210_i2s_bus_class_init,
241 };
242
243 static const VMStateDescription vmstate_exynos4210_i2s_bus = {
244     .name = "exynos4210.i2s_bus",
245     .version_id = 1,
246     .minimum_version_id = 1,
247     .minimum_version_id_old = 1,
248     .fields      = (VMStateField[]) {
249         VMSTATE_UINT32_ARRAY(reg, Exynos4210I2SBus,
250                                   I2S_REGS_NUM),
251         VMSTATE_END_OF_LIST()
252     }
253 };
254
255 #ifdef DEBUG_I2S
256 static const char *exynos4210_i2s_regname(Exynos4210I2SBus *bus,
257                                           target_phys_addr_t offset)
258 {
259     int i;
260
261     for (i = 0; i < ARRAY_SIZE(exynos4210_i2s_regs); i++) {
262         if (offset == exynos4210_i2s_regs[i].offset) {
263             return exynos4210_i2s_regs[i].name;
264         }
265     }
266
267     return NULL;
268 }
269 #endif
270
271 static void exynos4210_i2s_bus_write(void *opaque,
272                                      target_phys_addr_t offset,
273                                      uint64_t value,
274                                      unsigned size)
275 {
276     Exynos4210I2SBus *bus = opaque;
277     Exynos4210I2SSlave *s;
278     Exynos4210I2SSlaveClass *sc;
279     int i;
280
281     s = get_slave(bus);
282
283     assert(s != NULL);
284
285     if (s == NULL) {
286         hw_error("Exynos I2S cannot operate without a slave\n");
287     }
288
289     sc = EXYNOS4210_I2S_SLAVE_GET_CLASS(s);
290
291     switch (offset) {
292     case IISCON:
293         if (!(value & IISCON_SW_RST) &&
294              (bus->reg[I_(IISCON)] & IISCON_SW_RST)) {
295             reset_internal(&bus->qbus, 1);
296         }
297
298         bus->reg[I_(offset)] = (bus->reg[I_(offset)] & ~IISCON_WRITE_MASK) |
299                                (value & IISCON_WRITE_MASK);
300
301         DPRINTF("0x%.8X -> %s\n",
302                 bus->reg[I_(offset)],
303                 exynos4210_i2s_regname(bus, offset));
304
305         break;
306     case IISAHB:
307         if (((value & IISAHB_DMAEN) != 0) && ((value & IISAHB_DMARLD) == 0)) {
308             hw_error("Non auto-reload DMA is not supported\n");
309         }
310
311         if (((value & IISAHB_DMAEN) != 0) && ((value & IISAHB_INTMASK) == 0)) {
312             hw_error("Non buffer level DMA interrupt is not supported\n");
313         }
314
315         if (((value & IISAHB_DMAEN) != 0) &&
316             ((value & IISAHB_DMA_STRADDRTOG) != 0)) {
317             hw_error("DMA start address toggle is not supported\n");
318         }
319
320         for (i = 0; i < ARRAY_SIZE(lvl_regs); ++i) {
321             if ((value & lvl_regs[i].ahb_clr_bit) &&
322                 (bus->reg[I_(IISAHB)] & lvl_regs[i].ahb_int_bit)) {
323                 qemu_irq_lower(bus->irq);
324                 bus->reg[I_(IISAHB)] &= ~lvl_regs[i].ahb_int_bit;
325             }
326         }
327
328         if ((value & IISAHB_DMACLR) &&
329             (bus->reg[I_(IISAHB)] & IISAHB_DMAINT)) {
330             qemu_irq_lower(bus->irq);
331             bus->reg[I_(IISAHB)] &= ~IISAHB_DMAINT;
332         }
333
334         if ((value & IISAHB_DMAEN) !=
335             (bus->reg[I_(IISAHB)] & IISAHB_DMAEN)) {
336             if ((value & IISAHB_DMAEN) == 0) {
337                 qemu_irq_lower(bus->irq);
338             }
339             if (sc->dma_enable) {
340                 sc->dma_enable(s, ((value & IISAHB_DMAEN) != 0));
341             }
342         }
343
344         bus->reg[I_(offset)] = (bus->reg[I_(offset)] & ~IISAHB_WRITE_MASK) |
345                                (value & IISAHB_WRITE_MASK);
346
347         DPRINTF("0x%.8X -> %s\n",
348                 bus->reg[I_(offset)],
349                 exynos4210_i2s_regname(bus, offset));
350
351         break;
352     case IISTRNCNT:
353         hw_error("Cannot write IISTRNCNT\n");
354         break;
355     case IISSIZE:
356         if (value == 0) {
357             hw_error("IISSIZE cannot be 0\n");
358         }
359
360         bus->reg[I_(offset)] = value;
361
362         if (get_dma_size_words(bus) <= get_dma_trncnt_words(bus)) {
363             set_dma_trncnt_words(bus, 0);
364         }
365
366         DPRINTF("0x%.8X -> %s\n",
367                 bus->reg[I_(offset)],
368                 exynos4210_i2s_regname(bus, offset));
369
370         break;
371     case IISLVL0ADDR:
372     case IISLVL1ADDR:
373     case IISLVL2ADDR:
374     case IISLVL3ADDR:
375     case IISTXD:
376     case IISMOD:
377     case IISFIC:
378     case IISPSR:
379     case IISTXDS:
380     case IISFICS:
381     case IISSTR0:
382     case IISSTR1:
383         bus->reg[I_(offset)] = value;
384
385         DPRINTF("0x%.8X -> %s\n",
386                 bus->reg[I_(offset)],
387                 exynos4210_i2s_regname(bus, offset));
388
389         break;
390     default:
391         hw_error("Bad offset: 0x%X\n", (int)offset);
392     }
393 }
394
395 static uint64_t exynos4210_i2s_bus_read(void *opaque,
396                                         target_phys_addr_t offset,
397                                         unsigned size)
398 {
399     Exynos4210I2SBus *bus = opaque;
400
401     if (offset > (I2S_REGS_MEM_SIZE - sizeof(uint32_t))) {
402         hw_error("Bad offset: 0x%X\n", (int)offset);
403         return 0;
404     }
405
406     DPRINTF("%s -> 0x%.8X\n",
407             exynos4210_i2s_regname(bus, offset),
408             bus->reg[I_(offset)]);
409
410     return bus->reg[I_(offset)];
411 }
412
413 static int exynos4210_i2s_bus_reset(BusState *qbus)
414 {
415     reset_internal(qbus, 0);
416
417     return 0;
418 }
419
420 static const MemoryRegionOps exynos4210_i2s_bus_ops = {
421     .read = exynos4210_i2s_bus_read,
422     .write = exynos4210_i2s_bus_write,
423     .endianness = DEVICE_NATIVE_ENDIAN,
424     .valid = {
425         .max_access_size = 4,
426         .unaligned = false
427     },
428 };
429
430 BusState *exynos4210_i2s_bus_new(const char *name,
431                                  target_phys_addr_t addr,
432                                  qemu_irq irq)
433 {
434     Exynos4210I2SBus *bus;
435
436     bus = FROM_QBUS(Exynos4210I2SBus,
437                     qbus_create(TYPE_EXYNOS4210_I2S_BUS, NULL, name));
438     vmstate_register(NULL, -1, &vmstate_exynos4210_i2s_bus, bus);
439
440     memory_region_init_io(&bus->iomem,
441                           &exynos4210_i2s_bus_ops,
442                           bus,
443                           "exynos4210.i2s",
444                           I2S_REGS_MEM_SIZE);
445
446     memory_region_add_subregion(get_system_memory(),
447                                 addr,
448                                 &bus->iomem);
449
450     bus->irq = irq;
451
452     return &bus->qbus;
453 }
454
455 bool exynos4210_i2s_dma_enabled(BusState *qbus)
456 {
457     Exynos4210I2SBus *bus = DO_UPCAST(Exynos4210I2SBus, qbus, qbus);
458
459     return ((bus->reg[I_(IISAHB)] & IISAHB_DMAEN) != 0);
460 }
461
462 uint32_t exynos4210_i2s_dma_get_words_available(BusState *qbus)
463 {
464     Exynos4210I2SBus *bus = DO_UPCAST(Exynos4210I2SBus, qbus, qbus);
465
466     return get_dma_size_words(bus);
467 }
468
469 void exynos4210_i2s_dma_read(BusState *qbus, void *buf, uint32_t num_words)
470 {
471     Exynos4210I2SBus *bus = DO_UPCAST(Exynos4210I2SBus, qbus, qbus);
472     target_phys_addr_t addr;
473     uint32_t size_words, trncnt_words;
474
475     assert(num_words <= exynos4210_i2s_dma_get_words_available(qbus));
476
477     if (num_words > exynos4210_i2s_dma_get_words_available(qbus)) {
478         hw_error("Bad DMA read length: %d\n", num_words);
479     }
480
481     size_words = get_dma_size_words(bus);
482     addr = bus->reg[I_(IISSTR0)];
483     trncnt_words = get_dma_trncnt_words(bus);
484
485     assert(trncnt_words < size_words);
486
487     if (num_words > (size_words - trncnt_words)) {
488         cpu_physical_memory_read(addr +
489                                  (trncnt_words * EXYNOS4210_I2S_WORD_LEN),
490             buf,
491             (size_words - trncnt_words) * EXYNOS4210_I2S_WORD_LEN);
492         num_words -= (size_words - trncnt_words);
493         buf += (size_words - trncnt_words) * EXYNOS4210_I2S_WORD_LEN;
494         trncnt_words = 0;
495     }
496
497     cpu_physical_memory_read(addr + (trncnt_words * EXYNOS4210_I2S_WORD_LEN),
498                              buf,
499                              num_words * EXYNOS4210_I2S_WORD_LEN);
500 }
501
502 void exynos4210_i2s_dma_advance(BusState *qbus, uint32_t num_words)
503 {
504     Exynos4210I2SBus *bus = DO_UPCAST(Exynos4210I2SBus, qbus, qbus);
505     uint32_t size_words, trncnt_words;
506     int i;
507
508     assert(num_words <= exynos4210_i2s_dma_get_words_available(qbus));
509
510     if (num_words > exynos4210_i2s_dma_get_words_available(qbus)) {
511         hw_error("Bad DMA read length: %d\n", num_words);
512     }
513
514     size_words = get_dma_size_words(bus);
515     trncnt_words = get_dma_trncnt_words(bus);
516
517     for (i = 0; i < ARRAY_SIZE(lvl_regs); ++i) {
518         target_phys_addr_t dma_offset;
519         uint32_t tmp_num_words = num_words, tmp_trncnt_words = trncnt_words;
520
521         if ((bus->reg[I_(IISAHB)] & lvl_regs[i].ahb_en_bit) == 0) {
522             continue;
523         }
524
525         if (bus->reg[I_(lvl_regs[i].reg_offset)] < bus->reg[I_(IISSTR0)]) {
526             continue;
527         }
528
529         dma_offset = bus->reg[I_(lvl_regs[i].reg_offset)] -
530                      bus->reg[I_(IISSTR0)];
531
532         if (tmp_num_words > (size_words - tmp_trncnt_words)) {
533             if ((dma_offset >= (tmp_trncnt_words * EXYNOS4210_I2S_WORD_LEN)) &&
534                 (dma_offset < size_words * EXYNOS4210_I2S_WORD_LEN)) {
535                 bus->reg[I_(IISAHB)] |= lvl_regs[i].ahb_int_bit;
536                 qemu_irq_raise(bus->irq);
537                 break;
538             }
539
540             tmp_num_words -= (size_words - tmp_trncnt_words);
541             tmp_trncnt_words = 0;
542         }
543
544         if ((dma_offset >= (tmp_trncnt_words * EXYNOS4210_I2S_WORD_LEN)) &&
545             (dma_offset <
546                 (tmp_trncnt_words + tmp_num_words) * EXYNOS4210_I2S_WORD_LEN)) {
547             bus->reg[I_(IISAHB)] |= lvl_regs[i].ahb_int_bit;
548             qemu_irq_raise(bus->irq);
549         }
550     }
551
552     set_dma_trncnt_words(bus, (trncnt_words + num_words) % size_words);
553 }
554
555 const VMStateDescription vmstate_exynos4210_i2s_slave = {
556     .name = "Exynos4210I2SSlave",
557     .version_id = 1,
558     .minimum_version_id = 1,
559     .minimum_version_id_old = 1
560 };
561
562 static int exynos4210_i2s_slave_qdev_init(DeviceState *dev)
563 {
564     Exynos4210I2SSlave *s = EXYNOS4210_I2S_SLAVE_FROM_QDEV(dev);
565     Exynos4210I2SSlaveClass *sc = EXYNOS4210_I2S_SLAVE_GET_CLASS(s);
566
567     return sc->init ? sc->init(s) : 0;
568 }
569
570 static void exynos4210_i2s_slave_class_init(ObjectClass *klass, void *data)
571 {
572     DeviceClass *k = DEVICE_CLASS(klass);
573     k->init = exynos4210_i2s_slave_qdev_init;
574     k->bus_type = TYPE_EXYNOS4210_I2S_BUS;
575 }
576
577 static TypeInfo exynos4210_i2s_slave_type_info = {
578     .name = TYPE_EXYNOS4210_I2S_SLAVE,
579     .parent = TYPE_DEVICE,
580     .instance_size = sizeof(Exynos4210I2SSlave),
581     .abstract = true,
582     .class_size = sizeof(Exynos4210I2SSlaveClass),
583     .class_init = exynos4210_i2s_slave_class_init,
584 };
585
586 static void exynos4210_i2s_slave_register_types(void)
587 {
588     type_register_static(&exynos4210_i2s_bus_info);
589     type_register_static(&exynos4210_i2s_slave_type_info);
590 }
591
592 type_init(exynos4210_i2s_slave_register_types)