2 * Samsung exynos4210 I2S driver
4 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * Vorobiov Stanislav <s.vorobiov@samsung.com>
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.
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
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/>.
22 #include "exynos4210_i2s.h"
23 #include "exec-memory.h"
25 /* #define DEBUG_I2S */
28 #define DPRINTF(fmt, ...) \
30 fprintf(stdout, "I2S: [%s:%d] " fmt, __func__, __LINE__, \
34 #define DPRINTF(fmt, ...) do {} while (0)
49 #define IISTRNCNT 0x2C
50 #define IISLVL0ADDR 0x30
51 #define IISLVL1ADDR 0x34
52 #define IISLVL2ADDR 0x38
53 #define IISLVL3ADDR 0x3C
56 #define I2S_REGS_MEM_SIZE 0x44
57 #define I2S_REGS_NUM (I2S_REGS_MEM_SIZE >> 2)
59 #define I_(reg) (reg / sizeof(uint32_t))
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)
90 #define IISCON_WRITE_MASK (0x8295007F)
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)
114 /* AHB DMA Size Register */
115 #define IISSIZE_TRNS_SIZE_OFFSET 16
116 #define IISSIZE_TRNS_SIZE_MASK 0xFFFF
118 /* AHB DMA Transfer Count Register */
119 #define IISTRNCNT_OFFSET 0
120 #define IISTRNCNT_MASK 0xFFFFFF
124 target_phys_addr_t offset;
125 uint32_t reset_value;
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},
150 uint32_t ahb_int_bit;
151 uint32_t ahb_clr_bit;
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 },
160 #define TYPE_EXYNOS4210_I2S_BUS "exynos4210-i2s"
167 uint32_t reg[I2S_REGS_NUM];
170 static Exynos4210I2SSlave *get_slave(Exynos4210I2SBus *bus)
172 BusChild *kid = QTAILQ_FIRST(&bus->qbus.children);
178 return EXYNOS4210_I2S_SLAVE_FROM_QDEV(dev);
185 static void reset_internal(BusState *qbus, bool reset_slave)
187 Exynos4210I2SBus *bus = DO_UPCAST(Exynos4210I2SBus, qbus, qbus);
188 Exynos4210I2SSlave *s;
193 qemu_irq_lower(bus->irq);
195 for (i = 0; i < ARRAY_SIZE(exynos4210_i2s_regs); i++) {
196 bus->reg[i] = exynos4210_i2s_regs[i].reset_value;
203 device_reset(&s->qdev);
208 static uint32_t get_dma_size_words(Exynos4210I2SBus *bus)
210 return (bus->reg[I_(IISSIZE)] >> IISSIZE_TRNS_SIZE_OFFSET) &
211 IISSIZE_TRNS_SIZE_MASK;
214 static uint32_t get_dma_trncnt_words(Exynos4210I2SBus *bus)
216 return (bus->reg[I_(IISTRNCNT)] >> IISTRNCNT_OFFSET) &
220 static void set_dma_trncnt_words(Exynos4210I2SBus *bus, uint32_t trncnt_words)
222 bus->reg[I_(IISTRNCNT)] &= ~(IISTRNCNT_MASK << IISTRNCNT_OFFSET);
223 bus->reg[I_(IISTRNCNT)] |=
224 ((trncnt_words & IISTRNCNT_MASK) << IISTRNCNT_OFFSET);
227 static int exynos4210_i2s_bus_reset(BusState *qbus);
229 static void exynos4210_i2s_bus_class_init(ObjectClass *klass, void *data)
231 BusClass *k = BUS_CLASS(klass);
233 k->reset = exynos4210_i2s_bus_reset;
236 static struct TypeInfo exynos4210_i2s_bus_info = {
237 .name = TYPE_EXYNOS4210_I2S_BUS,
239 .instance_size = sizeof(Exynos4210I2SBus),
240 .class_init = exynos4210_i2s_bus_class_init,
243 static const VMStateDescription vmstate_exynos4210_i2s_bus = {
244 .name = "exynos4210.i2s_bus",
246 .minimum_version_id = 1,
247 .minimum_version_id_old = 1,
248 .fields = (VMStateField[]) {
249 VMSTATE_UINT32_ARRAY(reg, Exynos4210I2SBus,
251 VMSTATE_END_OF_LIST()
256 static const char *exynos4210_i2s_regname(Exynos4210I2SBus *bus,
257 target_phys_addr_t offset)
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;
271 static void exynos4210_i2s_bus_write(void *opaque,
272 target_phys_addr_t offset,
276 Exynos4210I2SBus *bus = opaque;
277 Exynos4210I2SSlave *s;
278 Exynos4210I2SSlaveClass *sc;
286 hw_error("Exynos I2S cannot operate without a slave\n");
289 sc = EXYNOS4210_I2S_SLAVE_GET_CLASS(s);
293 if (!(value & IISCON_SW_RST) &&
294 (bus->reg[I_(IISCON)] & IISCON_SW_RST)) {
295 reset_internal(&bus->qbus, 1);
298 bus->reg[I_(offset)] = (bus->reg[I_(offset)] & ~IISCON_WRITE_MASK) |
299 (value & IISCON_WRITE_MASK);
301 DPRINTF("0x%.8X -> %s\n",
302 bus->reg[I_(offset)],
303 exynos4210_i2s_regname(bus, offset));
307 if (((value & IISAHB_DMAEN) != 0) && ((value & IISAHB_DMARLD) == 0)) {
308 hw_error("Non auto-reload DMA is not supported\n");
311 if (((value & IISAHB_DMAEN) != 0) && ((value & IISAHB_INTMASK) == 0)) {
312 hw_error("Non buffer level DMA interrupt is not supported\n");
315 if (((value & IISAHB_DMAEN) != 0) &&
316 ((value & IISAHB_DMA_STRADDRTOG) != 0)) {
317 hw_error("DMA start address toggle is not supported\n");
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;
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;
334 if ((value & IISAHB_DMAEN) !=
335 (bus->reg[I_(IISAHB)] & IISAHB_DMAEN)) {
336 if ((value & IISAHB_DMAEN) == 0) {
337 qemu_irq_lower(bus->irq);
339 if (sc->dma_enable) {
340 sc->dma_enable(s, ((value & IISAHB_DMAEN) != 0));
344 bus->reg[I_(offset)] = (bus->reg[I_(offset)] & ~IISAHB_WRITE_MASK) |
345 (value & IISAHB_WRITE_MASK);
347 DPRINTF("0x%.8X -> %s\n",
348 bus->reg[I_(offset)],
349 exynos4210_i2s_regname(bus, offset));
353 hw_error("Cannot write IISTRNCNT\n");
357 hw_error("IISSIZE cannot be 0\n");
360 bus->reg[I_(offset)] = value;
362 if (get_dma_size_words(bus) <= get_dma_trncnt_words(bus)) {
363 set_dma_trncnt_words(bus, 0);
366 DPRINTF("0x%.8X -> %s\n",
367 bus->reg[I_(offset)],
368 exynos4210_i2s_regname(bus, offset));
383 bus->reg[I_(offset)] = value;
385 DPRINTF("0x%.8X -> %s\n",
386 bus->reg[I_(offset)],
387 exynos4210_i2s_regname(bus, offset));
391 hw_error("Bad offset: 0x%X\n", (int)offset);
395 static uint64_t exynos4210_i2s_bus_read(void *opaque,
396 target_phys_addr_t offset,
399 Exynos4210I2SBus *bus = opaque;
401 if (offset > (I2S_REGS_MEM_SIZE - sizeof(uint32_t))) {
402 hw_error("Bad offset: 0x%X\n", (int)offset);
406 DPRINTF("%s -> 0x%.8X\n",
407 exynos4210_i2s_regname(bus, offset),
408 bus->reg[I_(offset)]);
410 return bus->reg[I_(offset)];
413 static int exynos4210_i2s_bus_reset(BusState *qbus)
415 reset_internal(qbus, 0);
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,
425 .max_access_size = 4,
430 BusState *exynos4210_i2s_bus_new(const char *name,
431 target_phys_addr_t addr,
434 Exynos4210I2SBus *bus;
436 bus = FROM_QBUS(Exynos4210I2SBus,
437 qbus_create(TYPE_EXYNOS4210_I2S_BUS, NULL, name));
438 vmstate_register(NULL, -1, &vmstate_exynos4210_i2s_bus, bus);
440 memory_region_init_io(&bus->iomem,
441 &exynos4210_i2s_bus_ops,
446 memory_region_add_subregion(get_system_memory(),
455 bool exynos4210_i2s_dma_enabled(BusState *qbus)
457 Exynos4210I2SBus *bus = DO_UPCAST(Exynos4210I2SBus, qbus, qbus);
459 return ((bus->reg[I_(IISAHB)] & IISAHB_DMAEN) != 0);
462 uint32_t exynos4210_i2s_dma_get_words_available(BusState *qbus)
464 Exynos4210I2SBus *bus = DO_UPCAST(Exynos4210I2SBus, qbus, qbus);
466 return get_dma_size_words(bus);
469 void exynos4210_i2s_dma_read(BusState *qbus, void *buf, uint32_t num_words)
471 Exynos4210I2SBus *bus = DO_UPCAST(Exynos4210I2SBus, qbus, qbus);
472 target_phys_addr_t addr;
473 uint32_t size_words, trncnt_words;
475 assert(num_words <= exynos4210_i2s_dma_get_words_available(qbus));
477 if (num_words > exynos4210_i2s_dma_get_words_available(qbus)) {
478 hw_error("Bad DMA read length: %d\n", num_words);
481 size_words = get_dma_size_words(bus);
482 addr = bus->reg[I_(IISSTR0)];
483 trncnt_words = get_dma_trncnt_words(bus);
485 assert(trncnt_words < size_words);
487 if (num_words > (size_words - trncnt_words)) {
488 cpu_physical_memory_read(addr +
489 (trncnt_words * EXYNOS4210_I2S_WORD_LEN),
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;
497 cpu_physical_memory_read(addr + (trncnt_words * EXYNOS4210_I2S_WORD_LEN),
499 num_words * EXYNOS4210_I2S_WORD_LEN);
502 void exynos4210_i2s_dma_advance(BusState *qbus, uint32_t num_words)
504 Exynos4210I2SBus *bus = DO_UPCAST(Exynos4210I2SBus, qbus, qbus);
505 uint32_t size_words, trncnt_words;
508 assert(num_words <= exynos4210_i2s_dma_get_words_available(qbus));
510 if (num_words > exynos4210_i2s_dma_get_words_available(qbus)) {
511 hw_error("Bad DMA read length: %d\n", num_words);
514 size_words = get_dma_size_words(bus);
515 trncnt_words = get_dma_trncnt_words(bus);
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;
521 if ((bus->reg[I_(IISAHB)] & lvl_regs[i].ahb_en_bit) == 0) {
525 if (bus->reg[I_(lvl_regs[i].reg_offset)] < bus->reg[I_(IISSTR0)]) {
529 dma_offset = bus->reg[I_(lvl_regs[i].reg_offset)] -
530 bus->reg[I_(IISSTR0)];
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);
540 tmp_num_words -= (size_words - tmp_trncnt_words);
541 tmp_trncnt_words = 0;
544 if ((dma_offset >= (tmp_trncnt_words * EXYNOS4210_I2S_WORD_LEN)) &&
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);
552 set_dma_trncnt_words(bus, (trncnt_words + num_words) % size_words);
555 const VMStateDescription vmstate_exynos4210_i2s_slave = {
556 .name = "Exynos4210I2SSlave",
558 .minimum_version_id = 1,
559 .minimum_version_id_old = 1
562 static int exynos4210_i2s_slave_qdev_init(DeviceState *dev)
564 Exynos4210I2SSlave *s = EXYNOS4210_I2S_SLAVE_FROM_QDEV(dev);
565 Exynos4210I2SSlaveClass *sc = EXYNOS4210_I2S_SLAVE_GET_CLASS(s);
567 return sc->init ? sc->init(s) : 0;
570 static void exynos4210_i2s_slave_class_init(ObjectClass *klass, void *data)
572 DeviceClass *k = DEVICE_CLASS(klass);
573 k->init = exynos4210_i2s_slave_qdev_init;
574 k->bus_type = TYPE_EXYNOS4210_I2S_BUS;
577 static TypeInfo exynos4210_i2s_slave_type_info = {
578 .name = TYPE_EXYNOS4210_I2S_SLAVE,
579 .parent = TYPE_DEVICE,
580 .instance_size = sizeof(Exynos4210I2SSlave),
582 .class_size = sizeof(Exynos4210I2SSlaveClass),
583 .class_init = exynos4210_i2s_slave_class_init,
586 static void exynos4210_i2s_slave_register_types(void)
588 type_register_static(&exynos4210_i2s_bus_info);
589 type_register_static(&exynos4210_i2s_slave_type_info);
592 type_init(exynos4210_i2s_slave_register_types)