Statistics
| Branch: | Revision:

root / hw / omap_i2c.c @ 99a0949b

History | View | Annotate | Download (13 kB)

1
/*
2
 * TI OMAP on-chip I2C controller.  Only "new I2C" mode supported.
3
 *
4
 * Copyright (C) 2007 Andrzej Zaborowski  <balrog@zabor.org>
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License as
8
 * published by the Free Software Foundation; either version 2 of
9
 * the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License along
17
 * with this program; if not, see <http://www.gnu.org/licenses/>.
18
 */
19
#include "hw.h"
20
#include "i2c.h"
21
#include "omap.h"
22

    
23
struct omap_i2c_s {
24
    qemu_irq irq;
25
    qemu_irq drq[2];
26
    i2c_bus *bus;
27

    
28
    uint8_t revision;
29
    uint8_t mask;
30
    uint16_t stat;
31
    uint16_t dma;
32
    uint16_t count;
33
    int count_cur;
34
    uint32_t fifo;
35
    int rxlen;
36
    int txlen;
37
    uint16_t control;
38
    uint16_t addr[2];
39
    uint8_t divider;
40
    uint8_t times[2];
41
    uint16_t test;
42
};
43

    
44
#define OMAP2_INTR_REV        0x34
45
#define OMAP2_GC_REV        0x34
46

    
47
static void omap_i2c_interrupts_update(struct omap_i2c_s *s)
48
{
49
    qemu_set_irq(s->irq, s->stat & s->mask);
50
    if ((s->dma >> 15) & 1)                                        /* RDMA_EN */
51
        qemu_set_irq(s->drq[0], (s->stat >> 3) & 1);                /* RRDY */
52
    if ((s->dma >> 7) & 1)                                        /* XDMA_EN */
53
        qemu_set_irq(s->drq[1], (s->stat >> 4) & 1);                /* XRDY */
54
}
55

    
56
static void omap_i2c_fifo_run(struct omap_i2c_s *s)
57
{
58
    int ack = 1;
59

    
60
    if (!i2c_bus_busy(s->bus))
61
        return;
62

    
63
    if ((s->control >> 2) & 1) {                                /* RM */
64
        if ((s->control >> 1) & 1) {                                /* STP */
65
            i2c_end_transfer(s->bus);
66
            s->control &= ~(1 << 1);                                /* STP */
67
            s->count_cur = s->count;
68
            s->txlen = 0;
69
        } else if ((s->control >> 9) & 1) {                        /* TRX */
70
            while (ack && s->txlen)
71
                ack = (i2c_send(s->bus,
72
                                        (s->fifo >> ((-- s->txlen) << 3)) &
73
                                        0xff) >= 0);
74
            s->stat |= 1 << 4;                                        /* XRDY */
75
        } else {
76
            while (s->rxlen < 4)
77
                s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
78
            s->stat |= 1 << 3;                                        /* RRDY */
79
        }
80
    } else {
81
        if ((s->control >> 9) & 1) {                                /* TRX */
82
            while (ack && s->count_cur && s->txlen) {
83
                ack = (i2c_send(s->bus,
84
                                        (s->fifo >> ((-- s->txlen) << 3)) &
85
                                        0xff) >= 0);
86
                s->count_cur --;
87
            }
88
            if (ack && s->count_cur)
89
                s->stat |= 1 << 4;                                /* XRDY */
90
            else
91
                s->stat &= ~(1 << 4);                                /* XRDY */
92
            if (!s->count_cur) {
93
                s->stat |= 1 << 2;                                /* ARDY */
94
                s->control &= ~(1 << 10);                        /* MST */
95
            }
96
        } else {
97
            while (s->count_cur && s->rxlen < 4) {
98
                s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
99
                s->count_cur --;
100
            }
101
            if (s->rxlen)
102
                s->stat |= 1 << 3;                                /* RRDY */
103
            else
104
                s->stat &= ~(1 << 3);                                /* RRDY */
105
        }
106
        if (!s->count_cur) {
107
            if ((s->control >> 1) & 1) {                        /* STP */
108
                i2c_end_transfer(s->bus);
109
                s->control &= ~(1 << 1);                        /* STP */
110
                s->count_cur = s->count;
111
                s->txlen = 0;
112
            } else {
113
                s->stat |= 1 << 2;                                /* ARDY */
114
                s->control &= ~(1 << 10);                        /* MST */
115
            }
116
        }
117
    }
118

    
119
    s->stat |= (!ack) << 1;                                        /* NACK */
120
    if (!ack)
121
        s->control &= ~(1 << 1);                                /* STP */
122
}
123

    
124
void omap_i2c_reset(struct omap_i2c_s *s)
125
{
126
    s->mask = 0;
127
    s->stat = 0;
128
    s->dma = 0;
129
    s->count = 0;
130
    s->count_cur = 0;
131
    s->fifo = 0;
132
    s->rxlen = 0;
133
    s->txlen = 0;
134
    s->control = 0;
135
    s->addr[0] = 0;
136
    s->addr[1] = 0;
137
    s->divider = 0;
138
    s->times[0] = 0;
139
    s->times[1] = 0;
140
    s->test = 0;
141
}
142

    
143
static uint32_t omap_i2c_read(void *opaque, a_target_phys_addr addr)
144
{
145
    struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
146
    int offset = addr & OMAP_MPUI_REG_MASK;
147
    uint16_t ret;
148

    
149
    switch (offset) {
150
    case 0x00:        /* I2C_REV */
151
        return s->revision;                                        /* REV */
152

    
153
    case 0x04:        /* I2C_IE */
154
        return s->mask;
155

    
156
    case 0x08:        /* I2C_STAT */
157
        return s->stat | (i2c_bus_busy(s->bus) << 12);
158

    
159
    case 0x0c:        /* I2C_IV */
160
        if (s->revision >= OMAP2_INTR_REV)
161
            break;
162
        ret = ffs(s->stat & s->mask);
163
        if (ret)
164
            s->stat ^= 1 << (ret - 1);
165
        omap_i2c_interrupts_update(s);
166
        return ret;
167

    
168
    case 0x10:        /* I2C_SYSS */
169
        return (s->control >> 15) & 1;                                /* I2C_EN */
170

    
171
    case 0x14:        /* I2C_BUF */
172
        return s->dma;
173

    
174
    case 0x18:        /* I2C_CNT */
175
        return s->count_cur;                                        /* DCOUNT */
176

    
177
    case 0x1c:        /* I2C_DATA */
178
        ret = 0;
179
        if (s->control & (1 << 14)) {                                /* BE */
180
            ret |= ((s->fifo >> 0) & 0xff) << 8;
181
            ret |= ((s->fifo >> 8) & 0xff) << 0;
182
        } else {
183
            ret |= ((s->fifo >> 8) & 0xff) << 8;
184
            ret |= ((s->fifo >> 0) & 0xff) << 0;
185
        }
186
        if (s->rxlen == 1) {
187
            s->stat |= 1 << 15;                                        /* SBD */
188
            s->rxlen = 0;
189
        } else if (s->rxlen > 1) {
190
            if (s->rxlen > 2)
191
                s->fifo >>= 16;
192
            s->rxlen -= 2;
193
        } else
194
            /* XXX: remote access (qualifier) error - what's that?  */;
195
        if (!s->rxlen) {
196
            s->stat &= ~(1 << 3);                                /* RRDY */
197
            if (((s->control >> 10) & 1) &&                        /* MST */
198
                            ((~s->control >> 9) & 1)) {                /* TRX */
199
                s->stat |= 1 << 2;                                /* ARDY */
200
                s->control &= ~(1 << 10);                        /* MST */
201
            }
202
        }
203
        s->stat &= ~(1 << 11);                                        /* ROVR */
204
        omap_i2c_fifo_run(s);
205
        omap_i2c_interrupts_update(s);
206
        return ret;
207

    
208
    case 0x20:        /* I2C_SYSC */
209
        return 0;
210

    
211
    case 0x24:        /* I2C_CON */
212
        return s->control;
213

    
214
    case 0x28:        /* I2C_OA */
215
        return s->addr[0];
216

    
217
    case 0x2c:        /* I2C_SA */
218
        return s->addr[1];
219

    
220
    case 0x30:        /* I2C_PSC */
221
        return s->divider;
222

    
223
    case 0x34:        /* I2C_SCLL */
224
        return s->times[0];
225

    
226
    case 0x38:        /* I2C_SCLH */
227
        return s->times[1];
228

    
229
    case 0x3c:        /* I2C_SYSTEST */
230
        if (s->test & (1 << 15)) {                                /* ST_EN */
231
            s->test ^= 0xa;
232
            return s->test;
233
        } else
234
            return s->test & ~0x300f;
235
    }
236

    
237
    OMAP_BAD_REG(addr);
238
    return 0;
239
}
240

    
241
static void omap_i2c_write(void *opaque, a_target_phys_addr addr,
242
                uint32_t value)
243
{
244
    struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
245
    int offset = addr & OMAP_MPUI_REG_MASK;
246
    int nack;
247

    
248
    switch (offset) {
249
    case 0x00:        /* I2C_REV */
250
    case 0x0c:        /* I2C_IV */
251
    case 0x10:        /* I2C_SYSS */
252
        OMAP_RO_REG(addr);
253
        return;
254

    
255
    case 0x04:        /* I2C_IE */
256
        s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f);
257
        break;
258

    
259
    case 0x08:        /* I2C_STAT */
260
        if (s->revision < OMAP2_INTR_REV) {
261
            OMAP_RO_REG(addr);
262
            return;
263
        }
264

    
265
        /* RRDY and XRDY are reset by hardware. (in all versions???) */
266
        s->stat &= ~(value & 0x27);
267
        omap_i2c_interrupts_update(s);
268
        break;
269

    
270
    case 0x14:        /* I2C_BUF */
271
        s->dma = value & 0x8080;
272
        if (value & (1 << 15))                                        /* RDMA_EN */
273
            s->mask &= ~(1 << 3);                                /* RRDY_IE */
274
        if (value & (1 << 7))                                        /* XDMA_EN */
275
            s->mask &= ~(1 << 4);                                /* XRDY_IE */
276
        break;
277

    
278
    case 0x18:        /* I2C_CNT */
279
        s->count = value;                                        /* DCOUNT */
280
        break;
281

    
282
    case 0x1c:        /* I2C_DATA */
283
        if (s->txlen > 2) {
284
            /* XXX: remote access (qualifier) error - what's that?  */
285
            break;
286
        }
287
        s->fifo <<= 16;
288
        s->txlen += 2;
289
        if (s->control & (1 << 14)) {                                /* BE */
290
            s->fifo |= ((value >> 8) & 0xff) << 8;
291
            s->fifo |= ((value >> 0) & 0xff) << 0;
292
        } else {
293
            s->fifo |= ((value >> 0) & 0xff) << 8;
294
            s->fifo |= ((value >> 8) & 0xff) << 0;
295
        }
296
        s->stat &= ~(1 << 10);                                        /* XUDF */
297
        if (s->txlen > 2)
298
            s->stat &= ~(1 << 4);                                /* XRDY */
299
        omap_i2c_fifo_run(s);
300
        omap_i2c_interrupts_update(s);
301
        break;
302

    
303
    case 0x20:        /* I2C_SYSC */
304
        if (s->revision < OMAP2_INTR_REV) {
305
            OMAP_BAD_REG(addr);
306
            return;
307
        }
308

    
309
        if (value & 2)
310
            omap_i2c_reset(s);
311
        break;
312

    
313
    case 0x24:        /* I2C_CON */
314
        s->control = value & 0xcf87;
315
        if (~value & (1 << 15)) {                                /* I2C_EN */
316
            if (s->revision < OMAP2_INTR_REV)
317
                omap_i2c_reset(s);
318
            break;
319
        }
320
        if ((value & (1 << 15)) && !(value & (1 << 10))) {        /* MST */
321
            fprintf(stderr, "%s: I^2C slave mode not supported\n",
322
                            __FUNCTION__);
323
            break;
324
        }
325
        if ((value & (1 << 15)) && value & (1 << 8)) {                /* XA */
326
            fprintf(stderr, "%s: 10-bit addressing mode not supported\n",
327
                            __FUNCTION__);
328
            break;
329
        }
330
        if ((value & (1 << 15)) && value & (1 << 0)) {                /* STT */
331
            nack = !!i2c_start_transfer(s->bus, s->addr[1],        /* SA */
332
                            (~value >> 9) & 1);                        /* TRX */
333
            s->stat |= nack << 1;                                /* NACK */
334
            s->control &= ~(1 << 0);                                /* STT */
335
            s->fifo = 0;
336
            if (nack)
337
                s->control &= ~(1 << 1);                        /* STP */
338
            else {
339
                s->count_cur = s->count;
340
                omap_i2c_fifo_run(s);
341
            }
342
            omap_i2c_interrupts_update(s);
343
        }
344
        break;
345

    
346
    case 0x28:        /* I2C_OA */
347
        s->addr[0] = value & 0x3ff;
348
        break;
349

    
350
    case 0x2c:        /* I2C_SA */
351
        s->addr[1] = value & 0x3ff;
352
        break;
353

    
354
    case 0x30:        /* I2C_PSC */
355
        s->divider = value;
356
        break;
357

    
358
    case 0x34:        /* I2C_SCLL */
359
        s->times[0] = value;
360
        break;
361

    
362
    case 0x38:        /* I2C_SCLH */
363
        s->times[1] = value;
364
        break;
365

    
366
    case 0x3c:        /* I2C_SYSTEST */
367
        s->test = value & 0xf80f;
368
        if (value & (1 << 11))                                        /* SBB */
369
            if (s->revision >= OMAP2_INTR_REV) {
370
                s->stat |= 0x3f;
371
                omap_i2c_interrupts_update(s);
372
            }
373
        if (value & (1 << 15))                                        /* ST_EN */
374
            fprintf(stderr, "%s: System Test not supported\n", __FUNCTION__);
375
        break;
376

    
377
    default:
378
        OMAP_BAD_REG(addr);
379
        return;
380
    }
381
}
382

    
383
static void omap_i2c_writeb(void *opaque, a_target_phys_addr addr,
384
                uint32_t value)
385
{
386
    struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
387
    int offset = addr & OMAP_MPUI_REG_MASK;
388

    
389
    switch (offset) {
390
    case 0x1c:        /* I2C_DATA */
391
        if (s->txlen > 2) {
392
            /* XXX: remote access (qualifier) error - what's that?  */
393
            break;
394
        }
395
        s->fifo <<= 8;
396
        s->txlen += 1;
397
        s->fifo |= value & 0xff;
398
        s->stat &= ~(1 << 10);                                        /* XUDF */
399
        if (s->txlen > 2)
400
            s->stat &= ~(1 << 4);                                /* XRDY */
401
        omap_i2c_fifo_run(s);
402
        omap_i2c_interrupts_update(s);
403
        break;
404

    
405
    default:
406
        OMAP_BAD_REG(addr);
407
        return;
408
    }
409
}
410

    
411
static CPUReadMemoryFunc * const omap_i2c_readfn[] = {
412
    omap_badwidth_read16,
413
    omap_i2c_read,
414
    omap_badwidth_read16,
415
};
416

    
417
static CPUWriteMemoryFunc * const omap_i2c_writefn[] = {
418
    omap_i2c_writeb,        /* Only the last fifo write can be 8 bit.  */
419
    omap_i2c_write,
420
    omap_badwidth_write16,
421
};
422

    
423
struct omap_i2c_s *omap_i2c_init(a_target_phys_addr base,
424
                qemu_irq irq, qemu_irq *dma, omap_clk clk)
425
{
426
    int iomemtype;
427
    struct omap_i2c_s *s = (struct omap_i2c_s *)
428
            qemu_mallocz(sizeof(struct omap_i2c_s));
429

    
430
    /* TODO: set a value greater or equal to real hardware */
431
    s->revision = 0x11;
432
    s->irq = irq;
433
    s->drq[0] = dma[0];
434
    s->drq[1] = dma[1];
435
    s->bus = i2c_init_bus(NULL, "i2c");
436
    omap_i2c_reset(s);
437

    
438
    iomemtype = cpu_register_io_memory(omap_i2c_readfn,
439
                    omap_i2c_writefn, s);
440
    cpu_register_physical_memory(base, 0x800, iomemtype);
441

    
442
    return s;
443
}
444

    
445
struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
446
                qemu_irq irq, qemu_irq *dma, omap_clk fclk, omap_clk iclk)
447
{
448
    int iomemtype;
449
    struct omap_i2c_s *s = (struct omap_i2c_s *)
450
            qemu_mallocz(sizeof(struct omap_i2c_s));
451

    
452
    s->revision = 0x34;
453
    s->irq = irq;
454
    s->drq[0] = dma[0];
455
    s->drq[1] = dma[1];
456
    s->bus = i2c_init_bus(NULL, "i2c");
457
    omap_i2c_reset(s);
458

    
459
    iomemtype = l4_register_io_memory(omap_i2c_readfn,
460
                    omap_i2c_writefn, s);
461
    omap_l4_attach(ta, 0, iomemtype);
462

    
463
    return s;
464
}
465

    
466
i2c_bus *omap_i2c_bus(struct omap_i2c_s *s)
467
{
468
    return s->bus;
469
}