From mboxrd@z Thu Jan 1 00:00:00 1970 From: Simon Glass Date: Sat, 17 Oct 2015 11:50:02 -0600 Subject: [U-Boot] [PATCH 5/8] dm: pci: Add functions to emulate 8- and 16-bit access In-Reply-To: <1445104205-4079-1-git-send-email-sjg@chromium.org> References: <1445104205-4079-1-git-send-email-sjg@chromium.org> Message-ID: <1445104205-4079-6-git-send-email-sjg@chromium.org> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Provide a few functions to support using 32-bit access to emulate 8- and 16-bit access. Signed-off-by: Simon Glass --- drivers/pci/pci-uclass.c | 39 +++++++++++++++++++++++++++++++++++++++ include/pci.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index a59e468..1c6df0f 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -916,6 +916,45 @@ int pci_find_first_device(struct udevice **devp) return skip_to_next_device(bus, devp); } +ulong pci_conv_32_to_size(ulong value, uint offset, enum pci_size_t size) +{ + switch (size) { + case PCI_SIZE_8: + return (value >> ((offset & 3) * 8)) & 0xff; + case PCI_SIZE_16: + return (value >> ((offset & 2) * 8)) & 0xffff; + default: + return value; + } +} + +ulong pci_conv_size_to_32(ulong old, ulong value, uint offset, + enum pci_size_t size) +{ + uint off_mask; + uint val_mask, shift; + ulong ldata, mask; + + switch (size) { + case PCI_SIZE_8: + off_mask = 3; + val_mask = 0xff; + break; + case PCI_SIZE_16: + off_mask = 2; + val_mask = 0xffff; + break; + default: + return value; + } + shift = (offset & off_mask) * 8; + ldata = (value & val_mask) << shift; + mask = val_mask << shift; + value = (old & ~mask) | ldata; + + return value; +} + UCLASS_DRIVER(pci) = { .id = UCLASS_PCI, .name = "pci", diff --git a/include/pci.h b/include/pci.h index e24c970..f40a83d 100644 --- a/include/pci.h +++ b/include/pci.h @@ -1092,6 +1092,37 @@ static inline int pci_read_config_byte(pci_dev_t pcidev, int offset, } /** + * pci_conv_32_to_size() - convert a 32-bit read value to the given size + * + * Some PCI buses must always perform 32-bit reads. The data must then be + * shifted and masked to reflect the required access size and offset. This + * function performs this transformation. + * + * @value: Value to transform (32-bit value read from @offset & ~3) + * @offset: Register offset that was read + * @size: Required size of the result + * @return the value that would have been obtained if the read had been + * performed@the given offset with the correct size + */ +ulong pci_conv_32_to_size(ulong value, uint offset, enum pci_size_t size); + +/** + * pci_conv_size_to_32() - update a 32-bit value to prepare for a write + * + * Some PCI buses must always perform 32-bit writes. To emulate a smaller + * write the old 32-bit data must be read, updated with the required new data + * and written back as a 32-bit value. This function performs the + * transformation from the old value to the new value. + * + * @value: Value to transform (32-bit value read from @offset & ~3) + * @offset: Register offset that should be written + * @size: Required size of the write + * @return the value that should be written as a 32-bit access to @offset & ~3. + */ +ulong pci_conv_size_to_32(ulong old, ulong value, uint offset, + enum pci_size_t size); + +/** * struct dm_pci_emul_ops - PCI device emulator operations */ struct dm_pci_emul_ops { -- 2.6.0.rc2.230.g3dd15c0