diff options
Diffstat (limited to 'device.c')
-rw-r--r-- | device.c | 70 |
1 files changed, 68 insertions, 2 deletions
@@ -22,6 +22,14 @@ static struct device *devices[] = { }; #define DEVICES_COUNT ARRAY_SIZE(devices) +bool device_generic_is_dev_addr(struct device *dev, uint32_t addr) +{ + if (addr >= dev->base && addr < dev->base + dev->size) + return true; + + return false; +} + int device_init_all(void) { unsigned int i; @@ -30,7 +38,7 @@ int device_init_all(void) for (i = 0; i < DEVICES_COUNT; i++) { struct device *dev = devices[i]; - if (dev->init == NULL) + if (unlikely(dev->init == NULL)) continue; ret = dev->init(dev); @@ -39,8 +47,66 @@ int device_init_all(void) break; } - vinfo("%s at 0x%08x\n", dev->name, dev->base); + if (dev->is_dev_addr == NULL) + dev->is_dev_addr = device_generic_is_dev_addr; + + vinfo("%s at 0x%08x - 0x%08x\n", dev->name, dev->base, + (uint32_t)(dev->base + dev->size)); } return ret; } + +/** + * Get device mapped at a specific address. + * + * @param addr address to get the mapped device for + * @return pointer to the device mapped at addr, NULL if no device is + * mapped there + */ +struct device *device_get_by_addr(uint32_t addr) +{ + unsigned int i; + struct device *dev = NULL; + + for (i = 0; i < DEVICES_COUNT; i++) { + dev = devices[i]; + if (unlikely(dev->is_dev_addr == NULL)) + continue; + if (dev->is_dev_addr(dev, addr)) + return dev; + } + + return NULL; +} + +void device_simulate_all(void) +{ + unsigned int i; + struct device *dev; + + for (i = 0; i < DEVICES_COUNT; i++) { + dev = devices[i]; + if (likely(dev->simulate != NULL)) + dev->simulate(dev); + } +} + +void io_register_init(struct io_register *reg, uint32_t addr, + uint32_t valid, uint32_t readonly, uint32_t value) +{ + reg->addr = addr; + reg->valid_mask = valid; + reg->readonly_mask = readonly; + reg->value = value; +} + +uint32_t io_register_read(struct io_register *reg) +{ + return reg->value & reg->valid_mask; +} + +void io_register_write(struct io_register *reg, uint32_t value) +{ + reg->value = value & ~(reg->readonly_mask); +} |