Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1763029
  • 博文数量: 100
  • 博客积分: 10122
  • 博客等级: 上将
  • 技术积分: 4092
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-04 20:28
文章分类

全部博文(100)

文章存档

2010年(2)

2009年(28)

2008年(70)

我的朋友

分类:

2008-09-17 17:48:25

开发板来自 MEN 的 EM9, EM9 基于 mpc8548E SoC。

为了读 pci 设备的配置空间,需要通过 mpc8548 的 pci 设备地址寄存器和 pci 数据寄存器,定义如下:
#ifndef LIBBASE_REGS_CCSR_H
#define LIBBASE_REGS_CCSR_H

#include

/* Reference: MPC8548ERM P2-17 */

/* Read ccsr register, CCSR_BASEADDR is OS specified */
#define CCSR_REG_OFF(off) (CCSR_BASEADDR + off)
#define CCSR_REG(reg) CCSR_REG_OFF(CCSR_OFF_##reg)

/* Register offsets definition */

/* Local-Access Registers - Configuration, Control, and Status Registers */
#define CCSR_OFF_CCSRBAR 0x00000

/* Local-Access Registers - Local-Acces Window Base and Size Registers*/

/* ... */

/* PCI1/X Registers : PCI Configuration Access Registers */
#define CCSR_OFF_PCI_CFG_ADDR 0x08000
typedef struct __attribute__ ((__packed__)) _ccsr_pci_cfg_addr_t {
u_int8_t enable:1;
u_int8_t reserved1:7;
union {
struct {
u_int8_t bus;
u_int8_t device:5;
u_int8_t function:3;
} detail;
u_int16_t data;
} id;
u_int8_t reg;
} ccsr_pci_cfg_addr_t;
#define CCSR_OFF_PCI_CFG_DATA 0x08004
typedef struct _ccsr_pci_outbound_window_t {
u_int32_t POTAR;
u_int32_t POTEAR;
u_int32_t POWBAR; /* reserved for window 0(default) */
u_int32_t RESERVED1;
u_int32_t POWAR;
u_int32_t RESERVED2;
u_int32_t RESERVED3;
u_int32_t RESERVED4;
} ccsr_pci_outbound_window_t;
#define CCSR_OFFBASE_PCI_OUTBOUND_WINDOW 0x08C00
...
#endif
为了读写mpc8548的 CCSR 寄存器,按照手册,读写后必须执行sync/isync指令,所以定义了这些操作:
#ifndef LIBBASE_LOWIO_H
#define LIBBASE_LOWIO_H

#include

/*
* Low-level I/O routines.
*/
static inline u_int8_t in_8(const volatile u_int8_t *addr)
{
u_int8_t ret;

__asm__ __volatile__("lbz%U1%X1 %0,%1; twi 0,%0,0; isync"
: "=r" (ret) : "m" (*addr));
return ret;
}

static inline void out_8(volatile u_int8_t *addr, u_int8_t val)
{
__asm__ __volatile__("stb%U0%X0 %1,%0; sync"
: "=m" (*addr) : "r" (val));
}

static inline u_int16_t in_le16(const volatile u_int16_t *addr)
{
u_int16_t ret;

__asm__ __volatile__("lhbrx %0,0,%1; twi 0,%0,0; isync"
: "=r" (ret) : "r" (addr), "m" (*addr));

return ret;
}

static inline u_int16_t in_be16(const volatile u_int16_t *addr)
{
u_int16_t ret;

__asm__ __volatile__("lhz%U1%X1 %0,%1; twi 0,%0,0; isync"
: "=r" (ret) : "m" (*addr));
return ret;
}

static inline void out_le16(volatile u_int16_t *addr, u_int16_t val)
{
__asm__ __volatile__("sthbrx %1,0,%2; sync" : "=m" (*addr)
: "r" (val), "r" (addr));
}

static inline void out_be16(volatile u_int16_t *addr, u_int16_t val)
{
__asm__ __volatile__("sth%U0%X0 %1,%0; sync"
: "=m" (*addr) : "r" (val));
}

static inline u_int32_t in_le32(const volatile u_int32_t *addr)
{
u_int32_t ret;

__asm__ __volatile__("lwbrx %0,0,%1; twi 0,%0,0; isync"
: "=r" (ret) : "r" (addr), "m" (*addr));
return ret;
}

static inline u_int32_t in_be32(const volatile u_int32_t *addr)
{
u_int32_t ret;

__asm__ __volatile__("lwz%U1%X1 %0,%1; twi 0,%0,0; isync"
: "=r" (ret) : "m" (*addr));
return ret;
}

static inline void out_le32(volatile u_int32_t *addr, u_int32_t val)
{
__asm__ __volatile__("stwbrx %1,0,%2; sync" : "=m" (*addr)
: "r" (val), "r" (addr));
}

static inline void out_be32(volatile u_int32_t *addr, u_int32_t val)
{
__asm__ __volatile__("stw%U0%X0 %1,%0; sync"
: "=m" (*addr) : "r" (val));
}

static inline void sync(void)
{
asm volatile("sync" : : : "memory");
}

static inline void eieio(void)
{
asm volatile("eieio" : : : "memory");
}

#endif /* LIBBASE_LOWIO_H */

下面就可以枚举设备了,通过遍历所有bus/device/function,读 PCI 配置空间0x0寄存器四字节(即VendorID和DeviceID),如果是 0xFFFFFFFF 则该设备存在,反之打印之:
    ccsr_pci_cfg_addr_t pci_cfg_tmp;
u_int32_t data32;

printf("CCSRBAR: %08X\n", U_INT32_REG(CCSR_REG(CCSRBAR)));

/* pci devices enumeration */
pci_cfg_tmp.enable = 1;
pci_cfg_tmp.reserved1 = 0;
printf("PCI Devices:\n");
for (pci_cfg_tmp.id.data = 0;
pci_cfg_tmp.id.data < 0xFFFF;
++pci_cfg_tmp.id.data) {
pci_cfg_tmp.reg = 0;
out_be32(&U_INT32_REG(CCSR_REG(PCI_CFG_ADDR)), *(u_int32_t*)&pci_cfg_tmp);
data32 = in_le32(&U_INT32_REG(CCSR_REG(PCI_CFG_DATA)));
if (data32 != 0xFFFFFFFF) {
printf("%04X(%02X:%02X:%02X) -> DEV_VEN(%08X)\n",
pci_cfg_tmp.id.data,
pci_cfg_tmp.id.detail.bus,
pci_cfg_tmp.id.detail.device,
pci_cfg_tmp.id.detail.function,
data32
);
}
}

参考资料:
MPC8548ERM.pdf
PPC_Vers202_Book1_public.pdf
PPC_Vers202_Book2_public.pdf
PPC_Vers202_Book3_public.pdf
阅读(1945) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~