Revision 64330148

b/hw/omap.c
3065 3065
    omap_mpuio_kbd_update(s);
3066 3066
}
3067 3067

  
3068
/* General-Purpose I/O */
3069
struct omap_gpio_s {
3070
    target_phys_addr_t base;
3071
    qemu_irq irq;
3072
    qemu_irq *in;
3073
    qemu_irq handler[16];
3074

  
3075
    uint16_t inputs;
3076
    uint16_t outputs;
3077
    uint16_t dir;
3078
    uint16_t edge;
3079
    uint16_t mask;
3080
    uint16_t ints;
3081
};
3082

  
3083
static void omap_gpio_set(void *opaque, int line, int level)
3084
{
3085
    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
3086
    uint16_t prev = s->inputs;
3087

  
3088
    if (level)
3089
        s->inputs |= 1 << line;
3090
    else
3091
        s->inputs &= ~(1 << line);
3092

  
3093
    if (((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) &
3094
                    (1 << line) & s->dir & ~s->mask) {
3095
        s->ints |= 1 << line;
3096
        qemu_irq_raise(s->irq);
3097
    }
3098
}
3099

  
3100
static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
3101
{
3102
    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
3103
    int offset = addr - s->base;
3104
    uint16_t ret;
3105

  
3106
    switch (offset) {
3107
    case 0x00:	/* DATA_INPUT */
3108
        return s->inputs;
3109

  
3110
    case 0x04:	/* DATA_OUTPUT */
3111
        return s->outputs;
3112

  
3113
    case 0x08:	/* DIRECTION_CONTROL */
3114
        return s->dir;
3115

  
3116
    case 0x0c:	/* INTERRUPT_CONTROL */
3117
        return s->edge;
3118

  
3119
    case 0x10:	/* INTERRUPT_MASK */
3120
        return s->mask;
3121

  
3122
    case 0x14:	/* INTERRUPT_STATUS */
3123
        return s->ints;
3124
    }
3125

  
3126
    OMAP_BAD_REG(addr);
3127
    return 0;
3128
}
3129

  
3130
static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
3131
                uint32_t value)
3132
{
3133
    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
3134
    int offset = addr - s->base;
3135
    uint16_t diff;
3136
    int ln;
3137

  
3138
    switch (offset) {
3139
    case 0x00:	/* DATA_INPUT */
3140
        OMAP_RO_REG(addr);
3141
        return;
3142

  
3143
    case 0x04:	/* DATA_OUTPUT */
3144
        diff = s->outputs ^ (value & ~s->dir);
3145
        s->outputs = value;
3146
	value &= ~s->dir;
3147
        while ((ln = ffs(diff))) {
3148
            ln --;
3149
            if (s->handler[ln])
3150
                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
3151
            diff &= ~(1 << ln);
3152
        }
3153
        break;
3154

  
3155
    case 0x08:	/* DIRECTION_CONTROL */
3156
        diff = s->outputs & (s->dir ^ value);
3157
        s->dir = value;
3158

  
3159
        value = s->outputs & ~s->dir;
3160
        while ((ln = ffs(diff))) {
3161
            ln --;
3162
            if (s->handler[ln])
3163
                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
3164
            diff &= ~(1 << ln);
3165
        }
3166
        break;
3167

  
3168
    case 0x0c:	/* INTERRUPT_CONTROL */
3169
        s->edge = value;
3170
        break;
3171

  
3172
    case 0x10:	/* INTERRUPT_MASK */
3173
        s->mask = value;
3174
        break;
3175

  
3176
    case 0x14:	/* INTERRUPT_STATUS */
3177
        s->ints &= ~value;
3178
        if (!s->ints)
3179
            qemu_irq_lower(s->irq);
3180
        break;
3181

  
3182
    default:
3183
        OMAP_BAD_REG(addr);
3184
        return;
3185
    }
3186
}
3187

  
3188
static CPUReadMemoryFunc *omap_gpio_readfn[] = {
3189
    omap_gpio_read,
3190
    omap_badwidth_read32,
3191
    omap_badwidth_read32,
3192
};
3193

  
3194
static CPUWriteMemoryFunc *omap_gpio_writefn[] = {
3195
    omap_gpio_write,
3196
    omap_badwidth_write32,
3197
    omap_badwidth_write32,
3198
};
3199

  
3200
void omap_gpio_reset(struct omap_gpio_s *s)
3201
{
3202
    s->inputs = 0;
3203
    s->outputs = ~0;
3204
    s->dir = ~0;
3205
    s->edge = ~0;
3206
    s->mask = ~0;
3207
    s->ints = 0;
3208
}
3209

  
3210
struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
3211
                qemu_irq irq, omap_clk clk)
3212
{
3213
    int iomemtype;
3214
    struct omap_gpio_s *s = (struct omap_gpio_s *)
3215
            qemu_mallocz(sizeof(struct omap_gpio_s));
3216

  
3217
    s->base = base;
3218
    s->irq = irq;
3219
    s->in = qemu_allocate_irqs(omap_gpio_set, s, 16);
3220
    omap_gpio_reset(s);
3221

  
3222
    iomemtype = cpu_register_io_memory(0, omap_gpio_readfn,
3223
                    omap_gpio_writefn, s);
3224
    cpu_register_physical_memory(s->base, 0x1000, iomemtype);
3225

  
3226
    return s;
3227
}
3228

  
3229
qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
3230
{
3231
    return s->in;
3232
}
3233

  
3234
void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
3235
{
3236
    if (line >= 16 || line < 0)
3237
        cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", __FUNCTION__, line);
3238
    s->handler[line] = handler;
3239
}
3240

  
3068 3241
/* General chip reset */
3069 3242
static void omap_mpu_reset(void *opaque)
3070 3243
{
......
3093 3266
    omap_uart_reset(mpu->uart3);
3094 3267
    omap_mmc_reset(mpu->mmc);
3095 3268
    omap_mpuio_reset(mpu->mpuio);
3269
    omap_gpio_reset(mpu->gpio);
3096 3270
    cpu_reset(mpu->env);
3097 3271
}
3098 3272

  
......
3208 3382
                    s->irq[1][OMAP_INT_KEYBOARD], s->irq[1][OMAP_INT_MPUIO],
3209 3383
                    s->wakeup, omap_findclk(s, "clk32-kHz"));
3210 3384

  
3385
    s->gpio = omap_gpio_init(0xfffcf000, s->irq[1][OMAP_INT_KEYBOARD],
3386
                    omap_findclk(s, "mpuper_ck"));
3387

  
3211 3388
    qemu_register_reset(omap_mpu_reset, s);
3212 3389

  
3213 3390
    return s;
b/hw/omap.h
458 458
void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler);
459 459
void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down);
460 460

  
461
struct omap_gpio_s;
462
struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
463
                qemu_irq irq, omap_clk clk);
464
qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s);
465
void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler);
466

  
461 467
/* omap_lcdc.c */
462 468
struct omap_lcd_panel_s;
463 469
void omap_lcdc_reset(struct omap_lcd_panel_s *s);
......
574 580
    } clkm;
575 581

  
576 582
    struct omap_mpuio_s *mpuio;
583
    struct omap_gpio_s *gpio;
577 584
} *omap310_mpu_init(unsigned long sdram_size,
578 585
                DisplayState *ds, const char *core);
579 586

  
b/hw/palm.c
158 158

  
159 159
    qemu_add_kbd_event_handler(palmte_button_event, cpu);
160 160

  
161
    omap_mmc_handlers(cpu->mmc, 0,
161
    omap_mmc_handlers(cpu->mmc,
162
                    omap_gpio_in_get(cpu->gpio)[PALMTE_MMC_WP_GPIO],
162 163
                    qemu_allocate_irqs(palmte_mmc_cover, cpu, 1)[0]);
163 164

  
164 165
    /* Setup initial (reset) machine state */

Also available in: Unified diff