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:
parent
125884ae95
commit
7cbb7d36d8
3 changed files with 211 additions and 79 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue