pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Arm PrimeCell PL061 General Purpose IO with additional |
| 3 | * Luminary Micro Stellaris bits. |
| 4 | * |
| 5 | * Copyright (c) 2007 CodeSourcery. |
| 6 | * Written by Paul Brook |
| 7 | * |
Matthew Fernandez | 8e31bf3 | 2011-06-26 12:21:35 +1000 | [diff] [blame] | 8 | * This code is licensed under the GPL. |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 9 | */ |
| 10 | |
Paolo Bonzini | 83c9f4c | 2013-02-04 15:40:22 +0100 | [diff] [blame] | 11 | #include "hw/sysbus.h" |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 12 | |
| 13 | //#define DEBUG_PL061 1 |
| 14 | |
| 15 | #ifdef DEBUG_PL061 |
Blue Swirl | 001faf3 | 2009-05-13 17:53:17 +0000 | [diff] [blame] | 16 | #define DPRINTF(fmt, ...) \ |
| 17 | do { printf("pl061: " fmt , ## __VA_ARGS__); } while (0) |
| 18 | #define BADF(fmt, ...) \ |
| 19 | do { fprintf(stderr, "pl061: error: " fmt , ## __VA_ARGS__); exit(1);} while (0) |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 20 | #else |
Blue Swirl | 001faf3 | 2009-05-13 17:53:17 +0000 | [diff] [blame] | 21 | #define DPRINTF(fmt, ...) do {} while(0) |
| 22 | #define BADF(fmt, ...) \ |
| 23 | do { fprintf(stderr, "pl061: error: " fmt , ## __VA_ARGS__);} while (0) |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 24 | #endif |
| 25 | |
| 26 | static const uint8_t pl061_id[12] = |
Peter Maydell | 7063f49 | 2011-02-21 20:57:51 +0000 | [diff] [blame] | 27 | { 0x00, 0x00, 0x00, 0x00, 0x61, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 }; |
| 28 | static const uint8_t pl061_id_luminary[12] = |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 29 | { 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 }; |
| 30 | |
Andreas Färber | 692a76d | 2013-07-26 17:31:46 +0200 | [diff] [blame] | 31 | #define TYPE_PL061 "pl061" |
| 32 | #define PL061(obj) OBJECT_CHECK(PL061State, (obj), TYPE_PL061) |
| 33 | |
Andreas Färber | ee663e9 | 2013-07-26 17:21:21 +0200 | [diff] [blame] | 34 | typedef struct PL061State { |
Andreas Färber | 692a76d | 2013-07-26 17:31:46 +0200 | [diff] [blame] | 35 | SysBusDevice parent_obj; |
| 36 | |
Avi Kivity | 3cf89f8 | 2011-10-10 17:18:44 +0200 | [diff] [blame] | 37 | MemoryRegion iomem; |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 38 | uint32_t locked; |
| 39 | uint32_t data; |
Colin Leitner | bfb27e6 | 2014-09-12 14:06:48 +0100 | [diff] [blame] | 40 | uint32_t old_out_data; |
| 41 | uint32_t old_in_data; |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 42 | uint32_t dir; |
| 43 | uint32_t isense; |
| 44 | uint32_t ibe; |
| 45 | uint32_t iev; |
| 46 | uint32_t im; |
| 47 | uint32_t istate; |
| 48 | uint32_t afsel; |
| 49 | uint32_t dr2r; |
| 50 | uint32_t dr4r; |
| 51 | uint32_t dr8r; |
| 52 | uint32_t odr; |
| 53 | uint32_t pur; |
| 54 | uint32_t pdr; |
| 55 | uint32_t slr; |
| 56 | uint32_t den; |
| 57 | uint32_t cr; |
| 58 | uint32_t float_high; |
Peter Maydell | b3aaff1 | 2011-08-03 23:04:49 +0100 | [diff] [blame] | 59 | uint32_t amsel; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 60 | qemu_irq irq; |
| 61 | qemu_irq out[8]; |
Peter Maydell | 7063f49 | 2011-02-21 20:57:51 +0000 | [diff] [blame] | 62 | const unsigned char *id; |
Andreas Färber | ee663e9 | 2013-07-26 17:21:21 +0200 | [diff] [blame] | 63 | } PL061State; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 64 | |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 65 | static const VMStateDescription vmstate_pl061 = { |
| 66 | .name = "pl061", |
Colin Leitner | bfb27e6 | 2014-09-12 14:06:48 +0100 | [diff] [blame] | 67 | .version_id = 3, |
| 68 | .minimum_version_id = 3, |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 69 | .fields = (VMStateField[]) { |
Andreas Färber | ee663e9 | 2013-07-26 17:21:21 +0200 | [diff] [blame] | 70 | VMSTATE_UINT32(locked, PL061State), |
| 71 | VMSTATE_UINT32(data, PL061State), |
Colin Leitner | bfb27e6 | 2014-09-12 14:06:48 +0100 | [diff] [blame] | 72 | VMSTATE_UINT32(old_out_data, PL061State), |
| 73 | VMSTATE_UINT32(old_in_data, PL061State), |
Andreas Färber | ee663e9 | 2013-07-26 17:21:21 +0200 | [diff] [blame] | 74 | VMSTATE_UINT32(dir, PL061State), |
| 75 | VMSTATE_UINT32(isense, PL061State), |
| 76 | VMSTATE_UINT32(ibe, PL061State), |
| 77 | VMSTATE_UINT32(iev, PL061State), |
| 78 | VMSTATE_UINT32(im, PL061State), |
| 79 | VMSTATE_UINT32(istate, PL061State), |
| 80 | VMSTATE_UINT32(afsel, PL061State), |
| 81 | VMSTATE_UINT32(dr2r, PL061State), |
| 82 | VMSTATE_UINT32(dr4r, PL061State), |
| 83 | VMSTATE_UINT32(dr8r, PL061State), |
| 84 | VMSTATE_UINT32(odr, PL061State), |
| 85 | VMSTATE_UINT32(pur, PL061State), |
| 86 | VMSTATE_UINT32(pdr, PL061State), |
| 87 | VMSTATE_UINT32(slr, PL061State), |
| 88 | VMSTATE_UINT32(den, PL061State), |
| 89 | VMSTATE_UINT32(cr, PL061State), |
| 90 | VMSTATE_UINT32(float_high, PL061State), |
| 91 | VMSTATE_UINT32_V(amsel, PL061State, 2), |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 92 | VMSTATE_END_OF_LIST() |
| 93 | } |
| 94 | }; |
| 95 | |
Andreas Färber | ee663e9 | 2013-07-26 17:21:21 +0200 | [diff] [blame] | 96 | static void pl061_update(PL061State *s) |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 97 | { |
| 98 | uint8_t changed; |
| 99 | uint8_t mask; |
pbrook | 775616c | 2007-11-24 23:35:08 +0000 | [diff] [blame] | 100 | uint8_t out; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 101 | int i; |
| 102 | |
Colin Leitner | bfb27e6 | 2014-09-12 14:06:48 +0100 | [diff] [blame] | 103 | DPRINTF("dir = %d, data = %d\n", s->dir, s->data); |
| 104 | |
pbrook | 775616c | 2007-11-24 23:35:08 +0000 | [diff] [blame] | 105 | /* Outputs float high. */ |
| 106 | /* FIXME: This is board dependent. */ |
| 107 | out = (s->data & s->dir) | ~s->dir; |
Colin Leitner | bfb27e6 | 2014-09-12 14:06:48 +0100 | [diff] [blame] | 108 | changed = s->old_out_data ^ out; |
| 109 | if (changed) { |
| 110 | s->old_out_data = out; |
| 111 | for (i = 0; i < 8; i++) { |
| 112 | mask = 1 << i; |
| 113 | if (changed & mask) { |
| 114 | DPRINTF("Set output %d = %d\n", i, (out & mask) != 0); |
| 115 | qemu_set_irq(s->out[i], (out & mask) != 0); |
| 116 | } |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 117 | } |
| 118 | } |
| 119 | |
Colin Leitner | bfb27e6 | 2014-09-12 14:06:48 +0100 | [diff] [blame] | 120 | /* Inputs */ |
| 121 | changed = (s->old_in_data ^ s->data) & ~s->dir; |
| 122 | if (changed) { |
| 123 | s->old_in_data = s->data; |
| 124 | for (i = 0; i < 8; i++) { |
| 125 | mask = 1 << i; |
| 126 | if (changed & mask) { |
| 127 | DPRINTF("Changed input %d = %d\n", i, (s->data & mask) != 0); |
| 128 | |
| 129 | if (!(s->isense & mask)) { |
| 130 | /* Edge interrupt */ |
| 131 | if (s->ibe & mask) { |
| 132 | /* Any edge triggers the interrupt */ |
| 133 | s->istate |= mask; |
| 134 | } else { |
| 135 | /* Edge is selected by IEV */ |
| 136 | s->istate |= ~(s->data ^ s->iev) & mask; |
| 137 | } |
| 138 | } |
| 139 | } |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | /* Level interrupt */ |
| 144 | s->istate |= ~(s->data ^ s->iev) & s->isense; |
| 145 | |
| 146 | DPRINTF("istate = %02X\n", s->istate); |
| 147 | |
| 148 | qemu_set_irq(s->irq, (s->istate & s->im) != 0); |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 149 | } |
| 150 | |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 151 | static uint64_t pl061_read(void *opaque, hwaddr offset, |
Avi Kivity | 3cf89f8 | 2011-10-10 17:18:44 +0200 | [diff] [blame] | 152 | unsigned size) |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 153 | { |
Andreas Färber | ee663e9 | 2013-07-26 17:21:21 +0200 | [diff] [blame] | 154 | PL061State *s = (PL061State *)opaque; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 155 | |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 156 | if (offset >= 0xfd0 && offset < 0x1000) { |
Peter Maydell | 7063f49 | 2011-02-21 20:57:51 +0000 | [diff] [blame] | 157 | return s->id[(offset - 0xfd0) >> 2]; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 158 | } |
| 159 | if (offset < 0x400) { |
| 160 | return s->data & (offset >> 2); |
| 161 | } |
| 162 | switch (offset) { |
| 163 | case 0x400: /* Direction */ |
| 164 | return s->dir; |
| 165 | case 0x404: /* Interrupt sense */ |
| 166 | return s->isense; |
| 167 | case 0x408: /* Interrupt both edges */ |
| 168 | return s->ibe; |
Stefan Weil | ff2712b | 2011-04-28 17:20:35 +0200 | [diff] [blame] | 169 | case 0x40c: /* Interrupt event */ |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 170 | return s->iev; |
| 171 | case 0x410: /* Interrupt mask */ |
| 172 | return s->im; |
| 173 | case 0x414: /* Raw interrupt status */ |
| 174 | return s->istate; |
| 175 | case 0x418: /* Masked interrupt status */ |
| 176 | return s->istate | s->im; |
| 177 | case 0x420: /* Alternate function select */ |
| 178 | return s->afsel; |
| 179 | case 0x500: /* 2mA drive */ |
| 180 | return s->dr2r; |
| 181 | case 0x504: /* 4mA drive */ |
| 182 | return s->dr4r; |
| 183 | case 0x508: /* 8mA drive */ |
| 184 | return s->dr8r; |
| 185 | case 0x50c: /* Open drain */ |
| 186 | return s->odr; |
| 187 | case 0x510: /* Pull-up */ |
| 188 | return s->pur; |
| 189 | case 0x514: /* Pull-down */ |
| 190 | return s->pdr; |
| 191 | case 0x518: /* Slew rate control */ |
| 192 | return s->slr; |
| 193 | case 0x51c: /* Digital enable */ |
| 194 | return s->den; |
| 195 | case 0x520: /* Lock */ |
| 196 | return s->locked; |
| 197 | case 0x524: /* Commit */ |
| 198 | return s->cr; |
Peter Maydell | b3aaff1 | 2011-08-03 23:04:49 +0100 | [diff] [blame] | 199 | case 0x528: /* Analog mode select */ |
| 200 | return s->amsel; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 201 | default: |
Peter Maydell | abff909 | 2012-10-30 07:45:09 +0000 | [diff] [blame] | 202 | qemu_log_mask(LOG_GUEST_ERROR, |
| 203 | "pl061_read: Bad offset %x\n", (int)offset); |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 204 | return 0; |
| 205 | } |
| 206 | } |
| 207 | |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 208 | static void pl061_write(void *opaque, hwaddr offset, |
Avi Kivity | 3cf89f8 | 2011-10-10 17:18:44 +0200 | [diff] [blame] | 209 | uint64_t value, unsigned size) |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 210 | { |
Andreas Färber | ee663e9 | 2013-07-26 17:21:21 +0200 | [diff] [blame] | 211 | PL061State *s = (PL061State *)opaque; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 212 | uint8_t mask; |
| 213 | |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 214 | if (offset < 0x400) { |
| 215 | mask = (offset >> 2) & s->dir; |
| 216 | s->data = (s->data & ~mask) | (value & mask); |
| 217 | pl061_update(s); |
| 218 | return; |
| 219 | } |
| 220 | switch (offset) { |
| 221 | case 0x400: /* Direction */ |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 222 | s->dir = value & 0xff; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 223 | break; |
| 224 | case 0x404: /* Interrupt sense */ |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 225 | s->isense = value & 0xff; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 226 | break; |
| 227 | case 0x408: /* Interrupt both edges */ |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 228 | s->ibe = value & 0xff; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 229 | break; |
Stefan Weil | ff2712b | 2011-04-28 17:20:35 +0200 | [diff] [blame] | 230 | case 0x40c: /* Interrupt event */ |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 231 | s->iev = value & 0xff; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 232 | break; |
| 233 | case 0x410: /* Interrupt mask */ |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 234 | s->im = value & 0xff; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 235 | break; |
| 236 | case 0x41c: /* Interrupt clear */ |
| 237 | s->istate &= ~value; |
| 238 | break; |
| 239 | case 0x420: /* Alternate function select */ |
| 240 | mask = s->cr; |
| 241 | s->afsel = (s->afsel & ~mask) | (value & mask); |
| 242 | break; |
| 243 | case 0x500: /* 2mA drive */ |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 244 | s->dr2r = value & 0xff; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 245 | break; |
| 246 | case 0x504: /* 4mA drive */ |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 247 | s->dr4r = value & 0xff; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 248 | break; |
| 249 | case 0x508: /* 8mA drive */ |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 250 | s->dr8r = value & 0xff; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 251 | break; |
| 252 | case 0x50c: /* Open drain */ |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 253 | s->odr = value & 0xff; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 254 | break; |
| 255 | case 0x510: /* Pull-up */ |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 256 | s->pur = value & 0xff; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 257 | break; |
| 258 | case 0x514: /* Pull-down */ |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 259 | s->pdr = value & 0xff; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 260 | break; |
| 261 | case 0x518: /* Slew rate control */ |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 262 | s->slr = value & 0xff; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 263 | break; |
| 264 | case 0x51c: /* Digital enable */ |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 265 | s->den = value & 0xff; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 266 | break; |
| 267 | case 0x520: /* Lock */ |
| 268 | s->locked = (value != 0xacce551); |
| 269 | break; |
| 270 | case 0x524: /* Commit */ |
| 271 | if (!s->locked) |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 272 | s->cr = value & 0xff; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 273 | break; |
Peter Maydell | b3aaff1 | 2011-08-03 23:04:49 +0100 | [diff] [blame] | 274 | case 0x528: |
| 275 | s->amsel = value & 0xff; |
| 276 | break; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 277 | default: |
Peter Maydell | abff909 | 2012-10-30 07:45:09 +0000 | [diff] [blame] | 278 | qemu_log_mask(LOG_GUEST_ERROR, |
| 279 | "pl061_write: Bad offset %x\n", (int)offset); |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 280 | } |
| 281 | pl061_update(s); |
| 282 | } |
| 283 | |
Andreas Färber | ee663e9 | 2013-07-26 17:21:21 +0200 | [diff] [blame] | 284 | static void pl061_reset(PL061State *s) |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 285 | { |
| 286 | s->locked = 1; |
| 287 | s->cr = 0xff; |
| 288 | } |
| 289 | |
pbrook | 9596ebb | 2007-11-18 01:44:38 +0000 | [diff] [blame] | 290 | static void pl061_set_irq(void * opaque, int irq, int level) |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 291 | { |
Andreas Färber | ee663e9 | 2013-07-26 17:21:21 +0200 | [diff] [blame] | 292 | PL061State *s = (PL061State *)opaque; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 293 | uint8_t mask; |
| 294 | |
| 295 | mask = 1 << irq; |
| 296 | if ((s->dir & mask) == 0) { |
| 297 | s->data &= ~mask; |
| 298 | if (level) |
| 299 | s->data |= mask; |
| 300 | pl061_update(s); |
| 301 | } |
| 302 | } |
| 303 | |
Avi Kivity | 3cf89f8 | 2011-10-10 17:18:44 +0200 | [diff] [blame] | 304 | static const MemoryRegionOps pl061_ops = { |
| 305 | .read = pl061_read, |
| 306 | .write = pl061_write, |
| 307 | .endianness = DEVICE_NATIVE_ENDIAN, |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 308 | }; |
| 309 | |
Andreas Färber | 692a76d | 2013-07-26 17:31:46 +0200 | [diff] [blame] | 310 | static int pl061_initfn(SysBusDevice *sbd) |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 311 | { |
Andreas Färber | 692a76d | 2013-07-26 17:31:46 +0200 | [diff] [blame] | 312 | DeviceState *dev = DEVICE(sbd); |
| 313 | PL061State *s = PL061(dev); |
| 314 | |
Paolo Bonzini | b716368 | 2013-06-06 21:25:08 -0400 | [diff] [blame] | 315 | memory_region_init_io(&s->iomem, OBJECT(s), &pl061_ops, s, "pl061", 0x1000); |
Andreas Färber | 692a76d | 2013-07-26 17:31:46 +0200 | [diff] [blame] | 316 | sysbus_init_mmio(sbd, &s->iomem); |
| 317 | sysbus_init_irq(sbd, &s->irq); |
| 318 | qdev_init_gpio_in(dev, pl061_set_irq, 8); |
| 319 | qdev_init_gpio_out(dev, s->out, 8); |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 320 | pl061_reset(s); |
Gerd Hoffmann | 81a322d | 2009-08-14 10:36:05 +0200 | [diff] [blame] | 321 | return 0; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 322 | } |
Paul Brook | 40905a6 | 2009-06-03 15:16:49 +0100 | [diff] [blame] | 323 | |
Andreas Färber | 692a76d | 2013-07-26 17:31:46 +0200 | [diff] [blame] | 324 | static void pl061_luminary_init(Object *obj) |
Peter Maydell | 7063f49 | 2011-02-21 20:57:51 +0000 | [diff] [blame] | 325 | { |
Andreas Färber | 692a76d | 2013-07-26 17:31:46 +0200 | [diff] [blame] | 326 | PL061State *s = PL061(obj); |
| 327 | |
| 328 | s->id = pl061_id_luminary; |
Peter Maydell | 7063f49 | 2011-02-21 20:57:51 +0000 | [diff] [blame] | 329 | } |
| 330 | |
Andreas Färber | 692a76d | 2013-07-26 17:31:46 +0200 | [diff] [blame] | 331 | static void pl061_init(Object *obj) |
Peter Maydell | 7063f49 | 2011-02-21 20:57:51 +0000 | [diff] [blame] | 332 | { |
Andreas Färber | 692a76d | 2013-07-26 17:31:46 +0200 | [diff] [blame] | 333 | PL061State *s = PL061(obj); |
| 334 | |
| 335 | s->id = pl061_id; |
Peter Maydell | 7063f49 | 2011-02-21 20:57:51 +0000 | [diff] [blame] | 336 | } |
| 337 | |
Anthony Liguori | 999e12b | 2012-01-24 13:12:29 -0600 | [diff] [blame] | 338 | static void pl061_class_init(ObjectClass *klass, void *data) |
| 339 | { |
Anthony Liguori | 39bffca | 2011-12-07 21:34:16 -0600 | [diff] [blame] | 340 | DeviceClass *dc = DEVICE_CLASS(klass); |
Anthony Liguori | 999e12b | 2012-01-24 13:12:29 -0600 | [diff] [blame] | 341 | SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); |
| 342 | |
Andreas Färber | 692a76d | 2013-07-26 17:31:46 +0200 | [diff] [blame] | 343 | k->init = pl061_initfn; |
Anthony Liguori | 39bffca | 2011-12-07 21:34:16 -0600 | [diff] [blame] | 344 | dc->vmsd = &vmstate_pl061; |
Anthony Liguori | 999e12b | 2012-01-24 13:12:29 -0600 | [diff] [blame] | 345 | } |
| 346 | |
Andreas Färber | 8c43a6f | 2013-01-10 16:19:07 +0100 | [diff] [blame] | 347 | static const TypeInfo pl061_info = { |
Andreas Färber | 692a76d | 2013-07-26 17:31:46 +0200 | [diff] [blame] | 348 | .name = TYPE_PL061, |
Anthony Liguori | 39bffca | 2011-12-07 21:34:16 -0600 | [diff] [blame] | 349 | .parent = TYPE_SYS_BUS_DEVICE, |
Andreas Färber | ee663e9 | 2013-07-26 17:21:21 +0200 | [diff] [blame] | 350 | .instance_size = sizeof(PL061State), |
Andreas Färber | 692a76d | 2013-07-26 17:31:46 +0200 | [diff] [blame] | 351 | .instance_init = pl061_init, |
Anthony Liguori | 39bffca | 2011-12-07 21:34:16 -0600 | [diff] [blame] | 352 | .class_init = pl061_class_init, |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 353 | }; |
| 354 | |
Andreas Färber | 8c43a6f | 2013-01-10 16:19:07 +0100 | [diff] [blame] | 355 | static const TypeInfo pl061_luminary_info = { |
Anthony Liguori | 39bffca | 2011-12-07 21:34:16 -0600 | [diff] [blame] | 356 | .name = "pl061_luminary", |
Andreas Färber | 692a76d | 2013-07-26 17:31:46 +0200 | [diff] [blame] | 357 | .parent = TYPE_PL061, |
| 358 | .instance_init = pl061_luminary_init, |
Peter Maydell | a35faa9 | 2011-08-03 23:13:45 +0100 | [diff] [blame] | 359 | }; |
| 360 | |
Andreas Färber | 83f7d43 | 2012-02-09 15:20:55 +0100 | [diff] [blame] | 361 | static void pl061_register_types(void) |
Paul Brook | 40905a6 | 2009-06-03 15:16:49 +0100 | [diff] [blame] | 362 | { |
Anthony Liguori | 39bffca | 2011-12-07 21:34:16 -0600 | [diff] [blame] | 363 | type_register_static(&pl061_info); |
| 364 | type_register_static(&pl061_luminary_info); |
Paul Brook | 40905a6 | 2009-06-03 15:16:49 +0100 | [diff] [blame] | 365 | } |
| 366 | |
Andreas Färber | 83f7d43 | 2012-02-09 15:20:55 +0100 | [diff] [blame] | 367 | type_init(pl061_register_types) |