Linux下SMI总线驱动

本文详细介绍了Linux下Cavium Octeon处理器的SMI总线控制器驱动程序,包括驱动的初始化、资源分配、内存映射、SMI接口的使能以及读写操作。同时,提供了用户层访问SMI总线设备如Marvell PHY芯片的示例代码,展示了如何通过ioctl调用驱动进行读写操作。
摘要由CSDN通过智能技术生成
LinuxSMI总线驱动

韩大卫@吉林师范大学


剖析某类总线接口的芯片在linux里用户层对其的调用办法,较快捷的办法是直接找到该总线控制器的驱动程序,从其提供的软件接口展开逐层向上推及。现跟大家分享一下linuxocteon 处理器的SMI总线控制器的驱动(其架构完全符合platform设备驱动的通过架构)。附录里有用户层访问SMI总线设备,如marvell PHY芯片88E11111340/1340S的源程序。
下面为cavium octeonSMI总线驱动源代码的大致内容:

drivers/net/phy/mdio-octeon.c

static int __init octeon_mdiobus_mod_init(void)
{
//octeon_mdiobus_driver 作为一个platform类型的driver 注册到内核
    return platform_driver_register(&octeon_mdiobus_driver);
}
module_init(octeon_mdiobus_mod_init);

static struct platform_driver octeon_mdiobus_driver = {                                                                
    .driver = {                             
        .name       = "mdio-octeon",        
        .owner      = THIS_MODULE,          
        .of_match_table = octeon_mdiobus_match,
    },                                      
    .probe      = octeon_mdiobus_probe,     
    .remove     = __exit_p(octeon_mdiobus_remove),
};

static int __init octeon_mdiobus_probe(struct platform_device *pdev)
{  
    struct octeon_mdiobus *bus;
    struct resource *res_mem;
  
    union cvmx_smix_en smi_en;
    int err = -ENOENT;
   
    //申请并初始化一段内存填充数据结构 struct octeon_mdiobus
    bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
    if (!bus)
        return -ENOMEM;
   
   /*获取IO内存资源的描述,这个资料描述是uboot通过读取解析并处理uboot里的dts文件后得到的,在linux启动后,便可通过platform_get_resource()来获取,成功获取后,后面会向内核申请使用这段IO内存,另外, dts文件关于IO地址等资料的描述是按照CPU datasheet上的信息来写的。
   */
    res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);

    if (res_mem == NULL) {
        dev_err(&pdev->dev, "found no memory resource\n");
        err = -ENXIO;
        goto fail_region;
    }

    /*通过res_mem来得到地址首地址和地址长度, 这个start 是我在ubootdts文件里描述的
“
smi0: mdio@1180000001800 {
            compatible = "cavium,octeon-3860-mdio";
            #address-cells = <1>;
            #size-cells = <0>;                                                               
            reg = <0x11800 0x00001800 0x0 0x40>;	
“
 首地址 0x1180000001800, 长度为0x40
    /*
    bus->mdio_phys = res_mem->start;
    bus->regsize = resource_size(res_mem);
/*bus->mdio_phys, regsize打印出来分别为: 0x1800 0x40 */

    //调用include/linux/ioport.h 里提供的API 向内核申请使用这段IO内存
    if (!devm_request_mem_region(&pdev->dev, bus->mdio_phys, bus->regsize,
                     res_mem->name)) {
        dev_err(&pdev->dev, "request_mem_region failed\n");
        goto fail_region;
    }

    //将这段IO内存映射为内存地址,此时的register_base即可被内核空间直接使用
    bus->register_base = (u64)ioremap(bus->mdio_phys, bus->regsize);

/*   bus->register_base 打印出来 为0x1800 ,但是这个地址是存在内存中的,上面的bus->mdio_phys0x1800是存在于IO内存中的*/

    //mdiobus_alloc()封装了kzalloc, 作用是申请一段大小为sizeof(struct mii_bus)的内存 
    bus->mii_bus = mdiobus_alloc()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值