| /* |
| * 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); |
| } |