in bridges/vme_ca91cx42.c [963:1016]
static unsigned int ca91cx42_master_rmw(struct vme_master_resource *image,
unsigned int mask, unsigned int compare, unsigned int swap,
loff_t offset)
{
u32 result;
uintptr_t pci_addr;
struct ca91cx42_driver *bridge;
struct device *dev;
bridge = image->parent->driver_priv;
dev = image->parent->parent;
/* Find the PCI address that maps to the desired VME address */
/* Locking as we can only do one of these at a time */
mutex_lock(&bridge->vme_rmw);
/* Lock image */
spin_lock(&image->lock);
pci_addr = (uintptr_t)image->kern_base + offset;
/* Address must be 4-byte aligned */
if (pci_addr & 0x3) {
dev_err(dev, "RMW Address not 4-byte aligned\n");
result = -EINVAL;
goto out;
}
/* Ensure RMW Disabled whilst configuring */
iowrite32(0, bridge->base + SCYC_CTL);
/* Configure registers */
iowrite32(mask, bridge->base + SCYC_EN);
iowrite32(compare, bridge->base + SCYC_CMP);
iowrite32(swap, bridge->base + SCYC_SWP);
iowrite32(pci_addr, bridge->base + SCYC_ADDR);
/* Enable RMW */
iowrite32(CA91CX42_SCYC_CTL_CYC_RMW, bridge->base + SCYC_CTL);
/* Kick process off with a read to the required address. */
result = ioread32(image->kern_base + offset);
/* Disable RMW */
iowrite32(0, bridge->base + SCYC_CTL);
out:
spin_unlock(&image->lock);
mutex_unlock(&bridge->vme_rmw);
return result;
}