static unsigned int ca91cx42_master_rmw()

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;
}