| /* |
| * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) |
| * |
| * SPDX-License-Identifier: BSD-2-Clause |
| */ |
| #include <stdio.h> |
| #include <assert.h> |
| #include <pci/pci.h> |
| #include <pci/ioreg.h> |
| |
| void libpci_out(uint32_t port_no, uint32_t val, uint8_t size) { |
| assert(size == 1 || size == 2 || size == 4); |
| int UNUSED ret = libpci_iowrite(port_no, val, size); |
| assert(ret == 0); |
| } |
| |
| uint32_t libpci_in(uint32_t port_no, uint8_t size) { |
| assert(size == 1 || size == 2 || size == 4); |
| uint32_t val = 0; |
| int UNUSED ret = libpci_ioread(port_no, &val, size); |
| assert(ret == 0); |
| return val; |
| } |
| |
| void libpci_out32(uint32_t port_no, uint32_t val) { |
| libpci_out(port_no, val, 4); |
| } |
| |
| uint32_t libpci_in32(uint32_t port_no) { |
| return libpci_in(port_no, 4); |
| } |
| |
| void libpci_out16(uint32_t port_no, uint32_t val) { |
| libpci_out(port_no, val, 2); |
| } |
| |
| uint32_t libpci_in16(uint32_t port_no) { |
| return libpci_in(port_no, 2); |
| } |
| |
| void libpci_out8(uint32_t port_no, uint32_t val) { |
| libpci_out(port_no, val, 1); |
| } |
| |
| uint32_t libpci_in8(uint32_t port_no) { |
| return libpci_in(port_no, 1); |
| } |
| |
| uint32_t libpci_read_reg32(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t reg) { |
| reg &= ~MASK(2); |
| libpci_out32(PCI_CONF_PORT_ADDR, 0x80000000 | bus << 16 | dev << 11 | fun << 8 | reg); |
| return libpci_in32(PCI_CONF_PORT_DATA); |
| } |
| |
| void libpci_write_reg32(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t reg, uint32_t val) { |
| reg &= ~MASK(2); |
| libpci_out32(PCI_CONF_PORT_ADDR, 0x80000000 | bus << 16 | dev << 11 | fun << 8 | reg); |
| libpci_out32(PCI_CONF_PORT_DATA, val); |
| } |
| |
| uint16_t libpci_read_reg16(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t reg) { |
| reg &= ~MASK(1); |
| libpci_out32(PCI_CONF_PORT_ADDR, 0x80000000 | bus << 16 | dev << 11 | fun << 8 | (reg & ~MASK(2))); |
| return ( libpci_in32(PCI_CONF_PORT_DATA) >> ((reg & MASK(2)) * 8) ) & 0xFFFF; |
| } |
| |
| void libpci_write_reg16(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t reg, uint16_t val) { |
| reg &= ~MASK(1); |
| libpci_out32(PCI_CONF_PORT_ADDR, 0x80000000 | bus << 16 | dev << 11 | fun << 8 | reg); |
| libpci_out16(PCI_CONF_PORT_DATA, val); |
| } |
| |
| uint16_t libpci_read_reg8(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t reg) { |
| libpci_out32(PCI_CONF_PORT_ADDR, 0x80000000 | bus << 16 | dev << 11 | fun << 8 | (reg & ~MASK(2))); |
| return ( libpci_in32(PCI_CONF_PORT_DATA) >> ((reg & MASK(2)) * 8) ) & 0xFF; |
| } |
| |
| void libpci_write_reg8(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t reg, uint8_t val) { |
| libpci_out32(PCI_CONF_PORT_ADDR, 0x80000000 | bus << 16 | dev << 11 | fun << 8 | reg); |
| libpci_out8(PCI_CONF_PORT_DATA, val); |
| } |
| |
| uint32_t libpci_read_reg(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t reg, uint8_t size) { |
| switch (size) { |
| case 1: return (uint32_t) libpci_read_reg8(bus, dev, fun, reg); |
| case 2: return (uint32_t) libpci_read_reg16(bus, dev, fun, reg); |
| case 4: return (uint32_t) libpci_read_reg32(bus, dev, fun, reg); |
| default: |
| assert(!"libpci_read_reg: unsupported size."); |
| return 0xFFFFFFFF; |
| } |
| } |
| |
| void libpci_write_reg(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t reg, uint32_t val, uint8_t size) { |
| switch (size) { |
| case 1: libpci_write_reg8(bus, dev, fun, reg, val); return; |
| case 2: libpci_write_reg16(bus, dev, fun, reg, val); return; |
| case 4: libpci_write_reg32(bus, dev, fun, reg, val); return; |
| default: |
| assert(!"libpci_write_reg: unsupported size."); |
| return; |
| } |
| } |
| |
| void libpci_portno_reverse_lookup(uint32_t port_no, uint8_t *bus, uint8_t *dev, uint8_t *fun, |
| uint8_t *reg) { |
| if (bus) { |
| *bus = (port_no >> 16) & MASK(8); |
| } |
| if (dev) { |
| *dev = (port_no >> 11) & MASK(5); |
| } |
| if (fun) { |
| *fun = (port_no >> 8) & MASK(3); |
| } |
| if (reg) { |
| *reg = port_no & MASK(8); |
| } |
| } |