Revision 2a952feb

b/hw/omap.h
122 122
                                   target_phys_addr_t base, qemu_irq irq);
123 123
void omap_gpmc_reset(struct omap_gpmc_s *s);
124 124
void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, MemoryRegion *iomem);
125
void omap_gpmc_attach_nand(struct omap_gpmc_s *s, int cs, DeviceState *nand);
125 126

  
126 127
/*
127 128
 * Common IRQ numbers for level 1 interrupt handler
b/hw/omap_gpmc.c
43 43
        uint32_t config[7];
44 44
        MemoryRegion *iomem;
45 45
        MemoryRegion container;
46
        MemoryRegion nandiomem;
47
        DeviceState *dev;
46 48
    } cs_file[8];
47 49
    int ecc_cs;
48 50
    int ecc_ptr;
......
50 52
    ECCState ecc[9];
51 53
};
52 54

  
55
#define OMAP_GPMC_8BIT 0
56
#define OMAP_GPMC_16BIT 1
57
#define OMAP_GPMC_NOR 0
58
#define OMAP_GPMC_NAND 2
59

  
60
static int omap_gpmc_devtype(struct omap_gpmc_cs_file_s *f)
61
{
62
    return (f->config[0] >> 10) & 3;
63
}
64

  
65
static int omap_gpmc_devsize(struct omap_gpmc_cs_file_s *f)
66
{
67
    /* devsize field is really 2 bits but we ignore the high
68
     * bit to ensure consistent behaviour if the guest sets
69
     * it (values 2 and 3 are reserved in the TRM)
70
     */
71
    return (f->config[0] >> 12) & 1;
72
}
73

  
53 74
static void omap_gpmc_int_update(struct omap_gpmc_s *s)
54 75
{
55 76
    qemu_set_irq(s->irq, s->irqen & s->irqst);
56 77
}
57 78

  
79
/* Access functions for when a NAND-like device is mapped into memory:
80
 * all addresses in the region behave like accesses to the relevant
81
 * GPMC_NAND_DATA_i register (which is actually implemented to call these)
82
 */
83
static uint64_t omap_nand_read(void *opaque, target_phys_addr_t addr,
84
                               unsigned size)
85
{
86
    struct omap_gpmc_cs_file_s *f = (struct omap_gpmc_cs_file_s *)opaque;
87
    uint64_t v;
88
    nand_setpins(f->dev, 0, 0, 0, 1, 0);
89
    switch (omap_gpmc_devsize(f)) {
90
    case OMAP_GPMC_8BIT:
91
        v = nand_getio(f->dev);
92
        if (size == 1) {
93
            return v;
94
        }
95
        v |= (nand_getio(f->dev) << 8);
96
        if (size == 2) {
97
            return v;
98
        }
99
        v |= (nand_getio(f->dev) << 16);
100
        v |= (nand_getio(f->dev) << 24);
101
        return v;
102
    case OMAP_GPMC_16BIT:
103
        v = nand_getio(f->dev);
104
        if (size == 1) {
105
            /* 8 bit read from 16 bit device : probably a guest bug */
106
            return v & 0xff;
107
        }
108
        if (size == 2) {
109
            return v;
110
        }
111
        v |= (nand_getio(f->dev) << 16);
112
        return v;
113
    default:
114
        abort();
115
    }
116
}
117

  
118
static void omap_nand_setio(DeviceState *dev, uint64_t value,
119
                            int nandsize, int size)
120
{
121
    /* Write the specified value to the NAND device, respecting
122
     * both size of the NAND device and size of the write access.
123
     */
124
    switch (nandsize) {
125
    case OMAP_GPMC_8BIT:
126
        switch (size) {
127
        case 1:
128
            nand_setio(dev, value & 0xff);
129
            break;
130
        case 2:
131
            nand_setio(dev, value & 0xff);
132
            nand_setio(dev, (value >> 8) & 0xff);
133
            break;
134
        case 4:
135
        default:
136
            nand_setio(dev, value & 0xff);
137
            nand_setio(dev, (value >> 8) & 0xff);
138
            nand_setio(dev, (value >> 16) & 0xff);
139
            nand_setio(dev, (value >> 24) & 0xff);
140
            break;
141
        }
142
    case OMAP_GPMC_16BIT:
143
        switch (size) {
144
        case 1:
145
            /* writing to a 16bit device with 8bit access is probably a guest
146
             * bug; pass the value through anyway.
147
             */
148
        case 2:
149
            nand_setio(dev, value & 0xffff);
150
            break;
151
        case 4:
152
        default:
153
            nand_setio(dev, value & 0xffff);
154
            nand_setio(dev, (value >> 16) & 0xffff);
155
            break;
156
        }
157
    }
158
}
159

  
160
static void omap_nand_write(void *opaque, target_phys_addr_t addr,
161
                            uint64_t value, unsigned size)
162
{
163
    struct omap_gpmc_cs_file_s *f = (struct omap_gpmc_cs_file_s *)opaque;
164
    nand_setpins(f->dev, 0, 0, 0, 1, 0);
165
    omap_nand_setio(f->dev, value, omap_gpmc_devsize(f), size);
166
}
167

  
168
static const MemoryRegionOps omap_nand_ops = {
169
    .read = omap_nand_read,
170
    .write = omap_nand_write,
171
    .endianness = DEVICE_NATIVE_ENDIAN,
172
};
173

  
174
static MemoryRegion *omap_gpmc_cs_memregion(struct omap_gpmc_s *s, int cs)
175
{
176
    /* Return the MemoryRegion* to map/unmap for this chipselect */
177
    struct omap_gpmc_cs_file_s *f = &s->cs_file[cs];
178
    if (omap_gpmc_devtype(f) == OMAP_GPMC_NOR) {
179
        return f->iomem;
180
    }
181
    return &f->nandiomem;
182
}
183

  
58 184
static void omap_gpmc_cs_map(struct omap_gpmc_s *s, int cs)
59 185
{
60 186
    struct omap_gpmc_cs_file_s *f = &s->cs_file[cs];
......
62 188
    uint32_t base = f->config[6] & 0x3f;
63 189
    uint32_t size;
64 190

  
65
    if (!f->iomem) {
191
    if (!f->iomem && !f->dev) {
66 192
        return;
67 193
    }
68 194

  
......
86 212
     * that the same memory becomes accessible at every <i>size</i> bytes
87 213
     * starting from <i>base</i>.  */
88 214
    memory_region_init(&f->container, "omap-gpmc-file", size);
89
    memory_region_add_subregion(&f->container, 0, f->iomem);
215
    memory_region_add_subregion(&f->container, 0,
216
                                omap_gpmc_cs_memregion(s, cs));
90 217
    memory_region_add_subregion(get_system_memory(), base,
91 218
                                &f->container);
92 219
}
......
98 225
        /* Do nothing unless CSVALID */
99 226
        return;
100 227
    }
101
    if (!f->iomem) {
228
    if (!f->iomem && !f->dev) {
102 229
        return;
103 230
    }
104

  
105 231
    memory_region_del_subregion(get_system_memory(), &f->container);
106
    memory_region_del_subregion(&f->container, f->iomem);
232
    memory_region_del_subregion(&f->container, omap_gpmc_cs_memregion(s, cs));
107 233
    memory_region_destroy(&f->container);
108 234
}
109 235

  
......
151 277
        ecc_reset(&s->ecc[i]);
152 278
}
153 279

  
280
static int gpmc_wordaccess_only(target_phys_addr_t addr)
281
{
282
    /* Return true if the register offset is to a register that
283
     * only permits word width accesses.
284
     * Non-word accesses are only OK for GPMC_NAND_DATA/ADDRESS/COMMAND
285
     * for any chipselect.
286
     */
287
    if (addr >= 0x60 && addr <= 0x1d4) {
288
        int cs = (addr - 0x60) / 0x30;
289
        addr -= cs * 0x30;
290
        if (addr >= 0x7c && addr < 0x88) {
291
            /* GPMC_NAND_COMMAND, GPMC_NAND_ADDRESS, GPMC_NAND_DATA */
292
            return 0;
293
        }
294
    }
295
    return 1;
296
}
297

  
154 298
static uint64_t omap_gpmc_read(void *opaque, target_phys_addr_t addr,
155 299
                               unsigned size)
156 300
{
......
158 302
    int cs;
159 303
    struct omap_gpmc_cs_file_s *f;
160 304

  
161
    if (size != 4) {
305
    if (size != 4 && gpmc_wordaccess_only(addr)) {
162 306
        return omap_badwidth_read32(opaque, addr);
163 307
    }
164 308

  
......
210 354
            return f->config[5];
211 355
        case 0x78:      /* GPMC_CONFIG7 */
212 356
            return f->config[6];
213
        case 0x84:      /* GPMC_NAND_DATA */
357
        case 0x84 ... 0x87: /* GPMC_NAND_DATA */
358
            if (omap_gpmc_devtype(f) == OMAP_GPMC_NAND) {
359
                return omap_nand_read(f, 0, size);
360
            }
214 361
            return 0;
215 362
        }
216 363
        break;
......
260 407
    int cs;
261 408
    struct omap_gpmc_cs_file_s *f;
262 409

  
263
    if (size != 4) {
410
    if (size != 4 && gpmc_wordaccess_only(addr)) {
264 411
        return omap_badwidth_write32(opaque, addr, value);
265 412
    }
266 413

  
......
336 483
                omap_gpmc_cs_map(s, cs);
337 484
            }
338 485
            break;
339
        case 0x7c:      /* GPMC_NAND_COMMAND */
340
        case 0x80:      /* GPMC_NAND_ADDRESS */
341
        case 0x84:      /* GPMC_NAND_DATA */
486
        case 0x7c ... 0x7f: /* GPMC_NAND_COMMAND */
487
            if (omap_gpmc_devtype(f) == OMAP_GPMC_NAND) {
488
                nand_setpins(f->dev, 1, 0, 0, 1, 0); /* CLE */
489
                omap_nand_setio(f->dev, value, omap_gpmc_devsize(f), size);
490
            }
491
            break;
492
        case 0x80 ... 0x83: /* GPMC_NAND_ADDRESS */
493
            if (omap_gpmc_devtype(f) == OMAP_GPMC_NAND) {
494
                nand_setpins(f->dev, 0, 1, 0, 1, 0); /* ALE */
495
                omap_nand_setio(f->dev, value, omap_gpmc_devsize(f), size);
496
            }
497
            break;
498
        case 0x84 ... 0x87: /* GPMC_NAND_DATA */
499
            if (omap_gpmc_devtype(f) == OMAP_GPMC_NAND) {
500
                omap_nand_write(f, 0, value, size);
501
            }
342 502
            break;
343

  
344 503
        default:
345 504
            goto bad_reg;
346 505
        }
......
403 562
struct omap_gpmc_s *omap_gpmc_init(struct omap_mpu_state_s *mpu,
404 563
                                   target_phys_addr_t base, qemu_irq irq)
405 564
{
565
    int cs;
406 566
    struct omap_gpmc_s *s = (struct omap_gpmc_s *)
407 567
            g_malloc0(sizeof(struct omap_gpmc_s));
408 568

  
......
413 573
    s->revision = cpu_class_omap3(mpu) ? 0x50 : 0x20;
414 574
    omap_gpmc_reset(s);
415 575

  
576
    /* We have to register a different IO memory handler for each
577
     * chip select region in case a NAND device is mapped there. We
578
     * make the region the worst-case size of 256MB and rely on the
579
     * container memory region in cs_map to chop it down to the actual
580
     * guest-requested size.
581
     */
582
    for (cs = 0; cs < 8; cs++) {
583
        memory_region_init_io(&s->cs_file[cs].nandiomem,
584
                              &omap_nand_ops,
585
                              &s->cs_file[cs],
586
                              "omap-nand",
587
                              256 * 1024 * 1024);
588
    }
416 589
    return s;
417 590
}
418 591

  
......
428 601
    f = &s->cs_file[cs];
429 602

  
430 603
    omap_gpmc_cs_unmap(s, cs);
604
    f->config[0] &= ~(0xf << 10);
431 605
    f->iomem = iomem;
432 606
    omap_gpmc_cs_map(s, cs);
433 607
}
608

  
609
void omap_gpmc_attach_nand(struct omap_gpmc_s *s, int cs, DeviceState *nand)
610
{
611
    struct omap_gpmc_cs_file_s *f;
612
    assert(nand);
613

  
614
    if (cs < 0 || cs >= 8) {
615
        fprintf(stderr, "%s: bad chip-select %i\n", __func__, cs);
616
        exit(-1);
617
    }
618
    f = &s->cs_file[cs];
619

  
620
    omap_gpmc_cs_unmap(s, cs);
621
    f->config[0] &= ~(0xf << 10);
622
    f->config[0] |= (OMAP_GPMC_NAND << 10);
623
    f->dev = nand;
624
    if (nand_getbuswidth(f->dev) == 16) {
625
        f->config[0] |= OMAP_GPMC_16BIT << 12;
626
    }
627
    omap_gpmc_cs_map(s, cs);
628
}

Also available in: Unified diff