1 /* 2 * Raspberry Pi emulation (c) 2012 Gregory Estrade 3 * This code is licensed under the GNU GPLv2 and later. 4 */ 5 6 #include "hw/misc/bcm2835_property.h" 7 #include "hw/misc/bcm2835_mbox_defs.h" 8 #include "sysemu/dma.h" 9 10 /* https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface */ 11 12 static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) 13 { 14 uint32_t tag; 15 uint32_t bufsize; 16 uint32_t tot_len; 17 size_t resplen; 18 uint32_t tmp; 19 20 value &= ~0xf; 21 22 s->addr = value; 23 24 tot_len = ldl_phys(&s->dma_as, value); 25 26 /* @(addr + 4) : Buffer response code */ 27 value = s->addr + 8; 28 while (value + 8 <= s->addr + tot_len) { 29 tag = ldl_phys(&s->dma_as, value); 30 bufsize = ldl_phys(&s->dma_as, value + 4); 31 /* @(value + 8) : Request/response indicator */ 32 resplen = 0; 33 switch (tag) { 34 case 0x00000000: /* End tag */ 35 break; 36 case 0x00000001: /* Get firmware revision */ 37 stl_phys(&s->dma_as, value + 12, 346337); 38 resplen = 4; 39 break; 40 case 0x00010001: /* Get board model */ 41 qemu_log_mask(LOG_UNIMP, 42 "bcm2835_property: %x get board model NYI\n", tag); 43 resplen = 4; 44 break; 45 case 0x00010002: /* Get board revision */ 46 qemu_log_mask(LOG_UNIMP, 47 "bcm2835_property: %x get board revision NYI\n", tag); 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_phys(&s->dma_as, value + 12, 0); 62 /* size */ 63 stl_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_phys(&s->dma_as, value + 16); 71 stl_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_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_phys(&s->dma_as, value + 12)) { 92 case 1: /* EMMC */ 93 stl_phys(&s->dma_as, value + 16, 50000000); 94 break; 95 case 2: /* UART */ 96 stl_phys(&s->dma_as, value + 16, 3000000); 97 break; 98 default: 99 stl_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_phys(&s->dma_as, value + 16, 25000); 117 resplen = 8; 118 break; 119 120 case 0x0003000A: /* Get max temperature */ 121 stl_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_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_phys(&s->dma_as, value + 8, (1 << 31) | resplen); 147 value += bufsize + 12; 148 } 149 150 /* Buffer response code */ 151 stl_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("ram-size", BCM2835PropertyState, ram_size, 0), 262 DEFINE_PROP_END_OF_LIST() 263 }; 264 265 static void bcm2835_property_class_init(ObjectClass *klass, void *data) 266 { 267 DeviceClass *dc = DEVICE_CLASS(klass); 268 269 dc->props = bcm2835_property_props; 270 dc->realize = bcm2835_property_realize; 271 dc->vmsd = &vmstate_bcm2835_property; 272 } 273 274 static TypeInfo bcm2835_property_info = { 275 .name = TYPE_BCM2835_PROPERTY, 276 .parent = TYPE_SYS_BUS_DEVICE, 277 .instance_size = sizeof(BCM2835PropertyState), 278 .class_init = bcm2835_property_class_init, 279 .instance_init = bcm2835_property_init, 280 }; 281 282 static void bcm2835_property_register_types(void) 283 { 284 type_register_static(&bcm2835_property_info); 285 } 286 287 type_init(bcm2835_property_register_types) 288