Revision fe71e81a hw/omap.c

b/hw/omap.c
2787 2787
    cpu_register_physical_memory(s->clkm.dsp_base, 0x1000, iomemtype[1]);
2788 2788
}
2789 2789

  
2790
/* MPU I/O */
2791
struct omap_mpuio_s {
2792
    target_phys_addr_t base;
2793
    qemu_irq irq;
2794
    qemu_irq kbd_irq;
2795
    qemu_irq *in;
2796
    qemu_irq handler[16];
2797
    qemu_irq wakeup;
2798

  
2799
    uint16_t inputs;
2800
    uint16_t outputs;
2801
    uint16_t dir;
2802
    uint16_t edge;
2803
    uint16_t mask;
2804
    uint16_t ints;
2805

  
2806
    uint16_t debounce;
2807
    uint16_t latch;
2808
    uint8_t event;
2809

  
2810
    uint8_t buttons[5];
2811
    uint8_t row_latch;
2812
    uint8_t cols;
2813
    int kbd_mask;
2814
    int clk;
2815
};
2816

  
2817
static void omap_mpuio_set(void *opaque, int line, int level)
2818
{
2819
    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
2820
    uint16_t prev = s->inputs;
2821

  
2822
    if (level)
2823
        s->inputs |= 1 << line;
2824
    else
2825
        s->inputs &= ~(1 << line);
2826

  
2827
    if (((1 << line) & s->dir & ~s->mask) && s->clk) {
2828
        if ((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) {
2829
            s->ints |= 1 << line;
2830
            qemu_irq_raise(s->irq);
2831
            /* TODO: wakeup */
2832
        }
2833
        if ((s->event & (1 << 0)) &&		/* SET_GPIO_EVENT_MODE */
2834
                (s->event >> 1) == line)	/* PIN_SELECT */
2835
            s->latch = s->inputs;
2836
    }
2837
}
2838

  
2839
static void omap_mpuio_kbd_update(struct omap_mpuio_s *s)
2840
{
2841
    int i;
2842
    uint8_t *row, rows = 0, cols = ~s->cols;
2843

  
2844
    for (row = s->buttons + 4, i = 1 << 5; i; row --, i >>= 1)
2845
        if (*row & cols)
2846
            s->row_latch |= i;
2847

  
2848
    if (rows && ~s->kbd_mask && s->clk)
2849
        qemu_irq_raise(s->kbd_irq);
2850
    s->row_latch = rows ^ 0x1f;
2851
}
2852

  
2853
static uint32_t omap_mpuio_read(void *opaque, target_phys_addr_t addr)
2854
{
2855
    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
2856
    int offset = addr - s->base;
2857
    uint16_t ret;
2858

  
2859
    switch (offset) {
2860
    case 0x00:	/* INPUT_LATCH */
2861
        return s->inputs;
2862

  
2863
    case 0x04:	/* OUTPUT_REG */
2864
        return s->outputs;
2865

  
2866
    case 0x08:	/* IO_CNTL */
2867
        return s->dir;
2868

  
2869
    case 0x10:	/* KBR_LATCH */
2870
        return s->row_latch;
2871

  
2872
    case 0x14:	/* KBC_REG */
2873
        return s->cols;
2874

  
2875
    case 0x18:	/* GPIO_EVENT_MODE_REG */
2876
        return s->event;
2877

  
2878
    case 0x1c:	/* GPIO_INT_EDGE_REG */
2879
        return s->edge;
2880

  
2881
    case 0x20:	/* KBD_INT */
2882
        return (s->row_latch != 0x1f) && !s->kbd_mask;
2883

  
2884
    case 0x24:	/* GPIO_INT */
2885
        ret = s->ints;
2886
        s->ints &= ~s->mask;
2887
        return ret;
2888

  
2889
    case 0x28:	/* KBD_MASKIT */
2890
        return s->kbd_mask;
2891

  
2892
    case 0x2c:	/* GPIO_MASKIT */
2893
        return s->mask;
2894

  
2895
    case 0x30:	/* GPIO_DEBOUNCING_REG */
2896
        return s->debounce;
2897

  
2898
    case 0x34:	/* GPIO_LATCH_REG */
2899
        return s->latch;
2900
    }
2901

  
2902
    OMAP_BAD_REG(addr);
2903
    return 0;
2904
}
2905

  
2906
static void omap_mpuio_write(void *opaque, target_phys_addr_t addr,
2907
                uint32_t value)
2908
{
2909
    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
2910
    int offset = addr - s->base;
2911
    uint16_t diff;
2912
    int ln;
2913

  
2914
    switch (offset) {
2915
    case 0x04:	/* OUTPUT_REG */
2916
        diff = s->outputs ^ (value & ~s->dir);
2917
        s->outputs = value;
2918
	value &= ~s->dir;
2919
        while ((ln = ffs(diff))) {
2920
            ln --;
2921
            if (s->handler[ln])
2922
                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
2923
            diff &= ~(1 << ln);
2924
        }
2925
        break;
2926

  
2927
    case 0x08:	/* IO_CNTL */
2928
        diff = s->outputs & (s->dir ^ value);
2929
        s->dir = value;
2930

  
2931
        value = s->outputs & ~s->dir;
2932
        while ((ln = ffs(diff))) {
2933
            ln --;
2934
            if (s->handler[ln])
2935
                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
2936
            diff &= ~(1 << ln);
2937
        }
2938
        break;
2939

  
2940
    case 0x14:	/* KBC_REG */
2941
        s->cols = value;
2942
        omap_mpuio_kbd_update(s);
2943
        break;
2944

  
2945
    case 0x18:	/* GPIO_EVENT_MODE_REG */
2946
        s->event = value & 0x1f;
2947
        break;
2948

  
2949
    case 0x1c:	/* GPIO_INT_EDGE_REG */
2950
        s->edge = value;
2951
        break;
2952

  
2953
    case 0x28:	/* KBD_MASKIT */
2954
        s->kbd_mask = value & 1;
2955
        omap_mpuio_kbd_update(s);
2956
        break;
2957

  
2958
    case 0x2c:	/* GPIO_MASKIT */
2959
        s->mask = value;
2960
        break;
2961

  
2962
    case 0x30:	/* GPIO_DEBOUNCING_REG */
2963
        s->debounce = value & 0x1ff;
2964
        break;
2965

  
2966
    case 0x00:	/* INPUT_LATCH */
2967
    case 0x10:	/* KBR_LATCH */
2968
    case 0x20:	/* KBD_INT */
2969
    case 0x24:	/* GPIO_INT */
2970
    case 0x34:	/* GPIO_LATCH_REG */
2971
        OMAP_RO_REG(addr);
2972
        return;
2973

  
2974
    default:
2975
        OMAP_BAD_REG(addr);
2976
        return;
2977
    }
2978
}
2979

  
2980
static CPUReadMemoryFunc *omap_mpuio_readfn[] = {
2981
    omap_badwidth_read16,
2982
    omap_mpuio_read,
2983
    omap_badwidth_read16,
2984
};
2985

  
2986
static CPUWriteMemoryFunc *omap_mpuio_writefn[] = {
2987
    omap_badwidth_write16,
2988
    omap_mpuio_write,
2989
    omap_badwidth_write16,
2990
};
2991

  
2992
void omap_mpuio_reset(struct omap_mpuio_s *s)
2993
{
2994
    s->inputs = 0;
2995
    s->outputs = 0;
2996
    s->dir = ~0;
2997
    s->event = 0;
2998
    s->edge = 0;
2999
    s->kbd_mask = 0;
3000
    s->mask = 0;
3001
    s->debounce = 0;
3002
    s->latch = 0;
3003
    s->ints = 0;
3004
    s->row_latch = 0x1f;
3005
}
3006

  
3007
static void omap_mpuio_onoff(void *opaque, int line, int on)
3008
{
3009
    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
3010

  
3011
    s->clk = on;
3012
    if (on)
3013
        omap_mpuio_kbd_update(s);
3014
}
3015

  
3016
struct omap_mpuio_s *omap_mpuio_init(target_phys_addr_t base,
3017
                qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup,
3018
                omap_clk clk)
3019
{
3020
    int iomemtype;
3021
    struct omap_mpuio_s *s = (struct omap_mpuio_s *)
3022
            qemu_mallocz(sizeof(struct omap_mpuio_s));
3023

  
3024
    s->base = base;
3025
    s->irq = gpio_int;
3026
    s->kbd_irq = kbd_int;
3027
    s->wakeup = wakeup;
3028
    s->in = qemu_allocate_irqs(omap_mpuio_set, s, 16);
3029
    omap_mpuio_reset(s);
3030

  
3031
    iomemtype = cpu_register_io_memory(0, omap_mpuio_readfn,
3032
                    omap_mpuio_writefn, s);
3033
    cpu_register_physical_memory(s->base, 0x800, iomemtype);
3034

  
3035
    omap_clk_adduser(clk, qemu_allocate_irqs(omap_mpuio_onoff, s, 1)[0]);
3036

  
3037
    return s;
3038
}
3039

  
3040
qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s)
3041
{
3042
    return s->in;
3043
}
3044

  
3045
void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler)
3046
{
3047
    if (line >= 16 || line < 0)
3048
        cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", __FUNCTION__, line);
3049
    s->handler[line] = handler;
3050
}
3051

  
3052
void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down)
3053
{
3054
    if (row >= 5 || row < 0)
3055
        cpu_abort(cpu_single_env, "%s: No key %i-%i\n",
3056
                        __FUNCTION__, col, row);
3057

  
3058
    if (down)
3059
        s->buttons[row] = 1 << col;
3060
    else
3061
        s->buttons[row] = ~(1 << col);
3062

  
3063
    omap_mpuio_kbd_update(s);
3064
}
3065

  
2790 3066
/* General chip reset */
2791 3067
static void omap_mpu_reset(void *opaque)
2792 3068
{
......
2814 3090
    omap_uart_reset(mpu->uart2);
2815 3091
    omap_uart_reset(mpu->uart3);
2816 3092
    omap_mmc_reset(mpu->mmc);
3093
    omap_mpuio_reset(mpu->mpuio);
2817 3094
    cpu_reset(mpu->env);
2818 3095
}
2819 3096

  
......
2821 3098
{
2822 3099
    struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
2823 3100

  
2824
    cpu_interrupt(mpu->env, CPU_INTERRUPT_EXITTB);
3101
    if (mpu->env->halted)
3102
        cpu_interrupt(mpu->env, CPU_INTERRUPT_EXITTB);
2825 3103
}
2826 3104

  
2827 3105
struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
......
2839 3117

  
2840 3118
    cpu_arm_set_model(s->env, core ?: "ti925t");
2841 3119

  
3120
    s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
3121

  
2842 3122
    /* Clocks */
2843 3123
    omap_clk_init(s);
2844 3124

  
......
2922 3202
    s->mmc = omap_mmc_init(0xfffb7800, s->irq[1][OMAP_INT_OQN],
2923 3203
                    &s->drq[OMAP_DMA_MMC_TX], omap_findclk(s, "mmc_ck"));
2924 3204

  
3205
    s->mpuio = omap_mpuio_init(0xfffb5000,
3206
                    s->irq[1][OMAP_INT_KEYBOARD], s->irq[1][OMAP_INT_MPUIO],
3207
                    s->wakeup, omap_findclk(s, "clk32-kHz"));
3208

  
2925 3209
    qemu_register_reset(omap_mpu_reset, s);
2926
    s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
2927 3210

  
2928 3211
    return s;
2929 3212
}

Also available in: Unified diff