SPRD平台功耗调试分享

一、 return 0;
}
static int sci_keypad_resume(struct platform_device *pdev)
{
keypad_writel(KPD_INT_EN, KPD_INT_ALL);
return 0;
}
请在按键中断驱动中,做以下修改
suspend时,将KPD_INT_EN寄存器清o
resume时,执行probe里面enable动作。
下面是参考代码
{
value = KPD_INT_DOWNUP;

keypad_writel(KPD_INT_EN, value);
}

查看用户空间进程是否有活动的wake_lock使用adb shell登陆到手机的控制台 查看/sys/power/wake_lock 节点看是否有活动的 wake_lock  cat /sys/power/wake_lock 如果输出不为空则表示当前有应用申请了wake_lock比较常见的应用是PowerManagerService,java应用都是通过该服务来获得wake_lock。
通过logcat抓取的log可以查看相应的哪些应用通过PowerManagerService申请wake_lock

查看内核空间是否有活动的 wake_lock 需要将kernel/power路径下的wakelock.c文件中的打印消息的mask中加上DEBUG_WAKE_LOCK,这样, 内核如果有内核模块申请或释放wake_lock都会打印出来,通过打印就可以看出是那个模块申请了wake_lock
另外,内核中的可以通过看/proc/wakelocks,有哪些wakelock锁。
在kernel/kernel/power/wakelock.c中添加如下函数,那么在/proc/wakelocks下就能看到有哪些wakelock锁,这样看起来会比较清晰。

bool print_expired = true;
unsigned int ret = 0;
 
BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
seq_printf(m,”n*************************  ACTIVE WAKE LOCKS:  *************************n”);
list_for_each_entry(lock, &active_wake_locks[type], link) {

long timeout = lock->expires – jiffies;
if (timeout > 0)
ret += seq_printf(m,”active wake lock %s, time left %ldn”,lock->name, timeout);
else if (print_expired)
ret += seq_printf(m,”wake lock %s, expiredn”, lock->name);
} else {
ret += seq_printf(m,”active wake lock %sn”, lock->name);
if (!(debug_mask & DEBUG_EXPIRE))
print_expired = false;
}
}
return ret;
}
这个函数是在原有函数的基础上添加的,需要在如下函数中添加调用它。

struct wake_lock *lock;
int ret;
int type;
 
spin_lock_irqsave(&list_lock, irqflags);
 
ret = seq_puts(m, “nametcounttexpire_counttwake_counttactive_since”
“ttotal_timetsleep_timetmax_timetlast_changen”);
list_for_each_entry(lock, &inactive_locks, link)
ret = print_lock_stat(m, lock);
for (type = 0; type
list_for_each_entry(lock, &active_wake_locks[type], link)
ret = print_lock_stat(m, lock);
}
    
print_active_locks_sprd(m, WAKE_LOCK_SUSPEND);
spin_unlock_irqrestore(&list_lock, irqflags);
return 0;
}
通过抓取的kernel的log可以查看相应的哪些驱动申请了wake_lock

开机电流过大

关机电流过大

{REG_PIN_CLK_REQ1,            BITS_PIN_DS(1)|BITS_PIN_AF(3)|BIT_PIN_WPD|BIT_PIN_SLP_WPD|BIT_PIN_SLP_Z},
{REG_PIN_CLK_REQ2,            BITS_PIN_DS(1)|BITS_PIN_AF(3)|BIT_PIN_WPD|BIT_PIN_SLP_WPD|BIT_PIN_SLP_Z},

    Linux使用标准的regulator子系统来管理LDO,展讯平台也是基于regulator子系统实现了该部分代码。
    设备睡眠时关于LDO的状态。我们知道,有些LDO我们希望睡眠时关闭,相反有些LDO我们希望睡眠是打开。但是我们在写驱动时却不太关注这部分。因此,可能默认的配置影响了功耗。
这部分的例子,最常见于WIFI的调试。
在打开WIFI时,系统可以睡眠,WIFI当然不能睡眠,它还得唤醒系统。可是有时候,我们默认配置却不小心将其关闭了。最近在调试8825C1的GPS就遇到了这个问题。
 
8825 LDO睡眠设置,相关寄存器定义如下:
arch/arm/mach-sc8825/include/mach/regs_ana_glb.h
#define ANA_REG_GLB_LDO_SLP_CTRL0       SCI_ADDR(ANA_REGS_GLB_BASE, 0x030)
#define ANA_REG_GLB_LDO_SLP_CTRL1       SCI_ADDR(ANA_REGS_GLB_BASE, 0x034)
#define ANA_REG_GLB_LDO_SLP_CTRL2       SCI_ADDR(ANA_REGS_GLB_BASE, 0x038)
#define ANA_REG_GLB_LDO_SLP_CTRL3       SCI_ADDR(ANA_REGS_GLB_BASE, 0x03c)

unsigned int val;

/*
* FIXME, should be more gental
*/
val = sci_adi_read(ANA_REG_GLB_LDO_SLP_CTRL0);
val = 0xc7f1;
sci_adi_write(ANA_REG_GLB_LDO_SLP_CTRL0, val, 0xffff);
 
val = sci_adi_read(ANA_REG_GLB_LDO_SLP_CTRL1);
val |= BIT_FSM_SLPPD_EN;
val |= BIT_DCDC_ARM_BP_EN;
sci_adi_write(ANA_REG_GLB_LDO_SLP_CTRL1, val, 0xffff);

sci_adi_write(ANA_REG_GLB_LDO_SLP_CTRL2, val, 0xffff);
/*
* set ARM_DCDC_DLY_NUM, DLY_NUM:0x2
*/
sci_adi_write(ANA_REG_GLB_LDO_SLP_CTRL3, 0x2, 0xffff);
}
我们可以简单的修改pm_ana_ldo_config的value来改变LDO_SLP_CTRLX
ref code:
arch/arm/mach-sc8825/include/mach/__regulator_map.h
arch/arm/mach-sc8825/include/mach/regs_ana_glb.h
 
当然有一种更为合理的办法是使用函数控制,所有关于LDO睡眠时下电或不下电的配置都可以使用这种方式。
REGULATOR_MODE_NORMAL    // 睡眠下电
REGULATOR_MODE_STANDBY   // 睡眠保持供电

        …
        err = regulator_set_voltage(regulator_wifi_bt, 1800000, 1800000);
        …
        regulator_set_mode(regulator_gps, REGULATOR_MODE_STANDBY);
        regulator_enable(regulator_gps);

int gpio_request(unsigned gpio, const char *label) 该API是使用GPIO必须的第一步, gpio是gpio number,gpio number为新片spec上定义的gpio number, label为该gpio的说明,例如backlight。 
void gpio_free(unsigned gpio) 使用完gpio后释放该gpio。 

int gpio_direction_input(unsigned gpio) 配置gpio为输入。 
int gpio_direction_output(unsigned gpio, int value) 配置gpio为输出,value为输出的电平,1为高,0为低 

int gpio_get_value(unsigned gpio) 判断GPIO输入的电平高低,两点需要注意: 1,只对输入GPIO,不能对输出GPIO的电平进行判断。 2,返回的非零值为高电平,0为低电平。 
void gpio_set_value(unsigned gpio, int value) 设置输出GPIO的电平高低, 1为高,0为低。不能对输入GPIO进行设置。其它高级用法请参考driver/gpio/gpiolib.c. 

如 mount上debugfs,可以cat gpio查看使用的gpio情况。 
#mount –t debugfs /d
#cat /d/gpio/

    service logs4android /system/bin/logwrapper /system/xbin/logs4android.sh   disabled   service logs4modem /system/bin/logwrapper /system/xbin/logs4modem.sh   disabled
(3)adb shell setprop logs4android.enable 0

3. BT不睡眠导致底电流偏大
老版本W13.20.5待机底电流1.8mA,移植到W13.25后底电流增大到2.2mA, 新版本上硬件工作正常,外围器件的驱动GPIO口等都已经移植
(1)对比W13.20和W13.25两个log,都有正常睡眠动作,睡眠前ldo等寄存器的值都一致,所以初步定位问题是有外设漏电的情况, 进一步需要软件上和硬件上去除基本外设,相应的外设的输出功能的管脚pinmap配置需要配成输出高阻。定位问题是蓝牙没有睡眠, 型 为BK3512
(2)追踪W13.20和W13.25两个log,发现在都不开启BT的情况下,W13.25的代码在唤醒时会调用BT的唤醒函数,如下:

D/BluetoothAdapterStateMachine(  257): Bluetooth state 12 -> 13
D/BluetoothAdapterStateMachine(  257): Switching process message: 54
D/BluetoothAdapterStateMachine(  257): Bluetooth state 13 -> 10 客户机器打开蓝牙:D/BluetoothAdapterStateMachine(  257): HotOff process message: 1             D/BluetoothAdapterStateMachine(  257): Bluetooth state 10 -> 11
D/BluetoothAdapterStateMachine(  257): Switching process message: 54
D/BluetoothAdapterStateMachine(  257): Switching process message: 53
D/BluetoothAdapterStateMachine(  257): Bluetooth state 11 -> 12
样机关闭蓝牙:

D/BluetoothAdapterStateMachine(  262): HotOff process message: 101
D/BluetoothAdapterStateMachine(  262): Switching process message: 54
D/BluetoothAdapterStateMachine(  262): Switching process message: 53
D/BluetoothAdapterStateMachine(  262): Bluetooth state 11 -> 12
上面代码反映了BT的状态机BluetoothAdapterStateMachine在BluetoothOn-Switching-WarmUp-HotOff-PowerOff五种状态之间转换的流程 对比样机发现客户机器缺少了PowerOff状态,而该状态对于BK3512这款BT来说才是真正进入低功耗状态,正因为这个原因导致客户机器睡眠时BT没有 完全关掉原因。

解决办法: 是否有PowerOff状态是由变量config_bluetooth_adapter_quick_switch决定的,该值定义在 devicesprdxxxoverlayframeworksbasecoreresresvaluesconfig.xml
总结: 对于不同的wifi,BluetoothAdapterStateMachine具有的状态不一样,例如BRCM的wifi只需要BluetoothOn-Switching-WarmUp-HotOff四种状态 而BK3512这款wifi就还需要PowerOff这种状态。





声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2015年3月19日
下一篇 2015年3月19日

相关推荐