/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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, ®); 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, ®); 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, ®); 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; }