blob: 0010c91477adefebb25570c57be29bb679f16d90 [file] [log] [blame] [edit]
/*
* 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);
}
}