1 /* 2 * Raspberry Pi emulation (c) 2012 Gregory Estrade 3 * This code is licensed under the GNU GPLv2 and later. 4 */ 5 6 #include "qemu/osdep.h" 7 #include "hw/misc/bcm2835_property.h" 8 #include "hw/misc/bcm2835_mbox_defs.h" 9 #include "sysemu/dma.h" 10 11 /* https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface */ 12 13 static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) 14 { 15 uint32_t tag; 16 uint32_t bufsize; 17 uint32_t tot_len; 18 size_t resplen; 19 uint32_t tmp; 20 21 value &= ~0xf; 22 23 s->addr = value; 24 25 tot_len = ldl_le_phys(&s->dma_as, value); 26 27 /* @(addr + 4) : Buffer response code */ 28 value = s->addr + 8; 29 while (value + 8 <= s->addr + tot_len) { 30 tag = ldl_le_phys(&s->dma_as, value); 31 bufsize = ldl_le_phys(&s->dma_as, value + 4); 32 /* @(value + 8) : Request/response indicator */ 33 resplen = 0; 34 switch (tag) { 35 case 0x00000000: /* End tag */ 36 break; 37 case 0x00000001: /* Get firmware revision */ 38 stl_le_phys(&s->dma_as, value + 12, 346337); 39 resplen = 4; 40 break; 41 case 0x00010001: /* Get board model */ 42 qemu_log_mask(LOG_UNIMP, 43 "bcm2835_property: %x get board model NYI\n", tag); 44 resplen = 4; 45 break; 46 case 0x00010002: /* Get board revision */ 47 stl_le_phys(&s->dma_as, value + 12, s->board_rev); 48 resplen = 4; 49 break; 50 case 0x00010003: /* Get board MAC address */ 51 resplen = sizeof(s->macaddr.a); 52 dma_memory_write(&s->dma_as, value + 12, s->macaddr.a, resplen); 53 break; 54 case 0x00010004: /* Get board serial */ 55 qemu_log_mask(LOG_UNIMP, 56 "bcm2835_property: %x get board serial NYI\n", tag); 57 resplen = 8; 58 break; 59 case 0x00010005: /* Get ARM memory */ 60 /* base */ 61 stl_le_phys(&s->dma_as, value + 12, 0); 62 /* size */ 63 stl_le_phys(&s->dma_as, value + 16, s->ram_size); 64 resplen = 8; 65 break; 66 case 0x00028001: /* Set power state */ 67 /* Assume that whatever device they asked for exists, 68 * and we'll just claim we set it to the desired state 69 */ 70 tmp = ldl_le_phys(&s->dma_as, value + 16); 71 stl_le_phys(&s->dma_as, value + 16, (tmp & 1)); 72 resplen = 8; 73 break; 74 75 /* Clocks */ 76 77 case 0x00030001: /* Get clock state */ 78 stl_le_phys(&s->dma_as, value + 16, 0x1); 79 resplen = 8; 80 break; 81 82 case 0x00038001: /* Set clock state */ 83 qemu_log_mask(LOG_UNIMP, 84 "bcm2835_property: %x set clock state NYI\n", tag); 85 resplen = 8; 86 break; 87 88 case 0x00030002: /* Get clock rate */ 89 case 0x00030004: /* Get max clock rate */ 90 case 0x00030007: /* Get min clock rate */ 91 switch (ldl_le_phys(&s->dma_as, value + 12)) { 92 case 1: /* EMMC */ 93 stl_le_phys(&s->dma_as, value + 16, 50000000); 94 break; 95 case 2: /* UART */ 96 stl_le_phys(&s->dma_as, value + 16, 3000000); 97 break; 98 default: 99 stl_le_phys(&s->dma_as, value + 16, 700000000); 100 break; 101 } 102 resplen = 8; 103 break; 104 105 case 0x00038002: /* Set clock rate */ 106 case 0x00038004: /* Set max clock rate */ 107 case 0x00038007: /* Set min clock rate */ 108 qemu_log_mask(LOG_UNIMP, 109 "bcm2835_property: %x set clock rates NYI\n", tag); 110 resplen = 8; 111 break; 112 113 /* Temperature */ 114 115 case 0x00030006: /* Get temperature */ 116 stl_le_phys(&s->dma_as, value + 16, 25000); 117 resplen = 8; 118 break; 119 120 case 0x0003000A: /* Get max temperature */ 121 stl_le_phys(&s->dma_as, value + 16, 99000); 122 resplen = 8; 123 break; 124 125 126 case 0x00060001: /* Get DMA channels */ 127 /* channels 2-5 */ 128 stl_le_phys(&s->dma_as, value + 12, 0x003C); 129 resplen = 4; 130 break; 131 132 case 0x00050001: /* Get command line */ 133 resplen = 0; 134 break; 135 136 default: 137 qemu_log_mask(LOG_GUEST_ERROR, 138 "bcm2835_property: unhandled tag %08x\n", tag); 139 break; 140 } 141 142 if (tag == 0) { 143 break; 144 } 145 146 stl_le_phys(&s->dma_as, value + 8, (1 << 31) | resplen); 147 value += bufsize + 12; 148 } 149 150 /* Buffer response code */ 151 stl_le_phys(&s->dma_as, s->addr + 4, (1 << 31)); 152 } 153 154 static uint64_t bcm2835_property_read(void *opaque, hwaddr offset, 155 unsigned size) 156 { 157 BCM2835PropertyState *s = opaque; 158 uint32_t res = 0; 159 160 switch (offset) { 161 case MBOX_AS_DATA: 162 res = MBOX_CHAN_PROPERTY | s->addr; 163 s->pending = false; 164 qemu_set_irq(s->mbox_irq, 0); 165 break; 166 167 case MBOX_AS_PENDING: 168 res = s->pending; 169 break; 170 171 default: 172 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", 173 __func__, offset); 174 return 0; 175 } 176 177 return res; 178 } 179 180 static void bcm2835_property_write(void *opaque, hwaddr offset, 181 uint64_t value, unsigned size) 182 { 183 BCM2835PropertyState *s = opaque; 184 185 switch (offset) { 186 case MBOX_AS_DATA: 187 /* bcm2835_mbox should check our pending status before pushing */ 188 assert(!s->pending); 189 s->pending = true; 190 bcm2835_property_mbox_push(s, value); 191 qemu_set_irq(s->mbox_irq, 1); 192 break; 193 194 default: 195 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", 196 __func__, offset); 197 return; 198 } 199 } 200 201 static const MemoryRegionOps bcm2835_property_ops = { 202 .read = bcm2835_property_read, 203 .write = bcm2835_property_write, 204 .endianness = DEVICE_NATIVE_ENDIAN, 205 .valid.min_access_size = 4, 206 .valid.max_access_size = 4, 207 }; 208 209 static const VMStateDescription vmstate_bcm2835_property = { 210 .name = TYPE_BCM2835_PROPERTY, 211 .version_id = 1, 212 .minimum_version_id = 1, 213 .fields = (VMStateField[]) { 214 VMSTATE_MACADDR(macaddr, BCM2835PropertyState), 215 VMSTATE_UINT32(addr, BCM2835PropertyState), 216 VMSTATE_BOOL(pending, BCM2835PropertyState), 217 VMSTATE_END_OF_LIST() 218 } 219 }; 220 221 static void bcm2835_property_init(Object *obj) 222 { 223 BCM2835PropertyState *s = BCM2835_PROPERTY(obj); 224 225 memory_region_init_io(&s->iomem, OBJECT(s), &bcm2835_property_ops, s, 226 TYPE_BCM2835_PROPERTY, 0x10); 227 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); 228 sysbus_init_irq(SYS_BUS_DEVICE(s), &s->mbox_irq); 229 } 230 231 static void bcm2835_property_reset(DeviceState *dev) 232 { 233 BCM2835PropertyState *s = BCM2835_PROPERTY(dev); 234 235 s->pending = false; 236 } 237 238 static void bcm2835_property_realize(DeviceState *dev, Error **errp) 239 { 240 BCM2835PropertyState *s = BCM2835_PROPERTY(dev); 241 Object *obj; 242 Error *err = NULL; 243 244 obj = object_property_get_link(OBJECT(dev), "dma-mr", &err); 245 if (obj == NULL) { 246 error_setg(errp, "%s: required dma-mr link not found: %s", 247 __func__, error_get_pretty(err)); 248 return; 249 } 250 251 s->dma_mr = MEMORY_REGION(obj); 252 address_space_init(&s->dma_as, s->dma_mr, NULL); 253 254 /* TODO: connect to MAC address of USB NIC device, once we emulate it */ 255 qemu_macaddr_default_if_unset(&s->macaddr); 256 257 bcm2835_property_reset(dev); 258 } 259 260 static Property bcm2835_property_props[] = { 261 DEFINE_PROP_UINT32("board-rev", BCM2835PropertyState, board_rev, 0), 262 DEFINE_PROP_UINT32("ram-size", BCM2835PropertyState, ram_size, 0), 263 DEFINE_PROP_END_OF_LIST() 264 }; 265 266 static void bcm2835_property_class_init(ObjectClass *klass, void *data) 267 { 268 DeviceClass *dc = DEVICE_CLASS(klass); 269 270 dc->props = bcm2835_property_props; 271 dc->realize = bcm2835_property_realize; 272 dc->vmsd = &vmstate_bcm2835_property; 273 } 274 275 static TypeInfo bcm2835_property_info = { 276 .name = TYPE_BCM2835_PROPERTY, 277 .parent = TYPE_SYS_BUS_DEVICE, 278 .instance_size = sizeof(BCM2835PropertyState), 279 .class_init = bcm2835_property_class_init, 280 .instance_init = bcm2835_property_init, 281 }; 282 283 static void bcm2835_property_register_types(void) 284 { 285 type_register_static(&bcm2835_property_info); 286 } 287 288 type_init(bcm2835_property_register_types) 289