高通WLAN芯片点灯方法-QCA9563操控9880GPIO进行点灯

概述

最近在调试高通9563芯片的GPIO点灯,因为主控芯片GPIO口比较紧缺。所以就把9563出的wan口和lan口的灯交给了9880的GPIO口控制。

OpenWrt点灯套路

Linux内核集成LED模块,很方便就可以完成灯的控制,下面简单回顾下通常GPIO口点灯的几个步骤。

  1. 选中内核gpio点灯驱动,一般驱动名为leds-gpio(/sys/bus/platform/drivers/leds-gpio)。
  2. 如果是MIPS架构需要自己手动注册设备,信息自己携带在gpio_led_platform_data结构体中,同时可注册多个LED设备,最终呈现在sys fs文件系统下(/sys/devices/platform/leds-gpio/leds/LAN1:green:led)。
  3. 以上只是提供一个可操作的设备,具体怎么关联到系统当中,并且随着端口的link状态自动亮灭。这就需要结合LED模块提供的另外一个属性,LED触发模式。这个可以在注册设备时进行配置,也可在系统起来时进行脚本配置(root@mexon:/sys/devices/pci0000:00/0000:00:00.0/leds/LED0# cat trigger
    none [switch0] timer default-on netdev usbport phy0rx phy0tx phy0assoc phy0radio phy0tpt phy1rx phy1tx phy1assoc phy1radio phy1tpt)。
  4. 例如在OpenWrt中,有自动化配置脚本控制LED设备,进行触发模式选择。在openwrt/target/linux/ar71xx/base-files/etc/board.d/01_leds中配置switch芯片出的端口link状态。
    ucidef_set_led_switch “wan” “WAN” “LED3”(注册的led设备) “switch0”(触发器名称)“0x02”(端口掩码)
    此处如果有多个LED设备,可持续配置。
    MPP6600)
    	ucidef_set_led_switch "wan"  "WAN" "LED3" "switch0" "0x02"
    	ucidef_set_led_switch "lan1" "LAN1" "LED2" "switch0" "0x04"
    	ucidef_set_led_switch "lan2" "LAN2" "LED1" "switch0" "0x08"
    	ucidef_set_led_switch "lan3" "LAN3" "LED0" "switch0" "0x10"
    	ucidef_set_led_timer "run" "RUN" "MPP6600:green:run" "1000" "1000"
    	#ucidef_set_led_wlan "wlan2g" "WLAN 2.4 GHz" "MPP6600:green:2G" "phy1tpt"
    

9880控制8337端口的led灯

简单介绍

控制芯片为9563,通过GMAC接口连接高通的8337switch芯片,该芯片可配置单wan口或多wan口,其余均做lan口(软件通过swconfig进行vlan隔离即可)。由于9563上的GPIO口有限,9880又支持可配置的GPIO口。所以我们的8337link就采用9880GPIO口控制方式。

QCA9880驱动

采用开源 ath10k,内核选中即可。
ath10kled支持
这个地方选中Enable LED support是支持9880wifi状态灯的控制,这个灯是系统默认wifi状态点灯。并且ath10k驱动也仅仅支持这一个GPIO的控制,默认是9880上的GPIO1。接下来就是要在这里做手脚,进行代码改造。

QCA9880控灯驱动程序

  1. ath10k在进行核心初始化时,会注册led设备。
    ath10k_leds_register-默认注册一个wifi灯,此处进行扩展,扩展结构体如下:

    struct {
    		struct gpio_led wifi_led;
    		struct led_classdev cdev;
    		char label[48];
    		u32 gpio_state_pin;
    	} leds[10];
    

    然后循环调用led_classdev_register注册函数,把所需要操作的所有GPIO口都以LED设备的方式注册进去。

  2. 9880GPIO口配置
    使能对应的GPIO口以及配置GPIO口的方向。ath10k_wmi_gpio_config、ath10k_wmi_gpio_output。

  3. 需要关注下,对应的GPIO口是否被占用,有很多芯片GPIO口都是可复用的,芯片复位后有时会作其它功能(比如JTag)。

    /* 使能GPIO口 */
    for(i = 0; i < 5; ++ i)
    {
       ath10k_wmi_gpio_config(ar, ar->leds[i].wifi_led.gpio, 0,
           WMI_GPIO_PULL_NONE, WMI_GPIO_INTTYPE_DISABLE);
       ath10k_wmi_gpio_output(ar, ar->leds[i].wifi_led.gpio, 1);
    }
    /* 关掉GPIO口复用 */
    if(ar->hif.ops != NULL && ar->hif.ops->read32 != NULL)
    {
       val = ar->hif.ops->read32(ar, GPIO_BASE_ADDRESS + 0xb0);
       val |= 1;
       if(ar->hif.ops->write32 != NULL)
           ar->hif.ops->write32(ar, GPIO_BASE_ADDRESS + 0xb0, val);
    }
    return 0;
    
  4. 在注册设备的时候,会同时传递一个回调函数,做LED灯亮度调整用的。在这个回调函数中,需要重新解析GPIO口,因为之前这个地方仅仅控制一个GPIO口,现在要操作多个GPIO口。这里可以通过设备名称获取GPIO口的端口号。

    /* 只要是解析出当前的GPIO口号,然后去具体设置某个GPIO口 */
    int i = 0;
    if(!strcmp(led_cdev->name, "LED0"))
    {
        i = 1;
    }
    else if(!strcmp(led_cdev->name, "LED1"))
    {
        i = 2;
    }
    else if(!strcmp(led_cdev->name, "LED2"))
    {
        i = 3;
    }
    else if(!strcmp(led_cdev->name, "LED3"))
    {
        i = 4;
    }
    else
    {
        i = 0;
    }
    

    最后根据解析出来的端口号,可对GPIO的输出做控制。

    struct ath10k *ar = container_of(led_cdev, struct ath10k,leds[i].cdev);
    struct gpio_led *led = &ar->leds[i].wifi_led;
    ar->leds[i].gpio_state_pin = (brightness != LED_OFF) ^ led->active_low;
    ath10k_wmi_gpio_output(ar, led->gpio, ar->leds[i].gpio_state_pin);
    
  5. 由于OpenWrt编译机制,不能直接修改build_dir下代码,否则clean之后修改部分会丢失。这里有两种方法,一是解压dl下backports大包,修改源码之后再压缩,然后修改 Makefile下的校验码即可,二是打补丁,网上有很多教程,而且方便快捷,无需修改源码。

回顾

该部分内容主要掌握Linux LED设备操作及结合OpenWrt脚本配置即可。其中涉及的知识比较多,但是还是比较浅显,需要自己去深入学习。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值