1
0
mirror of https://github.com/physwizz/a155-U-u1.git synced 2025-10-18 01:15:33 +00:00
Files
physwizz 99537be4e2 first
2024-03-11 06:53:12 +11:00

288 lines
8.4 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2016 MediaTek Inc.
*/
#include <linux/list.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/kdev_t.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/sched/clock.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/fs.h>
#include <linux/netdevice.h>
#include <linux/random.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/syscore_ops.h>
#if defined(CONFIG_MTK_AEE_FEATURE)
#include <mt-plat/aee.h>
#endif
#include <linux/clk.h>
#include "ccci_config.h"
#include "ccci_common_config.h"
#include "ccci_core.h"
#ifndef CCCI_KMODULE_ENABLE
#include "modem_sys.h"
#endif
#include "ccci_bm.h"
#include "ccci_hif_cldma.h"
//#include "md_sys1_platform.h"
#include "cldma_reg.h"
#include "modem_reg_base.h"
#include "ccci_fsm.h"
#include "ccci_port.h"
#include "ccci_cldma_plat.h"
#include "ccci_platform.h"
#include "ccci_hif_cldma.h"
#define TAG "cldma"
void cldma_plat_hw_reset(unsigned char md_id)
{
unsigned int reg_value = 0;
int ret;
//struct ccci_modem *md = ccci_md_get_modem_by_id(md_id);
CCCI_NORMAL_LOG(md_id, TAG, "%s:rst cldma\n", __func__);
/* reset cldma hw: AO Domain */
ret = regmap_read(cldma_ctrl->plat_val.infra_ao_base,
INFRA_RST0_REG_AO, &reg_value);
if (ret) {
CCCI_ERROR_LOG(0, TAG, "read INFRA_RST0_REG_AO ret=%d\n", ret);
return;
}
reg_value &= ~(CLDMA_AO_RST_MASK); /* the bits in reg is WO, */
reg_value |= (CLDMA_AO_RST_MASK);/* so only this bit effective */
regmap_write(cldma_ctrl->plat_val.infra_ao_base,
INFRA_RST0_REG_AO, reg_value);
CCCI_BOOTUP_LOG(md_id, TAG, "%s:clear reset\n", __func__);
/* reset cldma clr */
ret = regmap_read(cldma_ctrl->plat_val.infra_ao_base,
INFRA_RST1_REG_AO, &reg_value);
if (ret) {
CCCI_ERROR_LOG(0, TAG, "read INFRA_RST1_REG_AO ret=%d\n", ret);
return;
}
reg_value &= ~(CLDMA_AO_RST_MASK);/* read no use, maybe a time delay */
reg_value |= (CLDMA_AO_RST_MASK);
regmap_write(cldma_ctrl->plat_val.infra_ao_base,
INFRA_RST1_REG_AO, reg_value);
CCCI_BOOTUP_LOG(md_id, TAG, "%s:done\n", __func__);
/* reset cldma hw: PD Domain */
ret = regmap_read(cldma_ctrl->plat_val.infra_ao_base,
INFRA_RST0_REG_PD, &reg_value);
if (ret) {
CCCI_ERROR_LOG(0, TAG, "read INFRA_RST0_REG_PD ret=%d\n", ret);
return;
}
reg_value &= ~(CLDMA_PD_RST_MASK);
reg_value |= (CLDMA_PD_RST_MASK);
regmap_write(cldma_ctrl->plat_val.infra_ao_base,
INFRA_RST0_REG_PD, reg_value);
CCCI_BOOTUP_LOG(md_id, TAG, "%s:clear reset\n", __func__);
/* reset cldma clr */
ret = regmap_read(cldma_ctrl->plat_val.infra_ao_base,
INFRA_RST1_REG_PD, &reg_value);
if (ret) {
CCCI_ERROR_LOG(0, TAG, "read INFRA_RST1_REG_PD ret=%d\n", ret);
return;
}
reg_value &= ~(CLDMA_PD_RST_MASK);
reg_value |= (CLDMA_PD_RST_MASK);
regmap_write(cldma_ctrl->plat_val.infra_ao_base,
INFRA_RST1_REG_PD, reg_value);
CCCI_DEBUG_LOG(md_id, TAG, "%s:done\n", __func__);
/* set cldma wakeup source mask */
ret = regmap_read(cldma_ctrl->plat_val.infra_ao_base,
INFRA_CLDMA_CTRL_REG, &reg_value);
if (ret) {
CCCI_ERROR_LOG(0, TAG, "read INFRA_CLDMA_CTRL_REG ret=%d\n", ret);
return;
}
reg_value |= (CLDMA_IP_BUSY_MASK);
regmap_write(cldma_ctrl->plat_val.infra_ao_base,
INFRA_CLDMA_CTRL_REG, reg_value);
CCCI_DEBUG_LOG(md_id, TAG, "set cldma ctrl reg as:0x%x\n", reg_value);
}
void cldma_plat_set_clk_cg(unsigned char md_id, unsigned int on)
{
int idx = 0;
int ret = 0;
CCCI_NORMAL_LOG(md_id, TAG, "%s: on=%d\n", __func__, on);
for (idx = 0; idx < CLDMA_CLOCK_COUNT; idx++) {
if (cldma_clk_table[idx].clk_ref == NULL)
continue;
if (on) {
ret = clk_prepare_enable(cldma_clk_table[idx].clk_ref);
if (ret)
CCCI_ERROR_LOG(md_id, TAG,
"%s: on=%d,ret=%d\n",
__func__, on, ret);
ccci_hif_set_devapc_flag(1);
} else {
ccci_hif_set_devapc_flag(0);
clk_disable_unprepare(cldma_clk_table[idx].clk_ref);
}
}
}
int cldma_plat_suspend(unsigned char md_id)
{
CCCI_NORMAL_LOG(md_id, TAG, "[%s]\n", __func__);
return 0;
}
void cldma_plat_resume(unsigned char md_id)
{
//struct md_sys1_info *md_info = (struct md_sys1_info *)md->private_data;
//enum MD_STATE md_state = ccci_fsm_get_md_state(md->index);
int i;
unsigned long flags;
unsigned int val = 0;
dma_addr_t bk_addr = 0;
CCCI_NORMAL_LOG(md_id, TAG, "%s\n", __func__);
// if (md_state == GATED ||
// md_state == WAITING_TO_STOP ||
// md_state == INVALID) {
// CCCI_NORMAL_LOG(md->index, TAG,
// "Resume no need reset cldma for md_state=%d\n"
// , md_state);
// return;
// }
if (cldma_ctrl->cldma_state != HIF_CLDMA_STATE_PWRON) {
CCCI_NORMAL_LOG(md_id, TAG,
"Resume no need reset cldma for md_state=%d\n",
cldma_ctrl->cldma_state);
return;
}
//cldma_write32(md_info->ap_ccif_base,
// APCCIF_CON, 0x01); /* arbitration */
if (cldma_read32(cldma_ctrl->cldma_ap_pdn_base, CLDMA_AP_TQSAR(0))
|| cldma_reg_get_4msb_val(cldma_ctrl->cldma_ap_ao_base,
CLDMA_AP_UL_START_ADDR_4MSB, cldma_ctrl->txq[0].index)) {
CCCI_NORMAL_LOG(md_id, TAG,
"Resume cldma pdn register: No need ...\n");
spin_lock_irqsave(&cldma_ctrl->cldma_timeout_lock, flags);
if (!(cldma_read32(cldma_ctrl->cldma_ap_ao_base,
CLDMA_AP_SO_STATUS))) {
cldma_write32(cldma_ctrl->cldma_ap_pdn_base,
CLDMA_AP_SO_RESUME_CMD,
CLDMA_BM_ALL_QUEUE & 0x1);
cldma_read32(cldma_ctrl->cldma_ap_pdn_base,
CLDMA_AP_SO_RESUME_CMD); /* dummy read */
} else
CCCI_NORMAL_LOG(md_id, TAG,
"Resume cldma ao register: No need ...\n");
spin_unlock_irqrestore(&cldma_ctrl->cldma_timeout_lock, flags);
} else {
CCCI_NORMAL_LOG(md_id, TAG,
"Resume cldma pdn register ...11\n");
spin_lock_irqsave(&cldma_ctrl->cldma_timeout_lock, flags);
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
/* re-config 8G mode flag for pd register*/
cldma_write32(cldma_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_CFG,
cldma_read32(cldma_ctrl->cldma_ap_pdn_base,
CLDMA_AP_UL_CFG) | 0x40);
#endif
cldma_write32(cldma_ctrl->cldma_ap_pdn_base,
CLDMA_AP_SO_RESUME_CMD, CLDMA_BM_ALL_QUEUE & 0x1);
cldma_read32(cldma_ctrl->cldma_ap_pdn_base,
CLDMA_AP_SO_RESUME_CMD); /* dummy read */
/* set start address */
for (i = 0; i < QUEUE_LEN(cldma_ctrl->txq); i++) {
if (cldma_read32(cldma_ctrl->cldma_ap_ao_base,
CLDMA_AP_TQCPBAK(cldma_ctrl->txq[i].index)) == 0
&& cldma_reg_get_4msb_val(
cldma_ctrl->cldma_ap_ao_base,
CLDMA_AP_UL_CURRENT_ADDR_BK_4MSB,
cldma_ctrl->txq[i].index) == 0) {
if (i != 7) /* Queue 7 not used currently */
CCCI_DEBUG_LOG(md_id, TAG,
"Resume CH(%d) current bak:== 0\n", i);
cldma_reg_set_tx_start_addr(
cldma_ctrl->cldma_ap_pdn_base,
cldma_ctrl->txq[i].index,
cldma_ctrl->txq[i].tr_done->gpd_addr);
cldma_reg_set_tx_start_addr_bk(
cldma_ctrl->cldma_ap_ao_base,
cldma_ctrl->txq[i].index,
cldma_ctrl->txq[i].tr_done->gpd_addr);
} else {
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
val = cldma_reg_get_4msb_val(
cldma_ctrl->cldma_ap_ao_base,
CLDMA_AP_UL_CURRENT_ADDR_BK_4MSB,
cldma_ctrl->txq[i].index);
/*set high bits*/
bk_addr = val;
bk_addr <<= 32;
#else
bk_addr = 0;
#endif
/*set low bits*/
val = cldma_read32(cldma_ctrl->cldma_ap_ao_base,
CLDMA_AP_TQCPBAK(cldma_ctrl->txq[i].index));
bk_addr |= val;
cldma_reg_set_tx_start_addr(
cldma_ctrl->cldma_ap_pdn_base,
cldma_ctrl->txq[i].index, bk_addr);
cldma_reg_set_tx_start_addr_bk(
cldma_ctrl->cldma_ap_ao_base,
cldma_ctrl->txq[i].index, bk_addr);
}
}
/* wait write done*/
wmb();
/* start all Tx and Rx queues */
cldma_ctrl->txq_started = 0;
cldma_ctrl->txq_active |= CLDMA_BM_ALL_QUEUE;
ccci_write32(cldma_ctrl->cldma_ap_pdn_base, CLDMA_AP_L2TIMCR0,
CLDMA_TX_INT_DONE |
CLDMA_TX_INT_QUEUE_EMPTY |
CLDMA_TX_INT_ERROR);
/* enable all L3 interrupts */
cldma_write32(cldma_ctrl->cldma_ap_pdn_base,
CLDMA_AP_L3TIMCR0, CLDMA_BM_INT_ALL);
cldma_write32(cldma_ctrl->cldma_ap_pdn_base,
CLDMA_AP_L3TIMCR1, CLDMA_BM_INT_ALL);
cldma_write32(cldma_ctrl->cldma_ap_pdn_base,
CLDMA_AP_L3RIMCR0, CLDMA_BM_INT_ALL);
cldma_write32(cldma_ctrl->cldma_ap_pdn_base,
CLDMA_AP_L3RIMCR1, CLDMA_BM_INT_ALL);
spin_unlock_irqrestore(&cldma_ctrl->cldma_timeout_lock, flags);
CCCI_NORMAL_LOG(md_id, TAG,
"Resume cldma pdn register done\n");
}
}