linux pcie 视频,Freesclae i.MX6 Linux PCIE驱动源码分析

本文详细解析了在i.MX6平台上,使用devm_ioremap进行PCIe控制器的初始化和寄存器配置过程。重点介绍了IOMUXC_GPR8和IOMUXC_GPR12寄存器的作用,以及如何通过内联函数imx_pcie_clrset进行位操作。内容涉及GPIO控制电源、时钟使能以及物理地址到内核空间的映射机制。
摘要由CSDN通过智能技术生成

这里用的devm_ioremap与ioremap很相似,唯一的区别引用一下这个网页上的回复http://www.spinics.net/lists/devicetree/msg07744.html的:In the PCIv3 driver, use devm_ioremap() instead of just ioremap(). when remapping the system controller in the PCIv3 driver, so the mapping will be automatically released on probe failure.

而这里dbi_base经过对platform-imx-pcie.c中的分析,访问的是[ PCIE_ARB_END_ADDR - SZ_16K, PCIE_ARB_END_ADDR]这一段

/* FIXME the field name should be aligned to RM */

imx_pcie_clrset(IOMUXC_GPR12_APP_LTSSM_ENABLE, 0 << 10, IOMUXC_GPR12);

/* configure constant input signal to the pcie ctrl and phy */

if (pdata->type_ep & 1)

/* EP */

imx_pcie_clrset(IOMUXC_GPR12_DEVICE_TYPE,

PCI_EXP_TYPE_ENDPOINT        << 12, IOMUXC_GPR12);

else

/* RC */

imx_pcie_clrset(IOMUXC_GPR12_DEVICE_TYPE,

PCI_EXP_TYPE_ROOT_PORT << 12, IOMUXC_GPR12);

imx_pcie_clrset(IOMUXC_GPR12_LOS_LEVEL, 9 << 4, IOMUXC_GPR12);

imx_pcie_clrset(IOMUXC_GPR8_TX_DEEMPH_GEN1, 0 << 0, IOMUXC_GPR8);

imx_pcie_clrset(IOMUXC_GPR8_TX_DEEMPH_GEN2_3P5DB, 0 << 6, IOMUXC_GPR8);

imx_pcie_clrset(IOMUXC_GPR8_TX_DEEMPH_GEN2_6DB, 20 << 12, IOMUXC_GPR8);

imx_pcie_clrset(IOMUXC_GPR8_TX_SWING_FULL, 127 << 18, IOMUXC_GPR8);

imx_pcie_clrset(IOMUXC_GPR8_TX_SWING_LOW, 127 << 25, IOMUXC_GPR8);

寄存器配置,其中对于PCIE的link成功与否比较关键的就是IOMUXC_GPR8和IOMUXC_GPR12,不过在reference manual中IOMUXC_GPR12的值已经被定死了,所以只能调节IOMUXC_GPR8了。

这里imx_pcie_clrset是一个内联函数,定义如下:

/* IMX PCIE GPR configure routines */

static inline void imx_pcie_clrset(u32 mask, u32 val, void __iomem *addr)

{

writel(((readl(addr) & ~mask) | (val & mask)), addr);

}

鉴于这里已经可以直接对地址进行直接读写,那么这块内存区域就已经被映射过了。找到IOMUXC_GPR8的定义,在arch/arm/mach-mx6/crm_regs.h文件中:

/* IOMUXC */

#define MXC_IOMUXC_BASE

MX6_IO_ADDRESS(MX6Q_IOMUXC_BASE_ADDR)

…………

#define IOMUXC_GPR8

(MXC_IOMUXC_BASE + 0x20)

这里MX6Q_IOMUXC_BASE_ADDR被定义在arch/arm/plat-mxc/include/mach/mx6.h中:

#define AIPS1_ARB_BASE_ADDR

0x02000000

………………

#define ATZ1_BASE_ADDR

AIPS1_ARB_BASE_ADDR

…………

#define AIPS1_OFF_BASE_ADDR

(ATZ1_BASE_ADDR + 0x80000)

…………

#define MX6Q_IOMUXC_BASE_ADDR

(AIPS1_OFF_BASE_ADDR + 0x60000)

最终的值也就是0x0200_0000+0x8_0000+0x6_0000 = 0x020E_0000,参考i.MX6Q reference manual可以找到IOMUXC寄存器范围:[020E_0000, 020E_3FFF] 这里和驱动相对应。

而MX6_IO_ADDRESS的定义在arch/arm/plat-mxc/include/mach/mx6.h中,定义如下的:

#define PERIPBASE_VIRT

0xF2000000

…………

#define MX6_IO_ADDRESS(x) (void __force __iomem *)((x) + PERIPBASE_VIRT)

基本上就是对基地址的一个偏移量。

注意:直接这样访问是无效的,首先必须要在MMU中建立页表映射到这段地址,即ioremap以后才可以从内核空间访问(这里能访问是因为这块地址之前肯定已经映射过了),只不过映射之后的关系是物理地址增加一个偏移量而已。

/* Enable the pwr, clks and so on */

imx_pcie_enable_controller(dev);

如注释所言,使能pcie的电源和时钟等,由于i.mx是由fuse100来供电的,因此需要通过GPIO的某个引脚来控制供电开关。这个函数很关键,下面简单介绍一下, 本身也不长。

/* Enable PCIE power */

gpio_request(pdata->pcie_pwr_en, "PCIE POWER_EN");

/* activate PCIE_PWR_EN */

gpio_direction_output(pdata->pcie_pwr_en, 1);

imx_pcie_clrset(IOMUXC_GPR1_TEST_POWERDOWN, 0 << 18, IOMUXC_GPR1);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值