Files
BPI-CM9-Linux/aml-comp/hardware/bluetooth/amlogic/w2l/amlbt_utils.c
T

280 lines
7.3 KiB
C

/*
* Copyright (c) 202X Amlogic, Inc. All rights reserved.
*
* This source code is subject to the terms and conditions defined in the
* file 'LICENSE' which is part of this source code package.
*
* Description:
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/skbuff.h>
#include <linux/usb.h>
#include <linux/cdev.h>
#include <linux/ioctl.h>
#include <linux/io.h>
#include <linux/compat.h>
#include <linux/firmware.h>
#include <linux/vmalloc.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/reboot.h>
#include <linux/time.h>
#include <linux/ktime.h>
#include <linux/kthread.h>
#include <linux/semaphore.h>
#include <linux/poll.h>
#include <linux/platform_device.h>
#include <linux/hrtimer.h>
#include <linux/wait.h>
#include <linux/spinlock.h>
#include <linux/amlogic/pm.h>
#include <linux/firmware.h>
#include <linux/jiffies.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/input.h>
#include "common.h"
#include "intf.h"
#include "amlbt_utils.h"
#define TIMER_INTERVAL_MS 10000 // 定时器触发间隔 (10s)
#define W2L_USB_UTILS_SENSOR_PRINT_INTERVAL 30 //5 min
#define W2L_DF_REG_A188 (0x00f062f0)
#define W2L_TS_CFG_REG1 (0x00a04904)
#define W2L_TS_STAT0 (0x00a04940)
#define W2L_USB_TEMP_SENSOR_THRES_HOLE (0x1c50)
typedef union TS_CFG_REG1_FIELD
{
unsigned int data;
struct
{
unsigned int REG_CH_SEL : 3;
unsigned int REG_DEM_EN : 1;
unsigned int REG_EN_IPTAT_GPIO : 1;
unsigned int REG_ENABLE : 1;
unsigned int REG_TS_OUT_CTRL : 1;
unsigned int REG_HCIC_MODE : 2;
unsigned int REG_TS_EN_VBG : 1;
unsigned int REG_TS_EN_VCM : 1;
unsigned int REG_TS_RESET_SD : 1;
unsigned int REG_TS_RESET_VBG : 1;
unsigned int CLR_HI_TEMP_STAT : 1;
unsigned int FAST_MODE : 1;
unsigned int TS_IRQ_EN : 1;
unsigned int CLR_IRQ : 8;
unsigned int irq_mask : 8;
}b;
}TS_CFG_REG1_FIELD_T;
typedef union TS_STAT0_FIELD
{
unsigned int data;
struct
{
unsigned int yout_d2 : 16;
unsigned int yvalid_d2 : 1;
unsigned int detected_hi_temp_r : 1;
unsigned int detect_hi_temp_cnt : 14;
}b;
}TS_STAT0_FIELD_T;
static w2l_usb_utils_bt_t w2l_utils = {0};
static unsigned int amlbt_utils_w2l_usb_is_wifi_alive(w2l_usb_utils_bt_t *p_utils)
{
int ret = 0;
unsigned int reg = 0;
ret = p_utils->read_word(W2L_DF_REG_A188, USB_EP2, &reg);
if (ret != 0)
{
BTE("%s:%d Failed : %d\n", __func__, __LINE__, ret);
return 1;
}
if (p_utils->print_cnt >= W2L_USB_UTILS_SENSOR_PRINT_INTERVAL)
{
BTI("wifi status:%#x\n", reg);
}
if ((reg & BIT(30) || reg & BIT(31)))
{
//BTI("wifi alive\n");
return 1;
}
else
{
//BTI("wifi not alive:%#x\n", reg);
return 0;
}
}
static enum hrtimer_restart amlbt_utils_w2l_usb_timer_callback(struct hrtimer *timer)
{
w2l_usb_utils_bt_t *p_utils = &w2l_utils;
amlbt_intf_queue_work(p_utils->wq, &p_utils->work);
hrtimer_forward_now(timer, ms_to_ktime(TIMER_INTERVAL_MS));
return HRTIMER_RESTART;
}
static unsigned int amlbt_utils_w2l_usb_sensor_get_temperature(w2l_usb_utils_bt_t *p_utils)
{
int ret = 0;
unsigned int reg = 0;
ret = p_utils->read_word(W2L_TS_STAT0, USB_EP2, &reg);
if (ret != 0)
{
BTE("%s:%d Failed : %d\n", __func__, __LINE__, ret);
return 0;
}
if (p_utils->print_cnt >= W2L_USB_UTILS_SENSOR_PRINT_INTERVAL)
{
BTI("W2L_TS_STAT0:%#x\n", reg);
}
if ((reg & 0xffff) < W2L_USB_TEMP_SENSOR_THRES_HOLE)
{
return 0;
}
return 1;
}
static void amlbt_utils_w2l_usb_work_handler(struct work_struct *work)
{
int ret = 0;
unsigned int reg = 0;
w2l_usb_utils_bt_t *p_utils = &w2l_utils;
p_utils->print_cnt++;
if (!amlbt_utils_w2l_usb_is_wifi_alive(p_utils))
{
ret = p_utils->read_word(RG_AON_A61, USB_EP2, &reg);
if (ret != 0)
{
BTE("%s:%d Failed : %d\n", __func__, __LINE__, ret);
p_utils->print_cnt = 0;
return ;
}
if (amlbt_utils_w2l_usb_sensor_get_temperature(p_utils))
{
reg |= (1 << 0);
}
else
{
reg &= ~(1 << 0);
}
ret = p_utils->write_word(RG_AON_A61, reg, USB_EP2);
if (ret != 0)
{
BTE("%s:%d Failed : %d\n", __func__, __LINE__, ret);
p_utils->print_cnt = 0;
return ;
}
}
if (p_utils->print_cnt >= W2L_USB_UTILS_SENSOR_PRINT_INTERVAL)
{
p_utils->print_cnt = 0;
}
}
static int amlbt_utils_w2l_usb_temp_sensor_cfg(w2l_usb_utils_bt_t *p_utils)
{
int ret = 0;
TS_CFG_REG1_FIELD_T ts_cfg_reg1;
ret = p_utils->read_word(W2L_TS_CFG_REG1, USB_EP2, &ts_cfg_reg1.data);
if (ret != 0)
{
BTE("%s:%d Failed : %d\n", __func__, __LINE__, ret);
return -1;
}
ts_cfg_reg1.b.REG_CH_SEL = 3;
ts_cfg_reg1.b.REG_DEM_EN = 1;
ts_cfg_reg1.b.REG_ENABLE = 1;
ts_cfg_reg1.b.REG_TS_OUT_CTRL = 1;
ts_cfg_reg1.b.REG_HCIC_MODE = 1;
ts_cfg_reg1.b.REG_TS_EN_VBG = 1;
ts_cfg_reg1.b.REG_TS_EN_VCM = 1;
ret = p_utils->write_word(W2L_TS_CFG_REG1, ts_cfg_reg1.data, USB_EP2);
if (ret != 0)
{
BTE("%s:%d Failed : %d\n", __func__, __LINE__, ret);
return -1;
}
return 0;
}
void amlbt_utils_w2l_usb_init(
int (*read_word)(unsigned int addr, unsigned int ep, unsigned int *value),
int (*write_word)(unsigned int addr,unsigned int data, unsigned int ep),
int (*write_sram)(unsigned char *buf, unsigned char *sram_addr, unsigned int len, unsigned int ep),
int (*read_sram)(unsigned char *buf,unsigned char *sram_addr, unsigned int len, unsigned int ep))
{
w2l_usb_utils_bt_t *p_utils = &w2l_utils;
BTI("%s\n", __func__);
p_utils->read_word = read_word;
p_utils->write_word = write_word;
p_utils->write_sram = write_sram;
p_utils->read_sram = read_sram;
p_utils->print_cnt = 0;
if (0 != amlbt_utils_w2l_usb_temp_sensor_cfg(p_utils))
{
BTE("%s failed!!\n", __func__);
return ;
}
p_utils->wq = create_singlethread_workqueue("w2l_usb_utils_workqueue");
if (!p_utils->wq)
{
BTE("%s:%d Failed\n", __func__, __LINE__);
return ;
}
INIT_WORK(&p_utils->work, amlbt_utils_w2l_usb_work_handler);
hrtimer_init(&p_utils->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
p_utils->hrtimer.function = amlbt_utils_w2l_usb_timer_callback;
hrtimer_start(&p_utils->hrtimer, ms_to_ktime(TIMER_INTERVAL_MS), HRTIMER_MODE_REL);
p_utils->utils_start = 1;
}
void amlbt_utils_w2l_usb_deinit(void)
{
w2l_usb_utils_bt_t *p_utils = &w2l_utils;
BTI("%s, utils_start:%d\n", __func__, p_utils->utils_start);
if (p_utils->utils_start)
{
hrtimer_cancel(&p_utils->hrtimer);
amlbt_intf_flush_workqueue(p_utils->wq, &p_utils->work);
destroy_workqueue(p_utils->wq);
p_utils->wq = NULL;
p_utils->utils_start = 0;
}
p_utils->print_cnt = 0;
}