hw/pxa2xx.c: Fix handling of pxa2xx_i2c variable offset within region
The pxa2xx I2C controller can have its registers at an arbitrary offset within the MemoryRegion it creates. We use this to create two controllers, one which covers a region of size 0x10000 with registers starting at an offset 0x1600 into that region, and a second one which covers a region of size just 0x100 with the registers starting at the base of the region. The implementation of this offsetting uses two qdev properties, "offset" (which sets the offset which must be subtracted from the address to get the offset into the actual register bank) and "size", which is the size of the MemoryRegion. We were actually using "offset" for two purposes: firstly the required one of handling the registers not being at the base of the MemoryRegion, and secondly as a workaround for a deficiency of QEMU. Until commit5312bd8b3
, if a MemoryRegion was mapped at a non-page boundary, the address passed into the read and write functions would be the offset from the start of the page, not the offset from the start of the MemoryRegion. So when calculating the value to set the "offset" qdev property we included a rounding to a page boundary. Following commit5312bd8b3
MemoryRegion read/write functions are now correctly passed the offset from the base of the region, and our workaround now means we're subtracting too much from addresses, resulting in warnings like "pxa2xx_i2c_read: Bad register 0xffffff90". The fix for this is simply to remove the rounding to a page boundary; this allows us to slightly simplify the expression since base - (base & (~region_size)) == base & region_size The qdev property "offset" itself must remain because it is still performing its primary job of handling register banks not being at the base of the MemoryRegion. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Andreas Färber <afaerber@suse.de>
This commit is contained in:
parent
27424dcc68
commit
14dd5faa7e
@ -1507,8 +1507,7 @@ PXA2xxI2CState *pxa2xx_i2c_init(target_phys_addr_t base,
|
||||
|
||||
i2c_dev = sysbus_from_qdev(qdev_create(NULL, "pxa2xx_i2c"));
|
||||
qdev_prop_set_uint32(&i2c_dev->qdev, "size", region_size + 1);
|
||||
qdev_prop_set_uint32(&i2c_dev->qdev, "offset",
|
||||
base - (base & (~region_size) & TARGET_PAGE_MASK));
|
||||
qdev_prop_set_uint32(&i2c_dev->qdev, "offset", base & region_size);
|
||||
|
||||
qdev_init_nofail(&i2c_dev->qdev);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user