symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/pxa2xx_gpio.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  * Intel XScale PXA255/270 GPIO controller emulation.
       
     3  *
       
     4  * Copyright (c) 2006 Openedhand Ltd.
       
     5  * Written by Andrzej Zaborowski <balrog@zabor.org>
       
     6  *
       
     7  * This code is licensed under the GPL.
       
     8  */
       
     9 
       
    10 #include "hw.h"
       
    11 #include "pxa.h"
       
    12 
       
    13 #define PXA2XX_GPIO_BANKS	4
       
    14 
       
    15 struct pxa2xx_gpio_info_s {
       
    16     qemu_irq *pic;
       
    17     int lines;
       
    18     CPUState *cpu_env;
       
    19     qemu_irq *in;
       
    20 
       
    21     /* XXX: GNU C vectors are more suitable */
       
    22     uint32_t ilevel[PXA2XX_GPIO_BANKS];
       
    23     uint32_t olevel[PXA2XX_GPIO_BANKS];
       
    24     uint32_t dir[PXA2XX_GPIO_BANKS];
       
    25     uint32_t rising[PXA2XX_GPIO_BANKS];
       
    26     uint32_t falling[PXA2XX_GPIO_BANKS];
       
    27     uint32_t status[PXA2XX_GPIO_BANKS];
       
    28     uint32_t gpsr[PXA2XX_GPIO_BANKS];
       
    29     uint32_t gafr[PXA2XX_GPIO_BANKS * 2];
       
    30 
       
    31     uint32_t prev_level[PXA2XX_GPIO_BANKS];
       
    32     qemu_irq handler[PXA2XX_GPIO_BANKS * 32];
       
    33     qemu_irq read_notify;
       
    34 };
       
    35 
       
    36 static struct {
       
    37     enum {
       
    38         GPIO_NONE,
       
    39         GPLR,
       
    40         GPSR,
       
    41         GPCR,
       
    42         GPDR,
       
    43         GRER,
       
    44         GFER,
       
    45         GEDR,
       
    46         GAFR_L,
       
    47         GAFR_U,
       
    48     } reg;
       
    49     int bank;
       
    50 } pxa2xx_gpio_regs[0x200] = {
       
    51     [0 ... 0x1ff] = { GPIO_NONE, 0 },
       
    52 #define PXA2XX_REG(reg, a0, a1, a2, a3)	\
       
    53     [a0] = { reg, 0 }, [a1] = { reg, 1 }, [a2] = { reg, 2 }, [a3] = { reg, 3 },
       
    54 
       
    55     PXA2XX_REG(GPLR, 0x000, 0x004, 0x008, 0x100)
       
    56     PXA2XX_REG(GPSR, 0x018, 0x01c, 0x020, 0x118)
       
    57     PXA2XX_REG(GPCR, 0x024, 0x028, 0x02c, 0x124)
       
    58     PXA2XX_REG(GPDR, 0x00c, 0x010, 0x014, 0x10c)
       
    59     PXA2XX_REG(GRER, 0x030, 0x034, 0x038, 0x130)
       
    60     PXA2XX_REG(GFER, 0x03c, 0x040, 0x044, 0x13c)
       
    61     PXA2XX_REG(GEDR, 0x048, 0x04c, 0x050, 0x148)
       
    62     PXA2XX_REG(GAFR_L, 0x054, 0x05c, 0x064, 0x06c)
       
    63     PXA2XX_REG(GAFR_U, 0x058, 0x060, 0x068, 0x070)
       
    64 };
       
    65 
       
    66 static void pxa2xx_gpio_irq_update(struct pxa2xx_gpio_info_s *s)
       
    67 {
       
    68     if (s->status[0] & (1 << 0))
       
    69         qemu_irq_raise(s->pic[PXA2XX_PIC_GPIO_0]);
       
    70     else
       
    71         qemu_irq_lower(s->pic[PXA2XX_PIC_GPIO_0]);
       
    72 
       
    73     if (s->status[0] & (1 << 1))
       
    74         qemu_irq_raise(s->pic[PXA2XX_PIC_GPIO_1]);
       
    75     else
       
    76         qemu_irq_lower(s->pic[PXA2XX_PIC_GPIO_1]);
       
    77 
       
    78     if ((s->status[0] & ~3) | s->status[1] | s->status[2] | s->status[3])
       
    79         qemu_irq_raise(s->pic[PXA2XX_PIC_GPIO_X]);
       
    80     else
       
    81         qemu_irq_lower(s->pic[PXA2XX_PIC_GPIO_X]);
       
    82 }
       
    83 
       
    84 /* Bitmap of pins used as standby and sleep wake-up sources.  */
       
    85 static const int pxa2xx_gpio_wake[PXA2XX_GPIO_BANKS] = {
       
    86     0x8003fe1b, 0x002001fc, 0xec080000, 0x0012007f,
       
    87 };
       
    88 
       
    89 static void pxa2xx_gpio_set(void *opaque, int line, int level)
       
    90 {
       
    91     struct pxa2xx_gpio_info_s *s = (struct pxa2xx_gpio_info_s *) opaque;
       
    92     int bank;
       
    93     uint32_t mask;
       
    94 
       
    95     if (line >= s->lines) {
       
    96         printf("%s: No GPIO pin %i\n", __FUNCTION__, line);
       
    97         return;
       
    98     }
       
    99 
       
   100     bank = line >> 5;
       
   101     mask = 1 << (line & 31);
       
   102 
       
   103     if (level) {
       
   104         s->status[bank] |= s->rising[bank] & mask &
       
   105                 ~s->ilevel[bank] & ~s->dir[bank];
       
   106         s->ilevel[bank] |= mask;
       
   107     } else {
       
   108         s->status[bank] |= s->falling[bank] & mask &
       
   109                 s->ilevel[bank] & ~s->dir[bank];
       
   110         s->ilevel[bank] &= ~mask;
       
   111     }
       
   112 
       
   113     if (s->status[bank] & mask)
       
   114         pxa2xx_gpio_irq_update(s);
       
   115 
       
   116     /* Wake-up GPIOs */
       
   117     if (s->cpu_env->halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank]))
       
   118         cpu_interrupt(s->cpu_env, CPU_INTERRUPT_EXITTB);
       
   119 }
       
   120 
       
   121 static void pxa2xx_gpio_handler_update(struct pxa2xx_gpio_info_s *s) {
       
   122     uint32_t level, diff;
       
   123     int i, bit, line;
       
   124     for (i = 0; i < PXA2XX_GPIO_BANKS; i ++) {
       
   125         level = s->olevel[i] & s->dir[i];
       
   126 
       
   127         for (diff = s->prev_level[i] ^ level; diff; diff ^= 1 << bit) {
       
   128             bit = ffs(diff) - 1;
       
   129             line = bit + 32 * i;
       
   130             qemu_set_irq(s->handler[line], (level >> bit) & 1);
       
   131         }
       
   132 
       
   133         s->prev_level[i] = level;
       
   134     }
       
   135 }
       
   136 
       
   137 static uint32_t pxa2xx_gpio_read(void *opaque, target_phys_addr_t offset)
       
   138 {
       
   139     struct pxa2xx_gpio_info_s *s = (struct pxa2xx_gpio_info_s *) opaque;
       
   140     uint32_t ret;
       
   141     int bank;
       
   142     if (offset >= 0x200)
       
   143         return 0;
       
   144 
       
   145     bank = pxa2xx_gpio_regs[offset].bank;
       
   146     switch (pxa2xx_gpio_regs[offset].reg) {
       
   147     case GPDR:		/* GPIO Pin-Direction registers */
       
   148         return s->dir[bank];
       
   149 
       
   150     case GPSR:		/* GPIO Pin-Output Set registers */
       
   151         printf("%s: Read from a write-only register " REG_FMT "\n",
       
   152                         __FUNCTION__, offset);
       
   153         return s->gpsr[bank];	/* Return last written value.  */
       
   154 
       
   155     case GPCR:		/* GPIO Pin-Output Clear registers */
       
   156         printf("%s: Read from a write-only register " REG_FMT "\n",
       
   157                         __FUNCTION__, offset);
       
   158         return 31337;		/* Specified as unpredictable in the docs.  */
       
   159 
       
   160     case GRER:		/* GPIO Rising-Edge Detect Enable registers */
       
   161         return s->rising[bank];
       
   162 
       
   163     case GFER:		/* GPIO Falling-Edge Detect Enable registers */
       
   164         return s->falling[bank];
       
   165 
       
   166     case GAFR_L:	/* GPIO Alternate Function registers */
       
   167         return s->gafr[bank * 2];
       
   168 
       
   169     case GAFR_U:	/* GPIO Alternate Function registers */
       
   170         return s->gafr[bank * 2 + 1];
       
   171 
       
   172     case GPLR:		/* GPIO Pin-Level registers */
       
   173         ret = (s->olevel[bank] & s->dir[bank]) |
       
   174                 (s->ilevel[bank] & ~s->dir[bank]);
       
   175         qemu_irq_raise(s->read_notify);
       
   176         return ret;
       
   177 
       
   178     case GEDR:		/* GPIO Edge Detect Status registers */
       
   179         return s->status[bank];
       
   180 
       
   181     default:
       
   182         cpu_abort(cpu_single_env,
       
   183                 "%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
       
   184     }
       
   185 
       
   186     return 0;
       
   187 }
       
   188 
       
   189 static void pxa2xx_gpio_write(void *opaque,
       
   190                 target_phys_addr_t offset, uint32_t value)
       
   191 {
       
   192     struct pxa2xx_gpio_info_s *s = (struct pxa2xx_gpio_info_s *) opaque;
       
   193     int bank;
       
   194     if (offset >= 0x200)
       
   195         return;
       
   196 
       
   197     bank = pxa2xx_gpio_regs[offset].bank;
       
   198     switch (pxa2xx_gpio_regs[offset].reg) {
       
   199     case GPDR:		/* GPIO Pin-Direction registers */
       
   200         s->dir[bank] = value;
       
   201         pxa2xx_gpio_handler_update(s);
       
   202         break;
       
   203 
       
   204     case GPSR:		/* GPIO Pin-Output Set registers */
       
   205         s->olevel[bank] |= value;
       
   206         pxa2xx_gpio_handler_update(s);
       
   207         s->gpsr[bank] = value;
       
   208         break;
       
   209 
       
   210     case GPCR:		/* GPIO Pin-Output Clear registers */
       
   211         s->olevel[bank] &= ~value;
       
   212         pxa2xx_gpio_handler_update(s);
       
   213         break;
       
   214 
       
   215     case GRER:		/* GPIO Rising-Edge Detect Enable registers */
       
   216         s->rising[bank] = value;
       
   217         break;
       
   218 
       
   219     case GFER:		/* GPIO Falling-Edge Detect Enable registers */
       
   220         s->falling[bank] = value;
       
   221         break;
       
   222 
       
   223     case GAFR_L:	/* GPIO Alternate Function registers */
       
   224         s->gafr[bank * 2] = value;
       
   225         break;
       
   226 
       
   227     case GAFR_U:	/* GPIO Alternate Function registers */
       
   228         s->gafr[bank * 2 + 1] = value;
       
   229         break;
       
   230 
       
   231     case GEDR:		/* GPIO Edge Detect Status registers */
       
   232         s->status[bank] &= ~value;
       
   233         pxa2xx_gpio_irq_update(s);
       
   234         break;
       
   235 
       
   236     default:
       
   237         cpu_abort(cpu_single_env,
       
   238                 "%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
       
   239     }
       
   240 }
       
   241 
       
   242 static CPUReadMemoryFunc *pxa2xx_gpio_readfn[] = {
       
   243     pxa2xx_gpio_read,
       
   244     pxa2xx_gpio_read,
       
   245     pxa2xx_gpio_read
       
   246 };
       
   247 
       
   248 static CPUWriteMemoryFunc *pxa2xx_gpio_writefn[] = {
       
   249     pxa2xx_gpio_write,
       
   250     pxa2xx_gpio_write,
       
   251     pxa2xx_gpio_write
       
   252 };
       
   253 
       
   254 static void pxa2xx_gpio_save(QEMUFile *f, void *opaque)
       
   255 {
       
   256     struct pxa2xx_gpio_info_s *s = (struct pxa2xx_gpio_info_s *) opaque;
       
   257     int i;
       
   258 
       
   259     qemu_put_be32(f, s->lines);
       
   260 
       
   261     for (i = 0; i < PXA2XX_GPIO_BANKS; i ++) {
       
   262         qemu_put_be32s(f, &s->ilevel[i]);
       
   263         qemu_put_be32s(f, &s->olevel[i]);
       
   264         qemu_put_be32s(f, &s->dir[i]);
       
   265         qemu_put_be32s(f, &s->rising[i]);
       
   266         qemu_put_be32s(f, &s->falling[i]);
       
   267         qemu_put_be32s(f, &s->status[i]);
       
   268         qemu_put_be32s(f, &s->gafr[i * 2 + 0]);
       
   269         qemu_put_be32s(f, &s->gafr[i * 2 + 1]);
       
   270 
       
   271         qemu_put_be32s(f, &s->prev_level[i]);
       
   272     }
       
   273 }
       
   274 
       
   275 static int pxa2xx_gpio_load(QEMUFile *f, void *opaque, int version_id)
       
   276 {
       
   277     struct pxa2xx_gpio_info_s *s = (struct pxa2xx_gpio_info_s *) opaque;
       
   278     int i;
       
   279 
       
   280     if (qemu_get_be32(f) != s->lines)
       
   281         return -EINVAL;
       
   282 
       
   283     for (i = 0; i < PXA2XX_GPIO_BANKS; i ++) {
       
   284         qemu_get_be32s(f, &s->ilevel[i]);
       
   285         qemu_get_be32s(f, &s->olevel[i]);
       
   286         qemu_get_be32s(f, &s->dir[i]);
       
   287         qemu_get_be32s(f, &s->rising[i]);
       
   288         qemu_get_be32s(f, &s->falling[i]);
       
   289         qemu_get_be32s(f, &s->status[i]);
       
   290         qemu_get_be32s(f, &s->gafr[i * 2 + 0]);
       
   291         qemu_get_be32s(f, &s->gafr[i * 2 + 1]);
       
   292 
       
   293         qemu_get_be32s(f, &s->prev_level[i]);
       
   294     }
       
   295 
       
   296     return 0;
       
   297 }
       
   298 
       
   299 struct pxa2xx_gpio_info_s *pxa2xx_gpio_init(target_phys_addr_t base,
       
   300                 CPUState *env, qemu_irq *pic, int lines)
       
   301 {
       
   302     int iomemtype;
       
   303     struct pxa2xx_gpio_info_s *s;
       
   304 
       
   305     s = (struct pxa2xx_gpio_info_s *)
       
   306             qemu_mallocz(sizeof(struct pxa2xx_gpio_info_s));
       
   307     memset(s, 0, sizeof(struct pxa2xx_gpio_info_s));
       
   308     s->pic = pic;
       
   309     s->lines = lines;
       
   310     s->cpu_env = env;
       
   311     s->in = qemu_allocate_irqs(pxa2xx_gpio_set, s, lines);
       
   312 
       
   313     iomemtype = cpu_register_io_memory(0, pxa2xx_gpio_readfn,
       
   314                     pxa2xx_gpio_writefn, s);
       
   315     cpu_register_physical_memory(base, 0x00001000, iomemtype);
       
   316 
       
   317     register_savevm("pxa2xx_gpio", 0, 0,
       
   318                     pxa2xx_gpio_save, pxa2xx_gpio_load, s);
       
   319 
       
   320     return s;
       
   321 }
       
   322 
       
   323 qemu_irq *pxa2xx_gpio_in_get(struct pxa2xx_gpio_info_s *s)
       
   324 {
       
   325     return s->in;
       
   326 }
       
   327 
       
   328 void pxa2xx_gpio_out_set(struct pxa2xx_gpio_info_s *s,
       
   329                 int line, qemu_irq handler)
       
   330 {
       
   331     if (line >= s->lines) {
       
   332         printf("%s: No GPIO pin %i\n", __FUNCTION__, line);
       
   333         return;
       
   334     }
       
   335 
       
   336     s->handler[line] = handler;
       
   337 }
       
   338 
       
   339 /*
       
   340  * Registers a callback to notify on GPLR reads.  This normally
       
   341  * shouldn't be needed but it is used for the hack on Spitz machines.
       
   342  */
       
   343 void pxa2xx_gpio_read_notifier(struct pxa2xx_gpio_info_s *s, qemu_irq handler)
       
   344 {
       
   345     s->read_notify = handler;
       
   346 }