Changed the x86 64 pci driver

Signed-off-by: yangshuyong <yangshuyong@xiaomi.com>
Signed-off-by: lipengfei28 <lipengfei28@xiaomi.com>
This commit is contained in:
yangshuyong
2024-03-05 14:25:08 +08:00
committed by Xiang Xiao
parent 125884ae95
commit 7cbb7d36d8
3 changed files with 211 additions and 79 deletions
+153 -79
View File
@@ -35,39 +35,41 @@
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
#define PCI_CFG_ADDR 0xcf8 #define PCI_CFG_ADDR 0xcf8
#define PCI_DATA_ADDR 0xcfc #define PCI_DATA_ADDR 0xcfc
#define PCI_CFG_EN (1 << 31) #define PCI_CFG_EN (1 << 31)
/**************************************************************************** /****************************************************************************
* Private Functions Definitions * Private Functions Definitions
****************************************************************************/ ****************************************************************************/
static void x86_64_pci_cfg_write(struct pci_dev_s *dev, int reg, static int x86_64_pci_write(struct pci_bus_s *bus, unsigned int devfn,
uint32_t val, int width); int where, int size, uint32_t val);
static uint32_t x86_64_pci_cfg_read(struct pci_dev_s *dev, int reg, static int x86_64_pci_read(struct pci_bus_s *bus, unsigned int devfn,
int width); int where, int size, uint32_t *val);
static int x86_64_pci_map_bar(uint64_t addr, uint64_t len); static uintptr_t x86_64_pci_map(struct pci_bus_s *bus, uintptr_t start,
static uint32_t x86_64_pci_io_read(const volatile void *addr, int width); uintptr_t end);
static void x86_64_pci_io_write(const volatile void *addr, uint32_t val, static int x86_64_pci_read_io(struct pci_bus_s *bus, uintptr_t addr,
int width); int size, uint32_t *val);
static int x86_64_pci_write_io(struct pci_bus_s *bus, uintptr_t addr,
int size, uint32_t val);
/**************************************************************************** /****************************************************************************
* Private Data * Private Data
****************************************************************************/ ****************************************************************************/
static const struct pci_bus_ops_s g_x86_64_pci_bus_ops = static const struct pci_ops_s g_x86_64_pci_ops =
{ {
.pci_cfg_write = x86_64_pci_cfg_write, .write = x86_64_pci_write,
.pci_cfg_read = x86_64_pci_cfg_read, .read = x86_64_pci_read,
.pci_map_bar = x86_64_pci_map_bar, .map = x86_64_pci_map,
.pci_io_read = x86_64_pci_io_read, .read_io = x86_64_pci_read_io,
.pci_io_write = x86_64_pci_io_write, .write_io = x86_64_pci_write_io,
}; };
static struct pci_bus_s g_x86_64_pci_bus = static struct pci_controller_s g_x86_64_pci =
{ {
.ops = &g_x86_64_pci_bus_ops, .ops = &g_x86_64_pci_ops
}; };
/**************************************************************************** /****************************************************************************
@@ -75,135 +77,208 @@ static struct pci_bus_s g_x86_64_pci_bus =
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: x86_64_pci_cfg_write * Name: x86_64_pci_write
* *
* Description: * Description:
* Write 8, 16, 32, 64 bits data to PCI-E configuration space of device * Write 8, 16, 32, 64 bits data to PCI configuration space of device
* specified by dev * specified by dev
* *
* Input Parameters: * Input Parameters:
* bdf - Device private data * bus - Bus that PCI device resides
* reg - A pointer to the read-only buffer of data to be written * devfn - The device and function bit field of bdf
* size - The number of bytes to send from the buffer * where - Offset in the specify PCI device cfg address space
* size - The number of bytes to send from the buffer
* val - The value to write
* *
* Returned Value: * Returned Value:
* 0: success, <0: A negated errno * 0: success, <0: A negated errno
* *
****************************************************************************/ ****************************************************************************/
static void x86_64_pci_cfg_write(struct pci_dev_s *dev, int reg, static int x86_64_pci_write(struct pci_bus_s *bus, unsigned int devfn,
uint32_t val, int width) int where, int size, uint32_t val)
{ {
uint8_t offset_mask = (4 - width); uint8_t offset_mask = (4 - size);
outl(PCI_CFG_EN | (dev->bdf << 8) | reg, PCI_CFG_ADDR); outl(PCI_CFG_EN | (bus->number << 16) | (devfn << 8) | where,
switch (width) PCI_CFG_ADDR);
switch (size)
{ {
case 1: case 1:
outb(val, PCI_DATA_ADDR + (reg & offset_mask)); outb(val, PCI_DATA_ADDR + (where & offset_mask));
return; break;
case 2: case 2:
outw(val, PCI_DATA_ADDR + (reg & offset_mask)); outw(val, PCI_DATA_ADDR + (where & offset_mask));
return; break;
case 4: case 4:
outl(val, PCI_DATA_ADDR); outl(val, PCI_DATA_ADDR);
return; break;
default: default:
pcierr("Invalid cfg write width %d\n", width); pcierr("Invalid cfg write size %d\n", size);
return -EINVAL;
} }
return 0;
} }
/**************************************************************************** /****************************************************************************
* Name: x86_64_pci_cfg_read * Name: x86_64_pci_read
* *
* Description: * Description:
* Read 8, 16, 32, 64 bits data from PCI-E configuration space of device * Read 8, 16, 32, 64 bits data from PCI configuration space of device
* specified by dev * specified by dev
* *
* Input Parameters: * Input Parameters:
* dev - Device private data * bus - Bus that PCI device resides
* buffer - A pointer to a buffer to receive the data from the device * devfn - The device and function bit field of bdf
* where - Offset in the specify PCI device cfg address space
* size - The requested number of bytes to be read * size - The requested number of bytes to be read
* val - A pointer to a buffer to receive the data from the device
* *
* Returned Value: * Returned Value:
* 0: success, <0: A negated errno * 0: success, <0: A negated errno
* *
****************************************************************************/ ****************************************************************************/
static uint32_t x86_64_pci_cfg_read(struct pci_dev_s *dev, int reg, static int x86_64_pci_read(struct pci_bus_s *bus, unsigned int devfn,
int width) int where, int size, uint32_t *val)
{ {
uint32_t ret; uint8_t offset_mask = 4 - size;
uint8_t offset_mask = 4 - width;
outl(PCI_CFG_EN | (dev->bdf << 8) | reg, PCI_CFG_ADDR); outl(PCI_CFG_EN | (bus->number << 16) | (devfn << 8) | where,
PCI_CFG_ADDR);
switch (width) switch (size)
{ {
case 1: case 1:
ret = inb(PCI_DATA_ADDR + (reg & offset_mask)); *val = inb(PCI_DATA_ADDR + (where & offset_mask));
return ret; break;
case 2: case 2:
ret = inw(PCI_DATA_ADDR + (reg & offset_mask)); *val = inw(PCI_DATA_ADDR + (where & offset_mask));
return ret; break;
case 4: case 4:
ret = inl(PCI_DATA_ADDR); *val = inl(PCI_DATA_ADDR);
return ret; break;
default: default:
pcierr("Invalid cfg read width %d\n", width); *val = 0;
pcierr("Invalid cfg read size %d\n", size);
return -EINVAL;
} }
return 0; return OK;
} }
static uint32_t x86_64_pci_io_read(const volatile void *addr, int width) /****************************************************************************
{ * Name: x86_64_pci_read_io
uint16_t portaddr = (uint16_t)(intptr_t)addr; *
* Description:
* Read 8, 16, 32, 64 bits data from PCI io address space of x86 64 device
*
* Input Parameters:
* bus - Bus that PCI device resides
* addr - The address to received data
* size - The requested number of bytes to be read
* val - A pointer to a buffer to receive the data from the device
*
* Returned Value:
* 0: success, <0: A negated errno
*
****************************************************************************/
switch (width) static int x86_64_pci_read_io(struct pci_bus_s *bus, uintptr_t addr,
int size, uint32_t *val)
{
uint16_t portaddr = (uint16_t)addr;
switch (size)
{ {
case 1: case 1:
return (uint32_t)inb(portaddr); *val = (uint32_t)inb(portaddr);
break;
case 2: case 2:
return (uint32_t)inw(portaddr); *val = (uint32_t)inw(portaddr);
break;
case 4: case 4:
return (uint32_t)inl(portaddr); *val = (uint32_t)inl(portaddr);
break;
default: default:
pcierr("Invalid read width %d\n", width); *val = 0;
pcierr("Invalid read size %d\n", size);
DEBUGPANIC(); DEBUGPANIC();
return -EINVAL;
} }
return 0; return OK;
} }
static void x86_64_pci_io_write(const volatile void *addr, uint32_t val, /****************************************************************************
int width) * Name: x86_64_pci_write_io
{ *
uint16_t portaddr = (uint16_t)(intptr_t)addr; * Description:
* Write 8, 16, 32, 64 bits data to PCI io address space of x86 64 device
*
* Input Parameters:
* bus - Bus that PCI device resides
* addr - The address to write data
* size - The requested number of bytes to be write
* val - The value to write
*
* Returned Value:
* 0: success, <0: A negated errno
*
****************************************************************************/
switch (width) static int x86_64_pci_write_io(struct pci_bus_s *bus, uintptr_t addr,
int size, uint32_t val)
{
uint16_t portaddr = (uint16_t)addr;
switch (size)
{ {
case 1: case 1:
outb((uint8_t)val, portaddr); outb((uint8_t)val, portaddr);
return; break;
case 2: case 2:
outw((uint16_t)val, portaddr); outw((uint16_t)val, portaddr);
return; break;
case 4: case 4:
outl((uint32_t)val, portaddr); outl((uint32_t)val, portaddr);
return; break;
default: default:
pcierr("Invalid write width %d\n", width); pcierr("Invalid write size %d\n", size);
DEBUGPANIC(); DEBUGPANIC();
return -EINVAL;
} }
return OK;
} }
static int x86_64_pci_map_bar(uint64_t addr, uint64_t len) /****************************************************************************
* Name: x86_64_pci_map
*
* Description:
* Map a memory region
*
* Input Parameters:
* bus - Bus that PCI device resides
* start - The start address to map
* end - The end address to map
*
* Returned Value:
* >0: success, 0: A positive value errno
*
****************************************************************************/
static uintptr_t x86_64_pci_map(struct pci_bus_s *bus, uintptr_t start,
uintptr_t end)
{ {
up_map_region((void *)(uintptr_t)addr, len, int ret;
X86_PAGE_WR | X86_PAGE_PRESENT | X86_PAGE_NOCACHE | X86_PAGE_GLOBAL);
return OK; ret = up_map_region((void *)start, end - start + 1, X86_PAGE_WR |
X86_PAGE_PRESENT | X86_PAGE_NOCACHE | X86_PAGE_GLOBAL);
return ret < 0 ? 0 : start;
} }
/**************************************************************************** /****************************************************************************
@@ -214,12 +289,11 @@ static int x86_64_pci_map_bar(uint64_t addr, uint64_t len)
* Name: x86_64_pci_init * Name: x86_64_pci_init
* *
* Description: * Description:
* Initialize the PCI-E bus * Initialize the PCI bus
* *
****************************************************************************/ ****************************************************************************/
void x86_64_pci_init(void) void x86_64_pci_init(void)
{ {
pciinfo("Initializing PCI Bus\n"); pci_register_controller(&g_x86_64_pci);
pci_initialize(&g_x86_64_pci_bus);
} }
+36
View File
@@ -74,6 +74,36 @@
return ret; \ return ret; \
} }
#define PCI_BUS_READ_IO(len, type, size) \
int pci_bus_read_io_##len(FAR struct pci_bus_s *bus, uintptr_t where, \
FAR type *value) \
{ \
int ret = -EINVAL; \
uint32_t data = 0; \
\
if (!PCI_##len##_BAD) \
{ \
ret = bus->ctrl->ops->read_io(bus, where, size, &data); \
} \
\
*value = (type)data; \
return ret; \
}
#define PCI_BUS_WRITE_IO(len, type, size) \
int pci_bus_write_io_##len(FAR struct pci_bus_s *bus, uintptr_t where, \
type value) \
{ \
int ret = -EINVAL; \
\
if (!PCI_##len##_BAD) \
{ \
ret = bus->ctrl->ops->write_io(bus, where, size, value); \
} \
\
return ret; \
}
#define pci_match_one_device(id, dev) \ #define pci_match_one_device(id, dev) \
(((id)->vendor == PCI_ANY_ID || (id)->vendor == (dev)->vendor) && \ (((id)->vendor == PCI_ANY_ID || (id)->vendor == (dev)->vendor) && \
((id)->device == PCI_ANY_ID || (id)->device == (dev)->device) && \ ((id)->device == PCI_ANY_ID || (id)->device == (dev)->device) && \
@@ -1171,3 +1201,9 @@ PCI_BUS_READ_CONFIG(dword, uint32_t, 4)
PCI_BUS_WRITE_CONFIG(byte, uint8_t, 1) PCI_BUS_WRITE_CONFIG(byte, uint8_t, 1)
PCI_BUS_WRITE_CONFIG(word, uint16_t, 2) PCI_BUS_WRITE_CONFIG(word, uint16_t, 2)
PCI_BUS_WRITE_CONFIG(dword, uint32_t, 4) PCI_BUS_WRITE_CONFIG(dword, uint32_t, 4)
PCI_BUS_READ_IO(byte, uint8_t, 1)
PCI_BUS_READ_IO(word, uint16_t, 2)
PCI_BUS_READ_IO(dword, uint32_t, 4)
PCI_BUS_WRITE_IO(byte, uint8_t, 1)
PCI_BUS_WRITE_IO(word, uint16_t, 2)
PCI_BUS_WRITE_IO(dword, uint32_t, 4)
+22
View File
@@ -152,6 +152,24 @@
#define pci_write_config_dword(dev, where, val) \ #define pci_write_config_dword(dev, where, val) \
pci_bus_write_config_dword((dev)->bus, (dev)->devfn, where, val) pci_bus_write_config_dword((dev)->bus, (dev)->devfn, where, val)
#define pci_read_io_byte(dev, addr, val) \
pci_bus_read_io_byte((dev)->bus, addr, val)
#define pci_read_io_word(dev, addr, val) \
pci_bus_read_io_word((dev)->bus, addr, val)
#define pci_read_io_dword(dev, addr, val) \
pci_bus_read_io_dword((dev)->bus, addr, val)
#define pci_write_io_byte(dev, addr, val) \
pci_bus_write_io_byte((dev)->bus, addr, val)
#define pci_write_io_word(dev, addr, val) \
pci_bus_write_io_word((dev)->bus, addr, val)
#define pci_write_io_dword(dev, addr, val) \
pci_bus_write_io_dword((dev)->bus, addr, val)
/**************************************************************************** /****************************************************************************
* Public Types * Public Types
****************************************************************************/ ****************************************************************************/
@@ -232,6 +250,10 @@ struct pci_ops_s
CODE uintptr_t (*map)(FAR struct pci_bus_s *bus, uintptr_t start, CODE uintptr_t (*map)(FAR struct pci_bus_s *bus, uintptr_t start,
uintptr_t end); uintptr_t end);
CODE int (*read_io)(FAR struct pci_bus_s *bus, uintptr_t addr,
int size, FAR uint32_t *val);
CODE int (*write_io)(FAR struct pci_bus_s *bus, uintptr_t addr,
int size, uint32_t val);
}; };
/* Each pci channel is a top-level PCI bus seem by CPU. A machine with /* Each pci channel is a top-level PCI bus seem by CPU. A machine with