blob: 80436e6a765eaf7c402ff496843c5f2765f2560b [file] [log] [blame] [edit]
/*
* Copyright 2019, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <assert.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdio.h>
#include <camkes.h>
#include <camkes/io.h>
static ps_io_port_ops_t io_ops;
#define CONFIG_ADDR 0xcf8
#define CONFIG_DATA 0xcfc
static void config_select(uint8_t bus, uint8_t dev, uint8_t fun, unsigned int offset)
{
/* Convert to 32bit values for doing bit shifting on */
uint32_t lbus = bus;
uint32_t ldev = dev;
uint32_t lfun = fun;
uint32_t address = (lbus << 16) | (ldev << 11) | (lfun << 8) | (offset & 0xfc) | 0x80000000u;
ps_io_port_out(&io_ops, CONFIG_ADDR, IOSIZE_32, address);
}
uint8_t pci_config_read8(uint8_t bus, uint8_t dev, uint8_t fun, unsigned int offset)
{
config_select(bus, dev, fun, offset);
uint32_t result = 0;
uint32_t port = CONFIG_DATA + (offset & 3);
int error = ps_io_port_in(&io_ops, port, IOSIZE_8, &result);
if (error) {
return 0;
}
return (uint8_t) result;
}
uint16_t pci_config_read16(uint8_t bus, uint8_t dev, uint8_t fun, unsigned int offset)
{
config_select(bus, dev, fun, offset);
uint32_t result = 0;
uint32_t port = CONFIG_DATA + (offset & 2);
int error = ps_io_port_in(&io_ops, port, IOSIZE_16, &result);
if (error) {
return 0;
}
return (uint16_t) result;
}
uint32_t pci_config_read32(uint8_t bus, uint8_t dev, uint8_t fun, unsigned int offset)
{
config_select(bus, dev, fun, offset);
uint32_t result = 0;
uint32_t port = CONFIG_DATA;
int error = ps_io_port_in(&io_ops, port, IOSIZE_32, &result);
if (error) {
return 0;
}
return result;
}
void pci_config_write8(uint8_t bus, uint8_t dev, uint8_t fun, unsigned int offset, uint8_t val)
{
config_select(bus, dev, fun, offset);
uint32_t port = CONFIG_DATA + (offset & 3);
// Ignore the error, if any
ps_io_port_out(&io_ops, port, IOSIZE_8, val);
}
void pci_config_write16(uint8_t bus, uint8_t dev, uint8_t fun, unsigned int offset, uint16_t val)
{
config_select(bus, dev, fun, offset);
uint32_t port = CONFIG_DATA + (offset & 2);
// Ignore the error, if any
ps_io_port_out(&io_ops, port, IOSIZE_16, val);
}
void pci_config_write32(uint8_t bus, uint8_t dev, uint8_t fun, unsigned int offset, uint32_t val)
{
config_select(bus, dev, fun, offset);
uint32_t port = CONFIG_DATA;
// Ignore the error, if any
ps_io_port_out(&io_ops, port, IOSIZE_32, val);
}
void pre_init(void)
{
set_putchar(putchar_putchar);
int error = camkes_io_port_ops(&io_ops);
assert(!error);
}