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

View file

@ -35,39 +35,41 @@
* Pre-processor Definitions
****************************************************************************/
#define PCI_CFG_ADDR 0xcf8
#define PCI_DATA_ADDR 0xcfc
#define PCI_CFG_EN (1 << 31)
#define PCI_CFG_ADDR 0xcf8
#define PCI_DATA_ADDR 0xcfc
#define PCI_CFG_EN (1 << 31)
/****************************************************************************
* Private Functions Definitions
****************************************************************************/
static void x86_64_pci_cfg_write(struct pci_dev_s *dev, int reg,
uint32_t val, int width);
static uint32_t x86_64_pci_cfg_read(struct pci_dev_s *dev, int reg,
int width);
static int x86_64_pci_map_bar(uint64_t addr, uint64_t len);
static uint32_t x86_64_pci_io_read(const volatile void *addr, int width);
static void x86_64_pci_io_write(const volatile void *addr, uint32_t val,
int width);
static int x86_64_pci_write(struct pci_bus_s *bus, unsigned int devfn,
int where, int size, uint32_t val);
static int x86_64_pci_read(struct pci_bus_s *bus, unsigned int devfn,
int where, int size, uint32_t *val);
static uintptr_t x86_64_pci_map(struct pci_bus_s *bus, uintptr_t start,
uintptr_t end);
static int x86_64_pci_read_io(struct pci_bus_s *bus, uintptr_t addr,
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
****************************************************************************/
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,
.pci_cfg_read = x86_64_pci_cfg_read,
.pci_map_bar = x86_64_pci_map_bar,
.pci_io_read = x86_64_pci_io_read,
.pci_io_write = x86_64_pci_io_write,
.write = x86_64_pci_write,
.read = x86_64_pci_read,
.map = x86_64_pci_map,
.read_io = x86_64_pci_read_io,
.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:
* 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
*
* Input Parameters:
* bdf - Device private data
* reg - A pointer to the read-only buffer of data to be written
* size - The number of bytes to send from the buffer
* bus - Bus that PCI device resides
* devfn - The device and function bit field of bdf
* 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:
* 0: success, <0: A negated errno
*
****************************************************************************/
static void x86_64_pci_cfg_write(struct pci_dev_s *dev, int reg,
uint32_t val, int width)
static int x86_64_pci_write(struct pci_bus_s *bus, unsigned int devfn,
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);
switch (width)
outl(PCI_CFG_EN | (bus->number << 16) | (devfn << 8) | where,
PCI_CFG_ADDR);
switch (size)
{
case 1:
outb(val, PCI_DATA_ADDR + (reg & offset_mask));
return;
outb(val, PCI_DATA_ADDR + (where & offset_mask));
break;
case 2:
outw(val, PCI_DATA_ADDR + (reg & offset_mask));
return;
outw(val, PCI_DATA_ADDR + (where & offset_mask));
break;
case 4:
outl(val, PCI_DATA_ADDR);
return;
break;
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:
* 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
*
* Input Parameters:
* dev - Device private data
* buffer - A pointer to a buffer to receive the data from the device
* bus - Bus that PCI device resides
* 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
* val - A pointer to a buffer to receive the data from the device
*
* Returned Value:
* 0: success, <0: A negated errno
*
****************************************************************************/
static uint32_t x86_64_pci_cfg_read(struct pci_dev_s *dev, int reg,
int width)
static int x86_64_pci_read(struct pci_bus_s *bus, unsigned int devfn,
int where, int size, uint32_t *val)
{
uint32_t ret;
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,
PCI_CFG_ADDR);
switch (width)
switch (size)
{
case 1:
ret = inb(PCI_DATA_ADDR + (reg & offset_mask));
return ret;
*val = inb(PCI_DATA_ADDR + (where & offset_mask));
break;
case 2:
ret = inw(PCI_DATA_ADDR + (reg & offset_mask));
return ret;
*val = inw(PCI_DATA_ADDR + (where & offset_mask));
break;
case 4:
ret = inl(PCI_DATA_ADDR);
return ret;
*val = inl(PCI_DATA_ADDR);
break;
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)
{
uint16_t portaddr = (uint16_t)(intptr_t)addr;
/****************************************************************************
* Name: x86_64_pci_read_io
*
* 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:
return (uint32_t)inb(portaddr);
*val = (uint32_t)inb(portaddr);
break;
case 2:
return (uint32_t)inw(portaddr);
*val = (uint32_t)inw(portaddr);
break;
case 4:
return (uint32_t)inl(portaddr);
*val = (uint32_t)inl(portaddr);
break;
default:
pcierr("Invalid read width %d\n", width);
*val = 0;
pcierr("Invalid read size %d\n", size);
DEBUGPANIC();
return -EINVAL;
}
return 0;
return OK;
}
static void x86_64_pci_io_write(const volatile void *addr, uint32_t val,
int width)
{
uint16_t portaddr = (uint16_t)(intptr_t)addr;
/****************************************************************************
* Name: x86_64_pci_write_io
*
* 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:
outb((uint8_t)val, portaddr);
return;
break;
case 2:
outw((uint16_t)val, portaddr);
return;
break;
case 4:
outl((uint32_t)val, portaddr);
return;
break;
default:
pcierr("Invalid write width %d\n", width);
pcierr("Invalid write size %d\n", size);
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,
X86_PAGE_WR | X86_PAGE_PRESENT | X86_PAGE_NOCACHE | X86_PAGE_GLOBAL);
return OK;
int ret;
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
*
* Description:
* Initialize the PCI-E bus
* Initialize the PCI bus
*
****************************************************************************/
void x86_64_pci_init(void)
{
pciinfo("Initializing PCI Bus\n");
pci_initialize(&g_x86_64_pci_bus);
pci_register_controller(&g_x86_64_pci);
}

View file

@ -74,6 +74,36 @@
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) \
(((id)->vendor == PCI_ANY_ID || (id)->vendor == (dev)->vendor) && \
((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(word, uint16_t, 2)
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)

View file

@ -152,6 +152,24 @@
#define pci_write_config_dword(dev, 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
****************************************************************************/
@ -232,6 +250,10 @@ struct pci_ops_s
CODE uintptr_t (*map)(FAR struct pci_bus_s *bus, uintptr_t start,
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