[Feature] add GA346 baseline version
Change-Id: Ic62933698569507dcf98240cdf5d9931ae34348f
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/Makefile b/src/kernel/modules/connectivity/2.0/gps_driver/Makefile
new file mode 100644
index 0000000..5819520
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/Makefile
@@ -0,0 +1,187 @@
+# drivers/barcelona/gps/Makefile
+#
+# Makefile for the Barcelona GPS driver.
+#
+# Copyright (C) 2004,2005 TomTom BV <http://www.tomtom.com/>
+# Author: Dimitry Andric <dimitry.andric@tomtom.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+
+###############################################################################
+# Necessary Check
+
+#ifeq ($(AUTOCONF_H),)
+# $(error AUTOCONF_H is not defined)
+#endif
+
+#ccflags-y += -imacros $(AUTOCONF_H)
+
+ifeq ($(TARGET_BUILD_VARIANT),$(filter $(TARGET_BUILD_VARIANT),userdebug user))
+ ldflags-y += -s
+endif
+
+# Force build fail on modpost warning
+KBUILD_MODPOST_FAIL_ON_WARNINGS := y
+###############################################################################
+
+# only WMT align this design flow, but gps use this also.
+#ccflags-y += -D MTK_WCN_REMOVE_KERNEL_MODULE
+
+ifeq ($(CONFIG_ARM64), y)
+ ccflags-y += -D CONFIG_MTK_WCN_ARM64
+endif
+
+ifeq ($(CONFIG_MTK_CONN_LTE_IDC_SUPPORT),y)
+ ccflags-y += -D WMT_IDC_SUPPORT=1
+else
+ ccflags-y += -D WMT_IDC_SUPPORT=0
+endif
+ccflags-y += -D MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT
+MTK_PLATFORM :=mt6880
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/include
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/mach
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/freqhopping
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/freqhopping/$(MTK_PLATFORM)
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/submodule
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/$(MTK_PLATFORM)
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/connectivity/common
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/mach/$(MTK_PLATFORM)/include/mach
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM)
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/clkbuf_v1
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/clkbuf_v1/$(MTK_PLATFORM)
+ccflags-y += -I$(srctree)/drivers/devfreq
+###############################################################################
+
+MODULE_NAME := gps_drv
+obj-m += $(MODULE_NAME).o
+
+SELECT_GPS_DL_DRV := y
+GPS_DL_HAS_MOCK := n
+GPS_DL_HAS_CONNINFRA_DRV := y
+
+ifeq ($(CONFIG_MACH_MT6885),y)
+SELECT_GPS_DL_DRV := y
+ccflags-y += -I$(DRIVER_DIR)/data_link/hw/inc/connac2_0
+ccflags-y += -I$(DRIVER_DIR)/data_link/hw/inc/connac2_0/coda_gen
+ifeq ($(CONFIG_MTK_COMBO_CHIP_CONSYS_6885),y)
+GPS_DL_HAS_CONNINFRA_DRV := y
+endif
+endif
+
+ifeq ($(SELECT_GPS_DL_DRV),y) # New GPS driver with L1+L5 support
+ifeq ($(GPS_DL_HAS_CONNINFRA_DRV),y)
+ccflags-y += -I$(CONNINFRA_INC_FOLDER)
+ccflags-y += -DGPS_DL_HAS_CONNINFRA_DRV=1
+endif
+
+ccflags-y += -I$(DRIVER_DIR)/data_link/inc
+ccflags-y += -I$(DRIVER_DIR)/data_link/linux/inc
+ccflags-y += -I$(DRIVER_DIR)/data_link/link/inc
+ccflags-y += -I$(DRIVER_DIR)/data_link/lib/inc
+ccflags-y += -I$(DRIVER_DIR)/data_link/hal/inc
+ccflags-y += -I$(DRIVER_DIR)/data_link/hw/inc
+ccflags-y += -I$(DRIVER_DIR)/data_link_mock/mock/inc
+
+ccflags-y += -I$(DRIVER_DIR)/data_link/hw/inc/mt6880
+ccflags-y += -I$(DRIVER_DIR)/data_link/hw/inc/mt6880/coda_gen
+ccflags-y += -I$(DRIVER_DIR)/data_link_mock/mock/inc
+ccflags-y += -DGPS_DL_HAS_CONNINFRA_DRV=1
+
+
+
+$(MODULE_NAME)-objs += gps_dl_module.o
+$(MODULE_NAME)-objs += data_link/gps_dl_context.o
+
+$(MODULE_NAME)-objs += data_link/lib/gps_dl_dma_buf.o
+$(MODULE_NAME)-objs += data_link/lib/gps_dl_lib_misc.o
+$(MODULE_NAME)-objs += data_link/lib/gps_dl_hist_rec.o
+$(MODULE_NAME)-objs += data_link/lib/gps_dl_time_tick.o
+$(MODULE_NAME)-objs += data_link/lib/gps_dl_name_list.o
+
+$(MODULE_NAME)-objs += data_link/hw/gps_dl_hw_conn_infra.o
+$(MODULE_NAME)-objs += data_link/hw/gps_dl_hw_bgf.o
+$(MODULE_NAME)-objs += data_link/hw/gps_dl_hw_gps.o
+$(MODULE_NAME)-objs += data_link/hw/gps_dl_hw_power_ctrl.o
+$(MODULE_NAME)-objs += data_link/hw/gps_dl_hw_usrt_apb.o
+$(MODULE_NAME)-objs += data_link/hw/gps_dl_hw_util.o
+
+$(MODULE_NAME)-objs += data_link/hal/gps_dl_hal.o
+$(MODULE_NAME)-objs += data_link/hal/gps_dl_hal_util.o
+$(MODULE_NAME)-objs += data_link/hal/gps_dsp_fsm.o
+$(MODULE_NAME)-objs += data_link/hal/gps_dl_power_ctrl.o
+$(MODULE_NAME)-objs += data_link/hal/gps_dl_isr.o
+$(MODULE_NAME)-objs += data_link/hal/gps_dl_dma.o
+$(MODULE_NAME)-objs += data_link/hal/gps_dl_mcub.o
+$(MODULE_NAME)-objs += data_link/hal/gps_dl_zbus.o
+$(MODULE_NAME)-objs += data_link/hal/gps_dl_conn_infra.o
+
+$(MODULE_NAME)-objs += data_link/link/gps_dl_subsys_reset.o
+$(MODULE_NAME)-objs += data_link/gps_each_link.o
+
+$(MODULE_NAME)-objs += data_link/linux/gps_data_link_devices.o
+$(MODULE_NAME)-objs += data_link/linux/gps_each_device.o
+$(MODULE_NAME)-objs += data_link/linux/gps_dl_linux.o
+$(MODULE_NAME)-objs += data_link/linux/gps_dl_linux_plat_drv.o
+$(MODULE_NAME)-objs += data_link/linux/gps_dl_linux_reserved_mem.o
+$(MODULE_NAME)-objs += data_link/linux/gps_dl_emi.o
+$(MODULE_NAME)-objs += data_link/linux/gps_dl_ctrld.o
+$(MODULE_NAME)-objs += data_link/linux/gps_dl_procfs.o
+$(MODULE_NAME)-objs += data_link/linux/gps_dl_osal.o
+
+ifeq ($(GPS_DL_HAS_MOCK),y)
+$(MODULE_NAME)-objs += data_link_mock/mock/gps_mock_mvcd.o
+$(MODULE_NAME)-objs += data_link_mock/mock/gps_mock_hal.o
+ccflags-y += -DGPS_DL_HAS_MOCK=1
+endif
+
+else #Legacy drivers
+WMT_SRC_FOLDER := $(TOP)/src/kernel/modules/connectivity/wmt_mt66xx
+
+ifeq ($(CONFIG_MTK_COMBO_CHIP),)
+ $(error CONFIG_MTK_COMBO_CHIP not defined)
+endif
+
+ifneq ($(filter "CONSYS_%",$(CONFIG_MTK_COMBO_CHIP)),)
+ ccflags-y += -DSOC_CO_CLOCK_FLAG=1
+ ccflags-y += -DWMT_CREATE_NODE_DYNAMIC=1
+ ccflags-y += -DREMOVE_MK_NODE=0
+
+ccflags-y += -I$(WMT_SRC_FOLDER)/common_main/$(MTK_PLATFORM)/include
+
+else
+ ccflags-y += -DSOC_CO_CLOCK_FLAG=0
+ ccflags-y += -DWMT_CREATE_NODE_DYNAMIC=0
+ ccflags-y += -DREMOVE_MK_NODE=1
+endif
+
+ifneq ($(filter "CONSYS_6771" "CONSYS_6775" "CONSYS_6779",$(CONFIG_MTK_COMBO_CHIP)),)
+ ccflags-y += -DEMI_MPU_PROTECTION_IS_READY=1
+endif
+
+ccflags-y += -I$(WMT_SRC_FOLDER)/common_main/include
+ccflags-y += -I$(WMT_SRC_FOLDER)/common_main/linux/include
+ccflags-y += -I$(WMT_SRC_FOLDER)/common_main/core/include
+ccflags-y += -I$(WMT_SRC_FOLDER)/common_main/platform/include
+ifneq ($(CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH),)
+ccflags-y += -I$(WMT_SRC_FOLDER)/debug_utility
+endif
+
+ifeq ($(CONFIG_MTK_CONN_MT3337_CHIP_SUPPORT),y)
+ $(MODULE_NAME)-objs += gps_mt3337.o
+else
+ $(MODULE_NAME)-objs += stp_chrdev_gps.o
+endif
+ifneq ($(CONFIG_MTK_GPS_EMI),)
+$(MODULE_NAME)-objs += gps_emi.o
+endif
+ifneq ($(CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH),)
+$(MODULE_NAME)-objs += fw_log_gps.o
+endif
+
+endif
+# EOF
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/Makefile.ce b/src/kernel/modules/connectivity/2.0/gps_driver/Makefile.ce
new file mode 100644
index 0000000..dc8a130
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/Makefile.ce
@@ -0,0 +1,37 @@
+# Makefile for MT66xx gps driver
+
+##############################################################
+# Common settings
+##############################################################
+EXTRA_KCONFIG:= \
+ CONFIG_MTK_GPS_SUPPORT=y
+
+EXTRA_CFLAGS:= \
+ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \
+ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \
+
+##############################################################
+# Platform specific
+##############################################################
+
+
+##############################################################
+# Compile settings
+##############################################################
+
+all: driver
+
+driver:
+ +cd $(DRIVER_DIR) && make -C $(LINUX_SRC) M=$(DRIVER_DIR) MODULE_NAME=$(MODULE_NAME) PLATFORM_FLAGS="$(PLATFORM_FLAGS)" PLATFORM=${PLATFORM} modules
+
+
+clean: driver_clean
+
+
+driver_clean:
+ cd $(DRIVER_DIR) && make -C $(LINUX_SRC) M=$(DRIVER_DIR) MODULE_NAME=$(MODULE_NAME) clean
+ if [ -e $(DRIVER_DIR)/$(MODULE_NAME).ko ]; then rm $(DRIVER_DIR)/$(MODULE_NAME).ko; fi;
+
+
+.PHONY: all clean driver driver_clean
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/README b/src/kernel/modules/connectivity/2.0/gps_driver/README
new file mode 100755
index 0000000..9046e3a
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/README
@@ -0,0 +1,2 @@
+GPS driver - kernel modules move out of kernel tree
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/gps_dl_context.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/gps_dl_context.c
new file mode 100644
index 0000000..48d6363
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/gps_dl_context.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+#include "gps_dl_context.h"
+#include "gps_dl_hw_api.h"
+
+#if GPS_DL_ON_LINUX
+#define GPS_DL_ISR_DATA0 gps_dl_linux_irq_dispatcher
+#define GPS_DL_ISR_NODATA0 gps_dl_linux_irq_dispatcher
+#define GPS_DL_ISR_MCUB0 gps_dl_linux_irq_dispatcher
+#define GPS_DL_ISR_DATA1 gps_dl_linux_irq_dispatcher
+#define GPS_DL_ISR_NODATA1 gps_dl_linux_irq_dispatcher
+#define GPS_DL_ISR_MCUB1 gps_dl_linux_irq_dispatcher
+#define GPS_DL_ISR_DMA gps_dl_linux_irq_dispatcher
+#elif GPS_DL_ON_CTP
+#define GPS_DL_ISR_DATA0 gps_dl_isr_dl0_has_data
+#define GPS_DL_ISR_NODATA0 gps_dl_isr_dl0_has_nodata
+#define GPS_DL_ISR_MCUB0 gps_dl_isr_dl0_mcub
+#define GPS_DL_ISR_DATA1 gps_dl_isr_dl1_has_data
+#define GPS_DL_ISR_NODATA1 gps_dl_isr_dl1_has_nodata
+#define GPS_DL_ISR_MCUB1 gps_dl_isr_dl1_mcub
+#define GPS_DL_ISR_DMA gps_dl_isr_dma_done
+#endif
+
+static struct gps_dl_ctx s_gps_dl_ctx = {
+ .links = {
+ /* for /dev/gpsdl0 */
+ {.cfg = {.tx_buf_size = GPS_DL_TX_BUF_SIZE, .rx_buf_size = GPS_DL_RX_BUF_SIZE} },
+
+ /* for /dev/gpsdl1 */
+ {.cfg = {.tx_buf_size = GPS_DL_TX_BUF_SIZE, .rx_buf_size = GPS_DL_RX_BUF_SIZE} },
+ },
+ .irqs = {
+ {.cfg = {.index = GPS_DL_IRQ_LINK0_DATA, .name = "gps_da0",
+ .trig_type = GPS_DL_IRQ_TRIG_LEVEL_HIGH,
+ .isr = (void *)GPS_DL_ISR_DATA0} },
+ {.cfg = {.index = GPS_DL_IRQ_LINK0_NODATA, .name = "gps_nd0",
+ .trig_type = GPS_DL_IRQ_TRIG_LEVEL_HIGH,
+ .isr = (void *)GPS_DL_ISR_NODATA0} },
+ {.cfg = {.index = GPS_DL_IRQ_LINK0_MCUB, .name = "gps_mb0",
+ .trig_type = GPS_DL_IRQ_TRIG_LEVEL_HIGH,
+ .isr = (void *)GPS_DL_ISR_MCUB0} },
+ {.cfg = {.index = GPS_DL_IRQ_LINK1_DATA, .name = "gps_da1",
+ .trig_type = GPS_DL_IRQ_TRIG_LEVEL_HIGH,
+ .isr = (void *)GPS_DL_ISR_DATA1} },
+ {.cfg = {.index = GPS_DL_IRQ_LINK1_NODATA, .name = "gps_nd1",
+ .trig_type = GPS_DL_IRQ_TRIG_LEVEL_HIGH,
+ .isr = (void *)GPS_DL_ISR_NODATA1} },
+ {.cfg = {.index = GPS_DL_IRQ_LINK1_MCUB, .name = "gps_mb1",
+ .trig_type = GPS_DL_IRQ_TRIG_LEVEL_HIGH,
+ .isr = (void *)GPS_DL_ISR_MCUB1} },
+ {.cfg = {.index = GPS_DL_IRQ_DMA, .name = "gps_dma",
+ .trig_type = GPS_DL_IRQ_TRIG_LEVEL_HIGH,
+ .isr = (void *)GPS_DL_ISR_DMA} },
+ },
+#if GPS_DL_ON_LINUX
+ .devices = {
+ /* for /dev/gpsdl0 */
+ {.cfg = {.dev_name = "gpsdl0", .index = 0} },
+
+ /* for /dev/gpsdl1 */
+ {.cfg = {.dev_name = "gpsdl1", .index = 1} },
+ },
+#endif /* GPS_DL_ON_LINUX */
+};
+
+static struct gps_dl_runtime_cfg s_gps_rt_cfg = {
+ .dma_is_1byte_mode = false,
+ .dma_is_enabled = true,
+ .show_reg_rw_log = false,
+ .show_reg_wait_log = true,
+ .only_show_wait_done_log = true,
+ .log_level = GPS_DL_LOG_DEF_SETTING_LEVEL,
+ .log_mod_bitmask = GPS_DL_LOG_DEF_SETTING_MODULES,
+ .log_reg_rw_bitmask = GPS_DL_LOG_REG_RW_BITMASK,
+};
+
+struct gps_each_link *gps_dl_link_get(enum gps_dl_link_id_enum link_id)
+{
+ if (link_id >= 0 && link_id < GPS_DATA_LINK_NUM)
+ return &s_gps_dl_ctx.links[link_id];
+
+ return NULL;
+}
+
+struct gps_each_irq *gps_dl_irq_get(enum gps_dl_irq_index_enum irq_idx)
+{
+ if (irq_idx >= 0 && irq_idx < GPS_DL_IRQ_NUM)
+ return &s_gps_dl_ctx.irqs[irq_idx];
+
+ return NULL;
+}
+
+#if GPS_DL_ON_LINUX
+struct gps_each_device *gps_dl_device_get(enum gps_dl_link_id_enum link_id)
+{
+ if (link_id >= 0 && link_id < GPS_DATA_LINK_NUM)
+ return &s_gps_dl_ctx.devices[link_id];
+
+ return NULL;
+}
+#endif
+
+struct gps_dl_remap_ctx *gps_dl_remap_ctx_get(void)
+{
+ return &s_gps_dl_ctx.remap_ctx;
+}
+
+bool gps_dl_is_1byte_mode(void)
+{
+ return s_gps_rt_cfg.dma_is_1byte_mode;
+}
+
+bool gps_dl_set_1byte_mode(bool is_1byte_mode)
+{
+ bool old = s_gps_rt_cfg.dma_is_1byte_mode;
+
+ s_gps_rt_cfg.dma_is_1byte_mode = is_1byte_mode;
+ return old;
+}
+
+bool gps_dl_is_dma_enabled(void)
+{
+ return s_gps_rt_cfg.dma_is_enabled;
+}
+
+bool gps_dl_set_dma_enabled(bool to_enable)
+{
+ bool old = s_gps_rt_cfg.dma_is_enabled;
+
+ s_gps_rt_cfg.dma_is_enabled = to_enable;
+ return old;
+}
+
+bool gps_dl_show_reg_rw_log(void)
+{
+ return s_gps_rt_cfg.show_reg_rw_log;
+}
+
+bool gps_dl_show_reg_wait_log(void)
+{
+ return s_gps_rt_cfg.show_reg_wait_log;
+}
+
+bool gps_dl_only_show_wait_done_log(void)
+{
+ return s_gps_rt_cfg.only_show_wait_done_log;
+}
+
+bool gps_dl_set_show_reg_rw_log(bool on)
+{
+ bool last_on = s_gps_rt_cfg.show_reg_rw_log;
+
+ s_gps_rt_cfg.show_reg_rw_log = on;
+ return last_on;
+}
+
+void gps_dl_set_show_reg_wait_log(bool on)
+{
+ s_gps_rt_cfg.show_reg_wait_log = on;
+}
+
+int gps_dl_set_rx_transfer_max(enum gps_dl_link_id_enum link_id, int max)
+{
+ struct gps_each_link *p_link;
+ int old_max = 0;
+
+ p_link = gps_dl_link_get(link_id);
+
+ if (p_link) {
+ old_max = p_link->rx_dma_buf.transfer_max;
+ p_link->rx_dma_buf.transfer_max = max;
+ GDL_LOGXD(link_id, "old_max = %d, new_max = %d", old_max, max);
+ }
+
+ return old_max;
+}
+
+int gps_dl_set_tx_transfer_max(enum gps_dl_link_id_enum link_id, int max)
+{
+ struct gps_each_link *p_link;
+ int old_max = 0;
+
+ p_link = gps_dl_link_get(link_id);
+
+ if (p_link) {
+ old_max = p_link->tx_dma_buf.transfer_max;
+ p_link->tx_dma_buf.transfer_max = max;
+ GDL_LOGXD(link_id, "old_max = %d, new_max = %d", old_max, max);
+ }
+
+ return old_max;
+}
+
+enum gps_dl_log_level_enum gps_dl_log_level_get(void)
+{
+ return s_gps_rt_cfg.log_level;
+}
+
+void gps_dl_log_level_set(enum gps_dl_log_level_enum level)
+{
+ s_gps_rt_cfg.log_level = level;
+}
+
+bool gps_dl_log_mod_is_on(enum gps_dl_log_module_enum mod)
+{
+ return (bool)(s_gps_rt_cfg.log_mod_bitmask & (1UL << mod));
+}
+
+void gps_dl_log_mod_on(enum gps_dl_log_module_enum mod)
+{
+ s_gps_rt_cfg.log_mod_bitmask |= (1UL << mod);
+}
+
+void gps_dl_log_mod_off(enum gps_dl_log_module_enum mod)
+{
+ s_gps_rt_cfg.log_mod_bitmask &= ~(1UL << mod);
+}
+
+void gps_dl_log_mod_bitmask_set(unsigned int bitmask)
+{
+ s_gps_rt_cfg.log_mod_bitmask = bitmask;
+}
+
+unsigned int gps_dl_log_mod_bitmask_get(void)
+{
+ return s_gps_rt_cfg.log_mod_bitmask;
+}
+
+bool gps_dl_log_reg_rw_is_on(enum gps_dl_log_reg_rw_ctrl_enum log_reg_rw)
+{
+ return (bool)(s_gps_rt_cfg.log_reg_rw_bitmask & (1UL << log_reg_rw));
+}
+
+void gps_dl_log_info_show(void)
+{
+ GDL_LOGE("level = %d, bitmask = 0x%08x", s_gps_rt_cfg.log_level, s_gps_rt_cfg.log_mod_bitmask);
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/gps_each_link.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/gps_each_link.c
new file mode 100644
index 0000000..420b6a3
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/gps_each_link.c
@@ -0,0 +1,1721 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+#include "gps_dl_time_tick.h"
+
+#include "gps_each_link.h"
+#include "gps_dl_hal.h"
+#include "gps_dl_hal_api.h"
+#include "gps_dl_hal_util.h"
+#include "gps_dl_hw_api.h"
+#include "gps_dl_isr.h"
+#include "gps_dl_lib_misc.h"
+#include "gps_dsp_fsm.h"
+#include "gps_dl_osal.h"
+#include "gps_dl_name_list.h"
+#include "gps_dl_context.h"
+#include "gps_dl_subsys_reset.h"
+
+#include "linux/jiffies.h"
+
+#include "linux/errno.h"
+#if GPS_DL_HAS_PLAT_DRV
+#include "gps_dl_linux_plat_drv.h"
+#endif
+
+void gps_each_link_set_bool_flag(enum gps_dl_link_id_enum link_id,
+ enum gps_each_link_bool_state name, bool value)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+
+ if (!p)
+ return;
+
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ switch (name) {
+ case LINK_TO_BE_CLOSED:
+ p->sub_states.to_be_closed = value;
+ break;
+ case LINK_USER_OPEN:
+ p->sub_states.user_open = value;
+ break;
+ case LINK_OPEN_RESULT_OKAY:
+ p->sub_states.open_result_okay = value;
+ break;
+ case LINK_NEED_A2Z_DUMP:
+ p->sub_states.need_a2z_dump = value;
+ break;
+ case LINK_SUSPEND_TO_CLK_EXT:
+ p->sub_states.suspend_to_clk_ext = value;
+ break;
+ default:
+ break; /* do nothing */
+ }
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+}
+
+bool gps_each_link_get_bool_flag(enum gps_dl_link_id_enum link_id,
+ enum gps_each_link_bool_state name)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+ bool value = false;
+
+ if (!p)
+ return false;
+
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ switch (name) {
+ case LINK_TO_BE_CLOSED:
+ value = p->sub_states.to_be_closed;
+ break;
+ case LINK_USER_OPEN:
+ value = p->sub_states.user_open;
+ break;
+ case LINK_OPEN_RESULT_OKAY:
+ value = p->sub_states.open_result_okay;
+ break;
+ case LINK_NEED_A2Z_DUMP:
+ value = p->sub_states.need_a2z_dump;
+ break;
+ case LINK_SUSPEND_TO_CLK_EXT:
+ value = p->sub_states.suspend_to_clk_ext;
+ break;
+ default:
+ break; /* TODO: warning it */
+ }
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+
+ return value;
+}
+
+void gps_dl_link_set_ready_to_write(enum gps_dl_link_id_enum link_id, bool is_ready)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ if (p)
+ p->sub_states.is_ready_to_write = is_ready;
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+}
+
+bool gps_dl_link_is_ready_to_write(enum gps_dl_link_id_enum link_id)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+ bool ready;
+
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ if (p)
+ ready = p->sub_states.is_ready_to_write;
+ else
+ ready = false;
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+
+ return ready;
+}
+
+void gps_each_link_set_active(enum gps_dl_link_id_enum link_id, bool is_active)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ if (p)
+ p->sub_states.is_active = is_active;
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+}
+
+bool gps_each_link_is_active(enum gps_dl_link_id_enum link_id)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+ bool ready;
+
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ if (p)
+ ready = p->sub_states.is_active;
+ else
+ ready = false;
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+
+ return ready;
+}
+
+void gps_each_link_inc_session_id(enum gps_dl_link_id_enum link_id)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+ int sid;
+
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ if (p->session_id >= GPS_EACH_LINK_SID_MAX)
+ p->session_id = 1;
+ else
+ p->session_id++;
+ sid = p->session_id;
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+
+ GDL_LOGXD(link_id, "new sid = %d, 1byte_mode = %d", sid, gps_dl_is_1byte_mode());
+}
+
+int gps_each_link_get_session_id(enum gps_dl_link_id_enum link_id)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+ int sid;
+
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ sid = p->session_id;
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+
+ return sid;
+}
+
+void gps_dl_link_open_wait(enum gps_dl_link_id_enum link_id, long *p_sigval)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+ enum GDL_RET_STATUS gdl_ret;
+ long sigval;
+
+ gdl_ret = gps_dl_link_wait_on(&p->waitables[GPS_DL_WAIT_OPEN_CLOSE], &sigval);
+ if (gdl_ret == GDL_FAIL_SIGNALED) {
+ /*
+ * LINK_OPENING should be a temp state. if code arriving here,
+ * it means something block LINK_OPENING changing to LINK_OPENED
+ * use the api to dump and check whether it's blocked by conn infra driver operation
+ */
+ gps_dl_hal_conn_infra_driver_debug_dump();
+ if (p_sigval != NULL) {
+ *p_sigval = sigval;
+ return;
+ }
+ } else if (gdl_ret == GDL_FAIL_NOT_SUPPORT)
+ ; /* show warnning */
+}
+
+void gps_dl_link_open_ack(enum gps_dl_link_id_enum link_id, bool okay, bool hw_resume)
+{
+#if 0
+ enum GDL_RET_STATUS gdl_ret;
+ struct gdl_dma_buf_entry dma_buf_entry;
+#endif
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+ bool send_msg = false;
+
+ GDL_LOGXD_ONF(link_id, "hw_resume = %d", hw_resume);
+
+ /* TODO: open fail case */
+ gps_each_link_set_bool_flag(link_id, LINK_OPEN_RESULT_OKAY, okay);
+ gps_dl_link_wake_up(&p->waitables[GPS_DL_WAIT_OPEN_CLOSE]);
+
+ gps_each_link_take_big_lock(link_id, GDL_LOCK_FOR_OPEN_DONE);
+ if (gps_each_link_get_bool_flag(link_id, LINK_USER_OPEN) && okay) {
+ GDL_LOGXW_ONF(link_id,
+ "user still online, try to change to opened");
+
+ /* Note: if pre_status not OPENING, it might be RESETTING, not handle it here */
+ if (hw_resume)
+ gps_each_link_change_state_from(link_id, LINK_RESUMING, LINK_OPENED);
+ else
+ gps_each_link_change_state_from(link_id, LINK_OPENING, LINK_OPENED);
+
+ /* TODO: ack on DSP reset done */
+#if 0
+ /* if has pending data, can send it now */
+ gdl_ret = gdl_dma_buf_get_data_entry(&p->tx_dma_buf, &dma_buf_entry);
+ if (gdl_ret == GDL_OKAY)
+ gps_dl_hal_a2d_tx_dma_start(link_id, &dma_buf_entry);
+#endif
+ } else {
+ GDL_LOGXW_ONF(link_id,
+ "okay = %d or user already offline, try to change to closing", okay);
+
+ /* Note: if pre_status not OPENING, it might be RESETTING, not handle it here */
+ if (gps_each_link_change_state_from(link_id, LINK_OPENING, LINK_CLOSING))
+ send_msg = true;
+ }
+ gps_each_link_give_big_lock(link_id);
+
+ if (send_msg) {
+ gps_dl_link_event_send(GPS_DL_EVT_LINK_CLOSE, link_id);
+ gps_each_link_set_bool_flag(link_id, LINK_TO_BE_CLOSED, true);
+ }
+}
+
+void gps_each_link_init(enum gps_dl_link_id_enum link_id)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+
+ p->session_id = 0;
+ gps_each_link_mutexes_init(p);
+ gps_each_link_spin_locks_init(p);
+ gps_each_link_set_active(link_id, false);
+ gps_dl_link_set_ready_to_write(link_id, false);
+ gps_each_link_context_init(link_id);
+ gps_each_link_set_state(link_id, LINK_CLOSED);
+}
+
+void gps_each_link_deinit(enum gps_dl_link_id_enum link_id)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+
+ gps_each_link_set_state(link_id, LINK_UNINIT);
+ gps_each_link_mutexes_deinit(p);
+ gps_each_link_spin_locks_deinit(p);
+}
+
+void gps_each_link_context_init(enum gps_dl_link_id_enum link_id)
+{
+ enum gps_each_link_waitable_type j;
+
+ for (j = 0; j < GPS_DL_WAIT_NUM; j++)
+ gps_dl_link_waitable_reset(link_id, j);
+}
+
+void gps_each_link_context_clear(enum gps_dl_link_id_enum link_id)
+{
+ gps_dl_link_waitable_reset(link_id, GPS_DL_WAIT_WRITE);
+ gps_dl_link_waitable_reset(link_id, GPS_DL_WAIT_READ);
+}
+
+int gps_each_link_open(enum gps_dl_link_id_enum link_id)
+{
+ enum gps_each_link_state_enum state, state2;
+ enum GDL_RET_STATUS gdl_ret;
+ long sigval = 0;
+ bool okay;
+ int retval;
+#if GPS_DL_ON_CTP
+ /* Todo: is it need on LINUX? */
+ struct gps_each_link *p_link = gps_dl_link_get(link_id);
+
+ gps_dma_buf_align_as_byte_mode(&p_link->tx_dma_buf);
+ gps_dma_buf_align_as_byte_mode(&p_link->rx_dma_buf);
+#endif
+
+#if 0
+#if (GPS_DL_ON_LINUX && !GPS_DL_NO_USE_IRQ && !GPS_DL_HW_IS_MOCK)
+ if (!p_link->sub_states.irq_is_init_done) {
+ gps_dl_irq_init();
+ p_link->sub_states.irq_is_init_done = true;
+ }
+#endif
+#endif
+
+ state = gps_each_link_get_state(link_id);
+
+ switch (state) {
+ case LINK_RESUMING:
+ case LINK_SUSPENDED:
+ case LINK_SUSPENDING:
+ retval = -EAGAIN;
+ break;
+
+ case LINK_CLOSING:
+ case LINK_RESETTING:
+ case LINK_DISABLED:
+ retval = -EAGAIN;
+ break;
+
+ case LINK_RESET_DONE:
+ /* RESET_DONE stands for user space not close me */
+ retval = -EBUSY; /* twice open not allowed */
+ break;
+
+ case LINK_OPENED:
+ case LINK_OPENING:
+ retval = -EBUSY;; /* twice open not allowed */
+ break;
+
+ case LINK_CLOSED:
+ okay = gps_each_link_change_state_from(link_id, LINK_CLOSED, LINK_OPENING);
+ if (!okay) {
+ retval = -EBUSY;
+ break;
+ }
+
+ /* TODO: simplify the flags */
+ gps_each_link_set_bool_flag(link_id, LINK_TO_BE_CLOSED, false);
+ gps_each_link_set_bool_flag(link_id, LINK_USER_OPEN, true);
+
+ gps_dl_link_waitable_reset(link_id, GPS_DL_WAIT_OPEN_CLOSE);
+ gps_dl_link_event_send(GPS_DL_EVT_LINK_OPEN, link_id);
+ gps_dl_link_open_wait(link_id, &sigval);
+
+ /* TODO: Check this mutex can be removed?
+ * the possible purpose is make it's atomic from LINK_USER_OPEN and LINK_OPEN_RESULT_OKAY.
+ */
+ gps_each_link_take_big_lock(link_id, GDL_LOCK_FOR_OPEN);
+ if (sigval != 0) {
+ gps_each_link_set_bool_flag(link_id, LINK_USER_OPEN, false);
+
+ gdl_ret = gps_dl_link_try_wait_on(link_id, GPS_DL_WAIT_OPEN_CLOSE);
+ if (gdl_ret == GDL_OKAY) {
+ okay = gps_each_link_change_state_from(link_id, LINK_OPENED, LINK_CLOSING);
+
+ /* Change okay, need to send event to trigger close */
+ if (okay) {
+ gps_each_link_give_big_lock(link_id);
+ gps_dl_link_event_send(GPS_DL_EVT_LINK_CLOSE, link_id);
+ GDL_LOGXW_ONF(link_id,
+ "sigval = %ld, corner case 1: close it", sigval);
+ retval = -EBUSY;
+ break;
+ }
+
+ /* Not change okay, state maybe RESETTING or RESET_DONE */
+ state2 = gps_each_link_get_state(link_id);
+ if (state2 == LINK_RESET_DONE)
+ gps_each_link_set_state(link_id, LINK_CLOSED);
+
+ gps_each_link_give_big_lock(link_id);
+ GDL_LOGXW_ONF(link_id, "sigval = %ld, corner case 2: %s",
+ sigval, gps_dl_link_state_name(state2));
+ retval = -EBUSY;
+ break;
+ }
+
+ gps_each_link_give_big_lock(link_id);
+ GDL_LOGXW_ONF(link_id, "sigval = %ld, normal case", sigval);
+ retval = -EINVAL;
+ break;
+ }
+
+ okay = gps_each_link_get_bool_flag(link_id, LINK_OPEN_RESULT_OKAY);
+ gps_each_link_give_big_lock(link_id);
+
+ if (okay)
+ retval = 0;
+ else {
+ gps_each_link_set_bool_flag(link_id, LINK_USER_OPEN, false);
+ retval = -EBUSY;
+ }
+ break;
+
+ default:
+ retval = -EINVAL;
+ break;
+ }
+
+ if (retval == 0) {
+ GDL_LOGXD_ONF(link_id, "prev_state = %s, retval = %d",
+ gps_dl_link_state_name(state), retval);
+ } else {
+ GDL_LOGXW_ONF(link_id, "prev_state = %s, retval = %d",
+ gps_dl_link_state_name(state), retval);
+ }
+
+ return retval;
+}
+
+int gps_each_link_reset(enum gps_dl_link_id_enum link_id)
+{
+ /*
+ * - set each link resetting flag
+ */
+ enum gps_each_link_state_enum state, state2;
+ bool okay;
+ int retval;
+
+ state = gps_each_link_get_state(link_id);
+
+ switch (state) {
+ case LINK_OPENING:
+ case LINK_CLOSING:
+ case LINK_CLOSED:
+ case LINK_DISABLED:
+ retval = -EBUSY;
+ break;
+
+ case LINK_RESETTING:
+ case LINK_RESET_DONE:
+ retval = 0;
+ break;
+
+ case LINK_RESUMING:
+ case LINK_SUSPENDING:
+ case LINK_SUSPENDED:
+ case LINK_OPENED:
+_try_change_to_reset_again:
+ okay = gps_each_link_change_state_from(link_id, state, LINK_RESETTING);
+ if (!okay) {
+ state2 = gps_each_link_get_state(link_id);
+
+ /* Already reset or close, not trigger reseeting again */
+ GDL_LOGXW_ONF(link_id, "state flip to %s - corner case",
+ gps_dl_link_state_name(state2));
+
+ /* -ing state may become -ed state, try change to reset again */
+ if ((state == LINK_SUSPENDING && state2 == LINK_SUSPENDED) ||
+ (state == LINK_RESUMING && state2 == LINK_OPENED)) {
+ state = state2;
+ goto _try_change_to_reset_again;
+ }
+
+ if (state2 == LINK_RESETTING || state2 == LINK_RESET_DONE)
+ retval = 0;
+ else
+ retval = -EBUSY;
+ break;
+ }
+
+ gps_each_link_set_bool_flag(link_id, LINK_IS_RESETTING, true);
+
+ /* no need to wait reset ack
+ * TODO: make sure message send okay
+ */
+ gps_dl_link_waitable_reset(link_id, GPS_DL_WAIT_RESET);
+ gps_dl_link_event_send(GPS_DL_EVT_LINK_RESET_DSP, link_id);
+ retval = 0;
+ break;
+
+ default:
+ retval = -EINVAL;
+ break;
+ }
+
+ /* wait until cttld thread ack the status */
+ if (retval == 0) {
+ GDL_LOGXD_ONF(link_id, "prev_state = %s, retval = %d",
+ gps_dl_link_state_name(state), retval);
+ } else {
+ GDL_LOGXW_ONF(link_id, "prev_state = %s, retval = %d",
+ gps_dl_link_state_name(state), retval);
+ }
+
+ return retval;
+}
+
+void gps_dl_ctrld_set_resest_status(void)
+{
+ gps_each_link_set_active(GPS_DATA_LINK_ID0, false);
+ gps_each_link_set_active(GPS_DATA_LINK_ID1, false);
+}
+
+void gps_dl_link_reset_ack_inner(enum gps_dl_link_id_enum link_id, bool post_conn_reset)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+ enum gps_each_link_state_enum old_state, new_state;
+ enum gps_each_link_reset_level old_level, new_level;
+ bool user_still_open;
+ bool both_clear_done = false;
+ bool try_conn_infra_off = false;
+
+ gps_each_link_take_big_lock(link_id, GDL_LOCK_FOR_RESET_DONE);
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ old_state = p->state_for_user;
+ old_level = p->reset_level;
+ user_still_open = p->sub_states.user_open;
+
+ switch (old_level) {
+ case GPS_DL_RESET_LEVEL_GPS_SINGLE_LINK:
+ p->reset_level = GPS_DL_RESET_LEVEL_NONE;
+ if (p->sub_states.user_open)
+ p->state_for_user = LINK_RESET_DONE;
+ else
+ p->state_for_user = LINK_CLOSED;
+ break;
+
+ case GPS_DL_RESET_LEVEL_CONNSYS:
+ if (!post_conn_reset)
+ break;
+ p->reset_level = GPS_DL_RESET_LEVEL_NONE;
+ both_clear_done = gps_dl_link_try_to_clear_both_resetting_status();
+ try_conn_infra_off = true;
+ break;
+
+ case GPS_DL_RESET_LEVEL_GPS_SUBSYS:
+ p->reset_level = GPS_DL_RESET_LEVEL_NONE;
+ both_clear_done = gps_dl_link_try_to_clear_both_resetting_status();
+ break;
+
+ default:
+ break;
+ }
+
+ new_state = p->state_for_user;
+ new_level = p->reset_level;
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+
+ if (try_conn_infra_off) {
+ /* During connsys resetting, conninfra_pwr_off may fail,
+ * it need to be called again when connsys reset done.
+ */
+ gps_dl_hal_conn_infra_driver_off();
+ }
+
+ /* TODO: if both clear, show another link's log */
+ GDL_LOGXE_STA(link_id,
+ "state change: %s -> %s, level: %d -> %d, user = %d, post_reset = %d, both_clear = %d",
+ gps_dl_link_state_name(old_state), gps_dl_link_state_name(new_state),
+ old_level, new_level,
+ user_still_open, post_conn_reset, both_clear_done);
+
+ gps_each_link_give_big_lock(link_id);
+
+ /* Note: for CONNSYS or GPS_SUBSYS RESET, here might be still RESETTING,
+ * if any other link not reset done (see both_clear_done print).
+ */
+ gps_dl_link_wake_up(&p->waitables[GPS_DL_WAIT_RESET]);
+}
+
+bool gps_dl_link_try_to_clear_both_resetting_status(void)
+{
+ enum gps_dl_link_id_enum link_id;
+ struct gps_each_link *p;
+
+ for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) {
+ p = gps_dl_link_get(link_id);
+ if (p->reset_level != GPS_DL_RESET_LEVEL_NONE)
+ return false;
+ }
+
+ for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) {
+ p = gps_dl_link_get(link_id);
+
+ if (p->sub_states.user_open)
+ p->state_for_user = LINK_RESET_DONE;
+ else
+ p->state_for_user = LINK_CLOSED;
+ }
+
+ return true;
+}
+
+void gps_dl_link_reset_ack(enum gps_dl_link_id_enum link_id)
+{
+ gps_dl_link_reset_ack_inner(link_id, false);
+}
+
+void gps_dl_link_on_post_conn_reset(enum gps_dl_link_id_enum link_id)
+{
+ gps_dl_link_reset_ack_inner(link_id, true);
+}
+
+void gps_dl_link_close_wait(enum gps_dl_link_id_enum link_id, long *p_sigval)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+ enum GDL_RET_STATUS gdl_ret;
+ long sigval;
+
+ gdl_ret = gps_dl_link_wait_on(&p->waitables[GPS_DL_WAIT_OPEN_CLOSE], &sigval);
+ if (gdl_ret == GDL_FAIL_SIGNALED) {
+ if (p_sigval != NULL) {
+ *p_sigval = sigval;
+ return;
+ }
+ } else if (gdl_ret == GDL_FAIL_NOT_SUPPORT)
+ ; /* show warnning */
+}
+
+void gps_dl_link_close_ack(enum gps_dl_link_id_enum link_id, bool hw_suspend)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+
+ GDL_LOGXD_ONF(link_id, "hw_suspend = %d", hw_suspend);
+ gps_dl_link_wake_up(&p->waitables[GPS_DL_WAIT_OPEN_CLOSE]);
+
+ gps_each_link_take_big_lock(link_id, GDL_LOCK_FOR_CLOSE_DONE);
+
+ /* gps_each_link_set_state(link_id, LINK_CLOSED); */
+ /* For case of reset_done */
+ if (hw_suspend) {
+ gps_each_link_change_state_from(link_id, LINK_SUSPENDING, LINK_SUSPENDED);
+ /* TODO */
+ } else
+ gps_each_link_change_state_from(link_id, LINK_CLOSING, LINK_CLOSED);
+
+ gps_each_link_give_big_lock(link_id);
+}
+
+int gps_each_link_close_or_suspend_inner(enum gps_dl_link_id_enum link_id,
+ enum gps_each_link_state_enum state,
+ enum gps_each_link_close_or_suspend_op close_or_suspend_op)
+{
+ enum gps_each_link_state_enum state2;
+ bool okay;
+ int retval = 0;
+ bool hw_suspend;
+
+ hw_suspend = !!(close_or_suspend_op == GDL_DPSTOP || close_or_suspend_op == GDL_CLKEXT);
+ gps_each_link_take_big_lock(link_id, GDL_LOCK_FOR_CLOSE);
+ do {
+ if (hw_suspend) {
+ okay = gps_each_link_change_state_from(link_id, LINK_OPENED, LINK_SUSPENDING);
+ if (!okay) {
+ state2 = gps_each_link_get_state(link_id);
+ gps_each_link_give_big_lock(link_id);
+ GDL_LOGXW_ONF(link_id, "state check: %s, return hw suspend fail",
+ gps_dl_link_state_name(state2));
+ retval = -EINVAL;
+ break;
+ }
+
+ gps_each_link_set_bool_flag(link_id,
+ LINK_SUSPEND_TO_CLK_EXT, close_or_suspend_op == GDL_CLKEXT);
+ } else {
+ if (state == LINK_SUSPENDED) {
+ okay = gps_each_link_change_state_from(
+ link_id, LINK_SUSPENDED, LINK_CLOSING);
+ } else {
+ okay = gps_each_link_change_state_from(
+ link_id, LINK_OPENED, LINK_CLOSING);
+ }
+ gps_each_link_set_bool_flag(link_id, LINK_USER_OPEN, false);
+ if (!okay) {
+ state2 = gps_each_link_get_state(link_id);
+ if (state2 == LINK_RESET_DONE)
+ gps_each_link_set_state(link_id, LINK_CLOSED);
+ else {
+ GDL_LOGXW_ONF(link_id, "state check: %s, return close ok",
+ gps_dl_link_state_name(state2));
+ }
+ gps_each_link_give_big_lock(link_id);
+ retval = 0;
+ break;
+ }
+ }
+ gps_each_link_give_big_lock(link_id);
+ } while (0);
+ return retval;
+}
+
+int gps_each_link_close_or_suspend(enum gps_dl_link_id_enum link_id,
+ enum gps_each_link_close_or_suspend_op close_or_suspend_op)
+{
+ enum gps_each_link_state_enum state;
+ long sigval = 0;
+ int retval;
+ bool hw_suspend;
+
+ state = gps_each_link_get_state(link_id);
+ hw_suspend = !!(close_or_suspend_op == GDL_DPSTOP || close_or_suspend_op == GDL_CLKEXT);
+
+ switch (state) {
+ case LINK_OPENING:
+ case LINK_CLOSING:
+ case LINK_CLOSED:
+ case LINK_DISABLED:
+ /* twice close */
+ /* TODO: show user open flag */
+ retval = -EINVAL;
+ break;
+
+ case LINK_SUSPENDING:
+ case LINK_RESUMING:
+ case LINK_RESETTING:
+ if (hw_suspend) {
+ if (state == LINK_SUSPENDING)
+ retval = 0;
+ else if (state == LINK_RESUMING)
+ retval = -EBUSY;
+ else
+ retval = -EINVAL;
+ break;
+ }
+
+ /* close on xxx-ing states: just recording user is not online
+ * ctrld will handle it on the end of xxx-ing handling
+ */
+ gps_each_link_set_bool_flag(link_id, LINK_USER_OPEN, false);
+ GDL_LOGXE_ONF(link_id, "state check: %s, return close ok", gps_dl_link_state_name(state));
+ /* return okay to avoid twice close */
+ retval = 0;
+ break;
+
+ case LINK_RESET_DONE:
+ if (hw_suspend) {
+ retval = -EINVAL;
+ break;
+ }
+ gps_each_link_set_bool_flag(link_id, LINK_USER_OPEN, false);
+ gps_each_link_set_state(link_id, LINK_CLOSED);
+ retval = 0;
+ break;
+
+ case LINK_SUSPENDED:
+ case LINK_OPENED:
+ retval = gps_each_link_close_or_suspend_inner(link_id, state, close_or_suspend_op);
+ if (retval != 0)
+ break;
+
+ /* clean the done(fired) flag before send and wait */
+ gps_dl_link_waitable_reset(link_id, GPS_DL_WAIT_OPEN_CLOSE);
+ if (hw_suspend)
+ gps_dl_link_event_send(GPS_DL_EVT_LINK_ENTER_DPSTOP, link_id);
+ else
+ gps_dl_link_event_send(GPS_DL_EVT_LINK_CLOSE, link_id);
+
+ /* set this status, hal proc will by pass the message from the link
+ * it can make LINK_CLOSE be processed faster
+ */
+ gps_each_link_set_bool_flag(link_id, LINK_TO_BE_CLOSED, true);
+ gps_dl_link_close_wait(link_id, &sigval);
+
+ if (sigval) {
+ retval = -EINVAL;
+ break;
+ }
+
+ retval = 0;
+ break;
+ default:
+ retval = -EINVAL;
+ break;
+ }
+
+ if (retval == 0) {
+ GDL_LOGXD_ONF(link_id, "prev_state = %s, retval = %d, op = %d",
+ gps_dl_link_state_name(state), retval, close_or_suspend_op);
+ } else {
+ GDL_LOGXW_ONF(link_id, "prev_state = %s, retval = %d, op = %d",
+ gps_dl_link_state_name(state), retval, close_or_suspend_op);
+ }
+
+ return retval;
+}
+
+int gps_each_link_close(enum gps_dl_link_id_enum link_id)
+{
+ return gps_each_link_close_or_suspend(link_id, GDL_CLOSE);
+}
+int gps_each_link_check(enum gps_dl_link_id_enum link_id, int reason)
+{
+ enum gps_each_link_state_enum state;
+ enum gps_dl_link_event_id event;
+ int retval = 0;
+
+ state = gps_each_link_get_state(link_id);
+
+ switch (state) {
+ case LINK_OPENING:
+ case LINK_CLOSING:
+ case LINK_CLOSED:
+ case LINK_DISABLED:
+ break;
+
+ case LINK_RESETTING:
+#if 0
+ if (rstflag == 1) {
+ /* chip resetting */
+ retval = -888;
+ } else if (rstflag == 2) {
+ /* chip reset end */
+ retval = -889;
+ } else {
+ /* normal */
+ retval = 0;
+ }
+#endif
+ retval = -888;
+ break;
+
+ case LINK_RESET_DONE:
+ retval = 889;
+ break;
+
+ case LINK_RESUMING:
+ case LINK_SUSPENDING:
+ case LINK_SUSPENDED:
+ case LINK_OPENED:
+ if (reason == 2)
+ event = GPS_DL_EVT_LINK_PRINT_HW_STATUS;
+ else if (reason == 4)
+ event = GPS_DL_EVT_LINK_PRINT_DATA_STATUS;
+ else
+ break;
+
+ /* if L1 trigger it, also print L5 status
+ * for this case, dump L5 firstly.
+ */
+ if (link_id == GPS_DATA_LINK_ID0)
+ gps_dl_link_event_send(event, GPS_DATA_LINK_ID1);
+
+ gps_dl_link_event_send(event, link_id);
+ break;
+
+ default:
+ break;
+ }
+
+ GDL_LOGXW_ONF(link_id, "prev_state = %s, reason = %d, retval = %d",
+ gps_dl_link_state_name(state), reason, retval);
+
+ return retval;
+}
+
+int gps_each_link_enter_dsleep(enum gps_dl_link_id_enum link_id)
+{
+ struct gps_each_link *p_link = gps_dl_link_get(link_id);
+
+ gps_dl_link_event_send(GPS_DL_EVT_LINK_ENTER_DPSLEEP, link_id);
+ gps_dma_buf_reset(&p_link->tx_dma_buf);
+ gps_dma_buf_reset(&p_link->rx_dma_buf);
+ return 0;
+}
+
+int gps_each_link_leave_dsleep(enum gps_dl_link_id_enum link_id)
+{
+#if GPS_DL_ON_CTP
+ struct gps_each_link *p_link = gps_dl_link_get(link_id);
+
+ gps_dma_buf_align_as_byte_mode(&p_link->tx_dma_buf);
+ gps_dma_buf_align_as_byte_mode(&p_link->rx_dma_buf);
+#endif
+ gps_dl_link_event_send(GPS_DL_EVT_LINK_LEAVE_DPSLEEP, link_id);
+ return 0;
+}
+
+
+int gps_each_link_hw_suspend(enum gps_dl_link_id_enum link_id, bool need_clk_ext)
+{
+ enum gps_each_link_close_or_suspend_op op;
+
+ if (need_clk_ext)
+ op = GDL_CLKEXT;
+ else
+ op = GDL_DPSTOP;
+ return gps_each_link_close_or_suspend(link_id, op);
+}
+
+int gps_each_link_hw_resume(enum gps_dl_link_id_enum link_id)
+{
+ enum gps_each_link_state_enum state;
+ long sigval = 0;
+ bool okay;
+ int retval;
+#if GPS_DL_ON_CTP
+ struct gps_each_link *p_link = gps_dl_link_get(link_id);
+#endif
+
+ state = gps_each_link_get_state(link_id);
+ do {
+ if (state != LINK_SUSPENDED) {
+ retval = -EINVAL;
+ break;
+ }
+
+ okay = gps_each_link_change_state_from(link_id, LINK_SUSPENDED, LINK_RESUMING);
+ if (!okay) {
+ retval = -EBUSY;
+ break;
+ }
+
+ gps_each_link_set_bool_flag(link_id, LINK_TO_BE_CLOSED, false);
+ gps_dl_link_waitable_reset(link_id, GPS_DL_WAIT_OPEN_CLOSE);
+#if GPS_DL_ON_CTP
+ gps_dma_buf_align_as_byte_mode(&p_link->tx_dma_buf);
+ gps_dma_buf_align_as_byte_mode(&p_link->rx_dma_buf);
+#endif
+ gps_dl_link_event_send(GPS_DL_EVT_LINK_LEAVE_DPSTOP, link_id);
+ gps_dl_link_open_wait(link_id, &sigval);
+ if (sigval != 0) {
+ GDL_LOGXW_ONF(link_id, "sigval = %ld", sigval);
+ retval = -EBUSY;
+ break;
+ }
+
+ okay = gps_each_link_get_bool_flag(link_id, LINK_OPEN_RESULT_OKAY);
+ if (okay)
+ retval = 0;
+ else
+ retval = -EBUSY;
+ } while (0);
+
+ if (retval == 0) {
+ GDL_LOGXD_ONF(link_id, "prev_state = %s, retval = %d",
+ gps_dl_link_state_name(state), retval);
+ } else {
+ GDL_LOGXW_ONF(link_id, "prev_state = %s, retval = %d",
+ gps_dl_link_state_name(state), retval);
+ }
+ return retval;
+}
+
+void gps_dl_link_waitable_init(struct gps_each_link_waitable *p,
+ enum gps_each_link_waitable_type type)
+{
+ p->type = type;
+ p->fired = false;
+#if GPS_DL_ON_LINUX
+ init_waitqueue_head(&p->wq);
+#endif
+}
+
+void gps_dl_link_waitable_reset(enum gps_dl_link_id_enum link_id, enum gps_each_link_waitable_type type)
+{
+ struct gps_each_link *p_link = gps_dl_link_get(link_id);
+
+ /* TOOD: check NULL and boundary */
+ p_link->waitables[type].fired = false;
+}
+
+#define GDL_TEST_TRUE_AND_SET_FALSE(x, x_old) \
+ do { \
+ x_old = x; \
+ if (x_old) { \
+ x = false; \
+ } } while (0)
+
+#define GDL_TEST_FALSE_AND_SET_TRUE(x, x_old) \
+ do { \
+ x_old = x; \
+ if (!x_old) { \
+ x = true; \
+ } } while (0)
+
+enum GDL_RET_STATUS gps_dl_link_wait_on(struct gps_each_link_waitable *p, long *p_sigval)
+{
+#if GPS_DL_ON_LINUX
+ long val;
+ bool is_fired;
+
+ p->waiting = true;
+ /* TODO: check race conditions? */
+ GDL_TEST_TRUE_AND_SET_FALSE(p->fired, is_fired);
+ if (is_fired) {
+ GDL_LOGD("waitable = %s, no wait return", gps_dl_waitable_type_name(p->type));
+ p->waiting = false;
+ return GDL_OKAY;
+ }
+
+ GDL_LOGD("waitable = %s, wait start", gps_dl_waitable_type_name(p->type));
+ val = wait_event_interruptible(p->wq, p->fired);
+ p->waiting = false;
+
+ if (val) {
+ GDL_LOGI("signaled by %ld", val);
+ if (p_sigval)
+ *p_sigval = val;
+ p->waiting = false;
+ return GDL_FAIL_SIGNALED;
+ }
+
+ p->fired = false;
+ p->waiting = false;
+ GDL_LOGD("waitable = %s, wait done", gps_dl_waitable_type_name(p->type));
+ return GDL_OKAY;
+#else
+ return GDL_FAIL_NOT_SUPPORT;
+#endif
+}
+
+enum GDL_RET_STATUS gps_dl_link_try_wait_on(enum gps_dl_link_id_enum link_id,
+ enum gps_each_link_waitable_type type)
+{
+ struct gps_each_link *p_link;
+ struct gps_each_link_waitable *p;
+ bool is_fired;
+
+ p_link = gps_dl_link_get(link_id);
+ p = &p_link->waitables[type];
+
+ GDL_TEST_TRUE_AND_SET_FALSE(p->fired, is_fired);
+ if (is_fired) {
+ GDL_LOGD("waitable = %s, okay", gps_dl_waitable_type_name(p->type));
+ p->waiting = false;
+ return GDL_OKAY;
+ }
+
+ return GDL_FAIL;
+}
+
+void gps_dl_link_wake_up(struct gps_each_link_waitable *p)
+{
+ bool is_fired;
+
+ ASSERT_NOT_NULL(p, GDL_VOIDF());
+
+ if (!p->waiting) {
+ if (p->type == GPS_DL_WAIT_WRITE || p->type == GPS_DL_WAIT_READ) {
+ /* normal case for read/write, not show warning */
+ GDL_LOGD("waitable = %s, nobody waiting",
+ gps_dl_waitable_type_name(p->type));
+ } else {
+ /* not return, just show warning */
+ GDL_LOGW("waitable = %s, nobody waiting",
+ gps_dl_waitable_type_name(p->type));
+ }
+ }
+
+ GDL_TEST_FALSE_AND_SET_TRUE(p->fired, is_fired);
+ GDL_LOGD("waitable = %s, fired = %d", gps_dl_waitable_type_name(p->type), is_fired);
+
+ if (!is_fired) {
+#if GPS_DL_ON_LINUX
+ wake_up(&p->wq);
+#else
+#endif
+ }
+}
+
+/* TODO: determine return value type */
+int gps_each_link_write(enum gps_dl_link_id_enum link_id,
+ unsigned char *buf, unsigned int len)
+{
+ return gps_each_link_write_with_opt(link_id, buf, len, true);
+}
+
+#define GPS_DL_READ_SHOW_BUF_MAX_LEN (32)
+int gps_each_link_write_with_opt(enum gps_dl_link_id_enum link_id,
+ unsigned char *buf, unsigned int len, bool wait_tx_done)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+ enum GDL_RET_STATUS gdl_ret;
+ long sigval = 0;
+
+ if (NULL == p)
+ return -1;
+
+ if (len > p->tx_dma_buf.len)
+ return -1;
+
+ if (gps_each_link_get_state(link_id) != LINK_OPENED) {
+ GDL_LOGXW_DRW(link_id, "not opened, drop the write data len = %d", len);
+ return -EBUSY;
+ }
+
+ if (len <= GPS_DL_READ_SHOW_BUF_MAX_LEN)
+ gps_dl_hal_show_buf("wr_buf", buf, len);
+ else
+ GDL_LOGXD_DRW(link_id, "wr_buf, len = %d", len);
+
+ while (1) {
+ gdl_ret = gdl_dma_buf_put(&p->tx_dma_buf, buf, len);
+
+ if (gdl_ret == GDL_OKAY) {
+ gps_dl_link_event_send(GPS_DL_EVT_LINK_WRITE, link_id);
+#if (GPS_DL_NO_USE_IRQ == 1)
+ if (wait_tx_done) {
+ do {
+ gps_dl_hal_a2d_tx_dma_wait_until_done_and_stop_it(
+ link_id, GPS_DL_RW_NO_TIMEOUT, false);
+ gps_dl_hal_event_send(GPS_DL_HAL_EVT_A2D_TX_DMA_DONE, link_id);
+ /* for case tx transfer_max > 0, GPS_DL_HAL_EVT_A2D_TX_DMA_DONE may */
+ /* start anthor dma session again, need to loop again until all data done */
+ } while (!gps_dma_buf_is_empty(&p->tx_dma_buf));
+ }
+#endif
+ return 0;
+ } else if (gdl_ret == GDL_FAIL_NOSPACE || gdl_ret == GDL_FAIL_BUSY ||
+ gdl_ret == GDL_FAIL_NOENTRY) {
+ /* TODO: */
+ /* 1. note: BUSY stands for others thread is do write, it should be impossible */
+ /* - If wait on BUSY, should wake up the waitings or return eno_again? */
+ /* 2. note: NOSPACE stands for need wait for tx dma working done */
+ gps_dma_buf_show(&p->tx_dma_buf, false);
+ GDL_LOGXD(link_id,
+ "wait due to gdl_dma_buf_put ret = %s", gdl_ret_to_name(gdl_ret));
+ gdl_ret = gps_dl_link_wait_on(&p->waitables[GPS_DL_WAIT_WRITE], &sigval);
+ if (gdl_ret == GDL_FAIL_SIGNALED)
+ break;
+ } else {
+ gps_dma_buf_show(&p->tx_dma_buf, true);
+ GDL_LOGXW(link_id,
+ "fail due to gdl_dma_buf_put ret = %s", gdl_ret_to_name(gdl_ret));
+ break;
+ }
+ }
+
+ return -1;
+}
+
+int gps_each_link_read(enum gps_dl_link_id_enum link_id,
+ unsigned char *buf, unsigned int len) {
+ return gps_each_link_read_with_timeout(link_id, buf, len, GPS_DL_RW_NO_TIMEOUT, NULL);
+}
+
+int gps_each_link_read_with_timeout(enum gps_dl_link_id_enum link_id,
+ unsigned char *buf, unsigned int len, int timeout_usec, bool *p_is_nodata)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+ enum GDL_RET_STATUS gdl_ret;
+#if (GPS_DL_NO_USE_IRQ == 0)
+ long sigval = 0;
+#endif
+ unsigned int data_len;
+
+ if (NULL == p)
+ return -1;
+
+ while (1) {
+ gdl_ret = gdl_dma_buf_get(&p->rx_dma_buf, buf, len, &data_len, p_is_nodata);
+
+ if (gdl_ret == GDL_OKAY) {
+ if (data_len <= GPS_DL_READ_SHOW_BUF_MAX_LEN)
+ gps_dl_hal_show_buf("rd_buf", buf, data_len);
+ else
+ GDL_LOGXD_DRW(link_id, "rd_buf, len = %d", data_len);
+
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+ if (p->rx_dma_buf.has_pending_rx) {
+ p->rx_dma_buf.has_pending_rx = false;
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+
+ GDL_LOGXI_DRW(link_id, "has pending rx, trigger again");
+ gps_dl_hal_event_send(GPS_DL_HAL_EVT_D2A_RX_HAS_DATA, link_id);
+ } else
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+
+ return data_len;
+ } else if (gdl_ret == GDL_FAIL_NODATA) {
+ GDL_LOGXD_DRW(link_id, "gdl_dma_buf_get no data and wait");
+#if (GPS_DL_NO_USE_IRQ == 1)
+ gdl_ret = gps_dl_hal_wait_and_handle_until_usrt_has_data(
+ link_id, timeout_usec);
+ if (gdl_ret == GDL_FAIL_TIMEOUT)
+ return -1;
+
+ gdl_ret = gps_dl_hal_wait_and_handle_until_usrt_has_nodata_or_rx_dma_done(
+ link_id, timeout_usec, true);
+ if (gdl_ret == GDL_FAIL_TIMEOUT)
+ return -1;
+ continue;
+#else
+ gdl_ret = gps_dl_link_wait_on(&p->waitables[GPS_DL_WAIT_READ], &sigval);
+ if (gdl_ret == GDL_FAIL_SIGNALED || gdl_ret == GDL_FAIL_NOT_SUPPORT)
+ return -1;
+#endif
+ } else {
+ GDL_LOGXW_DRW(link_id, "gdl_dma_buf_get fail %s", gdl_ret_to_name(gdl_ret));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+void gps_dl_link_event_send(enum gps_dl_link_event_id evt,
+ enum gps_dl_link_id_enum link_id)
+{
+#if (GPS_DL_HAS_CTRLD == 0)
+ gps_dl_link_event_proc(evt, link_id);
+#else
+ {
+ struct gps_dl_osal_lxop *pOp;
+ struct gps_dl_osal_signal *pSignal;
+ int iRet;
+
+ pOp = gps_dl_get_free_op();
+ if (!pOp)
+ return;
+
+ pSignal = &pOp->signal;
+ pSignal->timeoutValue = 0;/* send data need to wait ?ms */
+ if (link_id < GPS_DATA_LINK_NUM) {
+ pOp->op.opId = GPS_DL_OPID_LINK_EVENT_PROC;
+ pOp->op.au4OpData[0] = link_id;
+ pOp->op.au4OpData[1] = evt;
+ iRet = gps_dl_put_act_op(pOp);
+ } else {
+ gps_dl_put_op_to_free_queue(pOp);
+ /*printf error msg*/
+ return;
+ }
+ }
+#endif
+}
+
+void gps_dl_link_irq_set(enum gps_dl_link_id_enum link_id, bool enable)
+{
+ struct gps_each_link *p_link = gps_dl_link_get(link_id);
+ bool dma_working, pending_rx;
+ bool bypass_unmask_irq;
+
+ if (enable) {
+ gps_dl_irq_each_link_unmask(link_id, GPS_DL_IRQ_TYPE_HAS_DATA, GPS_DL_IRQ_CTRL_FROM_THREAD);
+ gps_dl_irq_each_link_unmask(link_id, GPS_DL_IRQ_TYPE_HAS_NODATA, GPS_DL_IRQ_CTRL_FROM_THREAD);
+
+ /* check if MCUB ROM ready */
+ if (gps_dl_test_mask_mcub_irq_on_open_get(link_id)) {
+ GDL_LOGXE(link_id, "test mask mcub irq, not unmask irq and wait reset");
+ gps_dl_hal_set_mcub_irq_dis_flag(link_id, true);
+ gps_dl_test_mask_mcub_irq_on_open_set(link_id, false);
+ } else if (!gps_dl_hal_mcub_flag_handler(link_id)) {
+ GDL_LOGXE(link_id, "mcub_flag_handler not okay, not unmask irq and wait reset");
+ gps_dl_hal_set_mcub_irq_dis_flag(link_id, true);
+ } else {
+ gps_dl_irq_each_link_unmask(link_id,
+ GPS_DL_IRQ_TYPE_MCUB, GPS_DL_IRQ_CTRL_FROM_THREAD);
+ }
+ } else {
+ if (gps_dl_hal_get_mcub_irq_dis_flag(link_id)) {
+ GDL_LOGXW(link_id, "mcub irq already disable, bypass mask irq");
+ gps_dl_hal_set_mcub_irq_dis_flag(link_id, false);
+ } else {
+ gps_dl_irq_each_link_mask(link_id,
+ GPS_DL_IRQ_TYPE_MCUB, GPS_DL_IRQ_CTRL_FROM_THREAD);
+ }
+
+ bypass_unmask_irq = false;
+ if (gps_dl_hal_get_irq_dis_flag(link_id, GPS_DL_IRQ_TYPE_HAS_DATA)) {
+ GDL_LOGXW(link_id, "hasdata irq already disable, bypass mask irq");
+ gps_dl_hal_set_irq_dis_flag(link_id, GPS_DL_IRQ_TYPE_HAS_DATA, false);
+ bypass_unmask_irq = true;
+ }
+
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+ dma_working = p_link->rx_dma_buf.dma_working_entry.is_valid;
+ pending_rx = p_link->rx_dma_buf.has_pending_rx;
+ if (dma_working || pending_rx) {
+ p_link->rx_dma_buf.has_pending_rx = false;
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+
+ /* It means this irq has already masked, */
+ /* DON'T mask again, otherwise twice unmask might be needed */
+ GDL_LOGXW(link_id,
+ "has dma_working = %d, pending rx = %d, bypass mask irq",
+ dma_working, pending_rx);
+ } else {
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+ if (!bypass_unmask_irq) {
+ gps_dl_irq_each_link_mask(link_id,
+ GPS_DL_IRQ_TYPE_HAS_DATA, GPS_DL_IRQ_CTRL_FROM_THREAD);
+ }
+ }
+
+ /* TODO: avoid twice mask need to be handled if HAS_CTRLD */
+ gps_dl_irq_each_link_mask(link_id, GPS_DL_IRQ_TYPE_HAS_NODATA, GPS_DL_IRQ_CTRL_FROM_THREAD);
+ }
+}
+
+void gps_dl_link_pre_off_setting(enum gps_dl_link_id_enum link_id)
+{
+ /*
+ * The order is important:
+ * 1. disallow write, avoiding to start dma
+ * 2. stop tx/rx dma and mask dma irq if it is last link
+ * 3. mask link's irqs
+ * 4. set inactive after all irq mask done
+ * (at this time isr can check inactive and unmask irq safely due to step 3 already mask irqs)
+ */
+ gps_dl_link_set_ready_to_write(link_id, false);
+ gps_dl_hal_link_confirm_dma_stop(link_id);
+ gps_dl_link_irq_set(link_id, false);
+ gps_each_link_set_active(link_id, false);
+}
+
+void gps_dl_link_event_proc(enum gps_dl_link_event_id evt,
+ enum gps_dl_link_id_enum link_id)
+{
+ struct gps_each_link *p_link = gps_dl_link_get(link_id);
+ bool show_log = false;
+ bool show_log2 = false;
+ unsigned long j0, j1;
+ int ret;
+ enum gps_dsp_state_t dsp_state;
+
+ j0 = jiffies;
+ GDL_LOGXD_EVT(link_id, "evt = %s", gps_dl_link_event_name(evt));
+
+ switch (evt) {
+ case GPS_DL_EVT_LINK_OPEN:
+ /* show_log = gps_dl_set_show_reg_rw_log(true); */
+ gps_each_dsp_reg_gourp_read_init(link_id);
+ gps_each_link_inc_session_id(link_id);
+ gps_each_link_set_active(link_id, true);
+ gps_each_link_set_bool_flag(link_id, LINK_NEED_A2Z_DUMP, false);
+
+ ret = gps_dl_hal_conn_power_ctrl(link_id, 1);
+ if (ret != 0) {
+ gps_dl_link_open_ack(link_id, false, false);
+ break;
+ }
+
+ ret = gps_dl_hal_link_power_ctrl(link_id, GPS_DL_HAL_POWER_ON);
+ if (ret != 0) {
+ gps_dl_hal_conn_power_ctrl(link_id, 0);
+ gps_dl_link_open_ack(link_id, false, false);
+ break;
+ }
+
+ gps_dsp_fsm(GPS_DSP_EVT_FUNC_ON, link_id);
+ gps_dl_link_irq_set(link_id, true);
+#if GPS_DL_NO_USE_IRQ
+ gps_dl_wait_us(1000); /* wait 1ms */
+#endif
+ /* set ready to write before open ack, otherwise need to check pending tx data
+ * gps_dl_link_set_ready_to_write(link_id, true);
+ * move it to DSP reset done handler
+ */
+ gps_dl_link_open_ack(link_id, true, false); /* TODO: ack on DSP reset done */
+ /* gps_dl_set_show_reg_rw_log(show_log); */
+ break;
+ case GPS_DL_EVT_LINK_LEAVE_DPSTOP:
+ gps_each_dsp_reg_gourp_read_init(link_id);
+ gps_each_link_inc_session_id(link_id);
+ gps_each_link_set_active(link_id, true);
+ gps_each_link_set_bool_flag(link_id, LINK_NEED_A2Z_DUMP, false);
+ ret = gps_dl_hal_link_power_ctrl(link_id, GPS_DL_HAL_LEAVE_DPSTOP);
+ if (ret != 0)
+ gps_dl_link_open_ack(link_id, false, true);
+ else {
+ gps_dsp_fsm(GPS_DSP_EVT_HW_STOP_EXIT, link_id);
+ gps_dl_link_irq_set(link_id, true);
+ gps_dl_link_open_ack(link_id, true, true);
+ }
+ break;
+ case GPS_DL_EVT_LINK_LEAVE_DPSLEEP:
+ gps_dl_hal_link_power_ctrl(link_id, GPS_DL_HAL_LEAVE_DPSLEEP);
+ gps_dl_link_irq_set(link_id, true);
+ break;
+ case GPS_DL_EVT_LINK_ENTER_DPSLEEP:
+ gps_dl_link_pre_off_setting(link_id);
+ gps_dl_hal_link_power_ctrl(link_id, GPS_DL_HAL_ENTER_DPSLEEP);
+ break;
+ case GPS_DL_EVT_LINK_ENTER_DPSTOP:
+ dsp_state = gps_dsp_state_get(link_id);
+ if ((GPS_DSP_ST_WORKING != dsp_state) && (GPS_DSP_ST_RESET_DONE != dsp_state)) {
+ /* TODO: ever working check */
+ GDL_LOGXE(link_id, "not enter dpstop due to dsp state = %s",
+ gps_dl_dsp_state_name(dsp_state));
+
+ /* TODO: ack fail */
+ gps_dl_link_close_ack(link_id, true);
+ break;
+ }
+
+ if (GPS_DSP_ST_WORKING == dsp_state) {
+ GDL_LOGXW(link_id, "enter dpstop with dsp state = %s",
+ gps_dl_dsp_state_name(dsp_state));
+ }
+
+ gps_dl_hal_set_need_clk_ext_flag(link_id,
+ gps_each_link_get_bool_flag(link_id, LINK_SUSPEND_TO_CLK_EXT));
+
+ gps_dl_link_pre_off_setting(link_id);
+ /* TODO: handle fail */
+ gps_dl_hal_link_power_ctrl(link_id, GPS_DL_HAL_ENTER_DPSTOP);
+ gps_dsp_fsm(GPS_DSP_EVT_HW_STOP_REQ, link_id);
+ gps_each_link_context_clear(link_id);
+#if GPS_DL_ON_LINUX
+ gps_dma_buf_reset(&p_link->tx_dma_buf);
+ gps_dma_buf_reset(&p_link->rx_dma_buf);
+#endif
+ gps_dl_link_close_ack(link_id, true);
+ break;
+ case GPS_DL_EVT_LINK_DSP_ROM_READY_TIMEOUT:
+ /* check again mcub not ready triggered */
+ if (false)
+ break; /* wait hal handle it */
+
+ /* true: */
+ if (!gps_each_link_change_state_from(link_id, LINK_OPENED, LINK_RESETTING)) {
+ /* no handle it again */
+ break;
+ }
+ /* TODO: go and do close */
+ case GPS_DL_EVT_LINK_CLOSE:
+ case GPS_DL_EVT_LINK_RESET_DSP:
+ case GPS_DL_EVT_LINK_RESET_GPS:
+ case GPS_DL_EVT_LINK_PRE_CONN_RESET:
+ if (evt != GPS_DL_EVT_LINK_CLOSE)
+ show_log = gps_dl_set_show_reg_rw_log(true);
+
+ /* handle open fail case */
+ if (!gps_each_link_get_bool_flag(link_id, LINK_OPEN_RESULT_OKAY)) {
+ GDL_LOGXD(link_id, "not open okay, just power off for %s",
+ gps_dl_link_event_name(evt));
+
+ gps_each_link_set_active(link_id, false);
+ gps_dl_hal_link_power_ctrl(link_id, GPS_DL_HAL_POWER_OFF);
+ gps_dl_hal_conn_power_ctrl(link_id, 0);
+ goto _close_or_reset_ack;
+ }
+
+ /* to avoid twice enter */
+ if (GPS_DSP_ST_OFF == gps_dsp_state_get(link_id)) {
+ GDL_LOGXD(link_id, "dsp state is off, do nothing for %s",
+ gps_dl_link_event_name(evt));
+
+ if (evt != GPS_DL_EVT_LINK_CLOSE)
+ gps_dl_set_show_reg_rw_log(show_log);
+
+ goto _close_or_reset_ack;
+ } else if (GPS_DSP_ST_HW_STOP_MODE == gps_dsp_state_get(link_id)) {
+ /* exit deep stop mode and turn off it
+ * before exit deep stop, need clear pwr stat to make sure dsp is in hold-on state
+ * after exit deep stop mode.
+ */
+ gps_dl_hal_link_clear_hw_pwr_stat(link_id);
+ gps_dl_hal_link_power_ctrl(link_id, GPS_DL_HAL_LEAVE_DPSTOP);
+ } else {
+ /* make sure current link's DMAs are stopped and mask the IRQs */
+ gps_dl_link_pre_off_setting(link_id);
+ }
+ gps_dl_hal_set_need_clk_ext_flag(link_id, false);
+
+ if (evt != GPS_DL_EVT_LINK_CLOSE) {
+ /* try to dump host csr info if not normal close operation */
+ if (gps_dl_conninfra_is_okay_or_handle_it(NULL, true))
+ gps_dl_hw_dump_host_csr_gps_info(true);
+ }
+
+ if (gps_each_link_get_bool_flag(link_id, LINK_NEED_A2Z_DUMP)) {
+ show_log2 = gps_dl_set_show_reg_rw_log(true);
+ gps_dl_hw_do_gps_a2z_dump();
+ gps_dl_set_show_reg_rw_log(show_log2);
+ }
+
+ gps_dl_hal_link_power_ctrl(link_id, GPS_DL_HAL_POWER_OFF);
+ gps_dl_hal_conn_power_ctrl(link_id, 0);
+
+ gps_dsp_fsm(GPS_DSP_EVT_FUNC_OFF, link_id);
+
+ gps_each_link_context_clear(link_id);
+#if GPS_DL_ON_LINUX
+ gps_dma_buf_reset(&p_link->tx_dma_buf);
+ gps_dma_buf_reset(&p_link->rx_dma_buf);
+#endif
+
+_close_or_reset_ack:
+ if (evt != GPS_DL_EVT_LINK_CLOSE)
+ gps_dl_set_show_reg_rw_log(show_log);
+
+ if (GPS_DL_EVT_LINK_CLOSE == evt)
+ gps_dl_link_close_ack(link_id, false); /* TODO: check fired race */
+ else
+ gps_dl_link_reset_ack(link_id);
+ break;
+
+ case GPS_DL_EVT_LINK_POST_CONN_RESET:
+ gps_dl_link_on_post_conn_reset(link_id);
+ break;
+
+ case GPS_DL_EVT_LINK_WRITE:
+ /* gps_dl_hw_print_usrt_status(link_id); */
+ if (gps_dl_link_is_ready_to_write(link_id))
+ gps_dl_link_start_tx_dma_if_has_data(link_id);
+ else
+ GDL_LOGXW(link_id, "too early writing");
+ break;
+
+ case GPS_DL_EVT_LINK_PRINT_HW_STATUS:
+ case GPS_DL_EVT_LINK_PRINT_DATA_STATUS:
+ if (!gps_each_link_is_active(link_id)) {
+ GDL_LOGXW(link_id, "inactive, do not dump hw status");
+ break;
+ }
+
+ gps_dma_buf_show(&p_link->rx_dma_buf, true);
+ gps_dma_buf_show(&p_link->tx_dma_buf, true);
+ if (!gps_dl_conninfra_is_okay_or_handle_it(NULL, true))
+ break;
+
+ show_log = gps_dl_set_show_reg_rw_log(true);
+ if (evt == GPS_DL_EVT_LINK_PRINT_HW_STATUS) {
+ gps_dl_hw_dump_host_csr_gps_info(true);
+ gps_dl_hw_print_hw_status(link_id, true);
+ gps_each_dsp_reg_gourp_read_start(link_id, true, 4);
+ } else {
+ gps_dl_hw_print_hw_status(link_id, false);
+ gps_each_dsp_reg_gourp_read_start(link_id, true, 1);
+ }
+ gps_dl_set_show_reg_rw_log(show_log);
+ break;
+
+ case GPS_DL_EVT_LINK_DSP_FSM_TIMEOUT:
+ gps_dsp_fsm(GPS_DSP_EVT_CTRL_TIMER_EXPIRE, link_id);
+ break;
+#if 0
+ case GPS_DL_EVT_LINK_RESET_GPS:
+ /* turn off GPS power directly */
+ break;
+
+ case GPS_DL_EVT_LINK_PRE_CONN_RESET:
+ /* turn off Connsys power directly
+ * 1. no need to do anything, just make sure the message queue is empty
+ * 2. how to handle ctrld block issue
+ */
+ /* gps_dl_link_open_ack(link_id); */
+ break;
+#endif
+ default:
+ break;
+ }
+
+ j1 = jiffies;
+ GDL_LOGXI_EVT(link_id, "evt = %s, dj = %lu", gps_dl_link_event_name(evt), j1 - j0);
+}
+
+void gps_each_link_mutexes_init(struct gps_each_link *p)
+{
+ enum gps_each_link_mutex i;
+
+ for (i = 0; i < GPS_DL_MTX_NUM; i++)
+ gps_dl_osal_sleepable_lock_init(&p->mutexes[i]);
+}
+
+void gps_each_link_mutexes_deinit(struct gps_each_link *p)
+{
+ enum gps_each_link_mutex i;
+
+ for (i = 0; i < GPS_DL_MTX_NUM; i++)
+ gps_dl_osal_sleepable_lock_deinit(&p->mutexes[i]);
+}
+
+void gps_each_link_spin_locks_init(struct gps_each_link *p)
+{
+ enum gps_each_link_spinlock i;
+
+ for (i = 0; i < GPS_DL_SPINLOCK_NUM; i++)
+ gps_dl_osal_unsleepable_lock_init(&p->spin_locks[i]);
+}
+
+void gps_each_link_spin_locks_deinit(struct gps_each_link *p)
+{
+#if 0
+ enum gps_each_link_spinlock i;
+
+ for (i = 0; i < GPS_DL_SPINLOCK_NUM; i++)
+ osal_unsleepable_lock_deinit(&p->spin_locks[i]);
+#endif
+}
+
+void gps_each_link_mutex_take(enum gps_dl_link_id_enum link_id, enum gps_each_link_mutex mtx_id)
+{
+ /* TODO: check range */
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+
+ /* TODO: handle killed */
+ gps_dl_osal_lock_sleepable_lock(&p->mutexes[mtx_id]);
+}
+
+void gps_each_link_mutex_give(enum gps_dl_link_id_enum link_id, enum gps_each_link_mutex mtx_id)
+{
+ /* TODO: check range */
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+
+ gps_dl_osal_unlock_sleepable_lock(&p->mutexes[mtx_id]);
+}
+
+void gps_each_link_spin_lock_take(enum gps_dl_link_id_enum link_id, enum gps_each_link_spinlock spin_lock_id)
+{
+ /* TODO: check range */
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+
+ gps_dl_osal_lock_unsleepable_lock(&p->spin_locks[spin_lock_id]);
+}
+
+void gps_each_link_spin_lock_give(enum gps_dl_link_id_enum link_id, enum gps_each_link_spinlock spin_lock_id)
+{
+ /* TODO: check range */
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+
+ gps_dl_osal_unlock_unsleepable_lock(&p->spin_locks[spin_lock_id]);
+}
+
+int gps_each_link_take_big_lock(enum gps_dl_link_id_enum link_id,
+ enum gps_each_link_lock_reason reason)
+{
+ gps_each_link_mutex_take(link_id, GPS_DL_MTX_BIG_LOCK);
+ return 0;
+}
+
+int gps_each_link_give_big_lock(enum gps_dl_link_id_enum link_id)
+{
+ gps_each_link_mutex_give(link_id, GPS_DL_MTX_BIG_LOCK);
+ return 0;
+}
+
+enum gps_each_link_state_enum gps_each_link_get_state(enum gps_dl_link_id_enum link_id)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+ enum gps_each_link_state_enum state;
+
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ state = p->state_for_user;
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+
+ return state;
+}
+
+void gps_each_link_set_state(enum gps_dl_link_id_enum link_id, enum gps_each_link_state_enum state)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+ enum gps_each_link_state_enum pre_state;
+
+
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ pre_state = p->state_for_user;
+ p->state_for_user = state;
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+
+ GDL_LOGXI_STA(link_id, "state change: %s -> %s",
+ gps_dl_link_state_name(pre_state), gps_dl_link_state_name(state));
+}
+
+bool gps_each_link_change_state_from(enum gps_dl_link_id_enum link_id,
+ enum gps_each_link_state_enum from, enum gps_each_link_state_enum to)
+{
+ bool is_okay = false;
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+ enum gps_each_link_state_enum pre_state;
+ enum gps_each_link_reset_level old_level, new_level;
+
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ pre_state = p->state_for_user;
+ if (from == pre_state) {
+ p->state_for_user = to;
+ is_okay = true;
+
+ if (to == LINK_RESETTING) {
+ old_level = p->reset_level;
+ if (old_level < GPS_DL_RESET_LEVEL_GPS_SINGLE_LINK)
+ p->reset_level = GPS_DL_RESET_LEVEL_GPS_SINGLE_LINK;
+ new_level = p->reset_level;
+ }
+ }
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+
+ if (is_okay && (to == LINK_RESETTING)) {
+ GDL_LOGXI_STA(link_id, "state change: %s -> %s, okay, level: %d -> %d",
+ gps_dl_link_state_name(from), gps_dl_link_state_name(to),
+ old_level, new_level);
+ } else if (is_okay) {
+ GDL_LOGXI_STA(link_id, "state change: %s -> %s, okay",
+ gps_dl_link_state_name(from), gps_dl_link_state_name(to));
+ } else {
+ GDL_LOGXW_STA(link_id, "state change: %s -> %s, fail on pre_state = %s",
+ gps_dl_link_state_name(from), gps_dl_link_state_name(to),
+ gps_dl_link_state_name(pre_state));
+ }
+
+ return is_okay;
+}
+
+bool gps_dl_link_start_tx_dma_if_has_data(enum gps_dl_link_id_enum link_id)
+{
+ struct gps_each_link *p_link = gps_dl_link_get(link_id);
+ struct gdl_dma_buf_entry dma_buf_entry;
+ enum GDL_RET_STATUS gdl_ret;
+ bool tx_dma_started;
+
+ gdl_ret = gdl_dma_buf_get_data_entry(&p_link->tx_dma_buf, &dma_buf_entry);
+
+ if (gdl_ret == GDL_OKAY) {
+ /* wait until dsp recevie last data done or timeout(10ms)
+ * TODO: handle timeout case
+ */
+ gps_dl_hw_poll_usrt_dsp_rx_empty(link_id);
+ gps_dl_hal_a2d_tx_dma_claim_emi_usage(link_id, true);
+ gps_dl_hal_a2d_tx_dma_start(link_id, &dma_buf_entry);
+ tx_dma_started = true;
+ } else {
+ GDL_LOGD("gdl_dma_buf_get_data_entry ret = %s", gdl_ret_to_name(gdl_ret));
+ tx_dma_started = false;
+ }
+
+ return tx_dma_started;
+}
+
+int gps_dl_link_get_clock_flag(void)
+{
+ return gps_dl_hal_get_clock_flag();
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_conn_infra.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_conn_infra.c
new file mode 100644
index 0000000..c2ee33f
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_conn_infra.c
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#include "gps_dl_config.h"
+
+#include "gps_dl_context.h"
+#include "gps_dl_hw_api.h"
+#include "gps_dl_hal_api.h"
+#if GPS_DL_HAS_PLAT_DRV
+#include "gps_dl_linux_reserved_mem.h"
+#endif
+
+#define GPS_EMI_REMAP_BASE_MASK (0xFFFFF0000) /* start from 64KB boundary, get msb20 of 36bit */
+#define GPS_EMI_REMAP_LENGTH (64 * 1024 * 1024UL)
+#define GPS_EMI_BUS_BASE (0x78000000)
+
+void gps_dl_emi_remap_set(unsigned int min_addr, unsigned int max_addr)
+{
+ unsigned int aligned_addr = 0;
+ unsigned int _20msb_of_36bit_phy_addr;
+
+ /* TODO: addr may not use uint, due to addr might be 36bit and uint might be only 32bit */
+ aligned_addr = (min_addr & GPS_EMI_REMAP_BASE_MASK);
+
+
+ if (max_addr - aligned_addr > GPS_EMI_REMAP_LENGTH) {
+ GDL_LOGE("min = 0x%09x, max = 0x%09x, base = 0x%09x, over range",
+ min_addr, max_addr, aligned_addr);
+ } else {
+ GDL_LOGD("min = 0x%09x, max = 0x%09x, base = 0x%09x",
+ min_addr, max_addr, aligned_addr);
+ }
+
+ _20msb_of_36bit_phy_addr = aligned_addr >> 16;
+ GDL_LOGD("icap_buf: remap setting = 0x%08x", _20msb_of_36bit_phy_addr);
+ gps_dl_hw_set_gps_emi_remapping(_20msb_of_36bit_phy_addr);
+ gps_dl_remap_ctx_get()->gps_emi_phy_high20 = aligned_addr;
+}
+
+enum GDL_RET_STATUS gps_dl_emi_remap_phy_to_bus_addr(unsigned int phy_addr, unsigned int *bus_addr)
+{
+ unsigned int remap_setting = gps_dl_remap_ctx_get()->gps_emi_phy_high20;
+
+ if ((phy_addr >= remap_setting) &&
+ (phy_addr < (remap_setting + GPS_EMI_REMAP_LENGTH))) {
+ *bus_addr = GPS_EMI_BUS_BASE + (phy_addr - remap_setting);
+ return GDL_OKAY;
+ }
+
+ *bus_addr = 0;
+ return GDL_FAIL;
+}
+
+void gps_dl_emi_remap_calc_and_set(void)
+{
+ enum gps_dl_link_id_enum i;
+ struct gps_each_link *p_link;
+
+ unsigned int min_addr = 0xFFFFFFFF;
+ unsigned int max_addr = 0;
+ unsigned int tx_end;
+ unsigned int rx_end;
+
+#if GPS_DL_HAS_PLAT_DRV
+ if (gps_dl_reserved_mem_is_ready()) {
+ gps_dl_reserved_mem_show_info();
+ gps_dl_reserved_mem_get_range(&min_addr, &max_addr);
+ gps_dl_emi_remap_set(min_addr, max_addr);
+ return;
+ }
+#endif
+
+ for (i = 0; i < GPS_DATA_LINK_NUM; i++) {
+ p_link = gps_dl_link_get(i);
+
+ min_addr = (p_link->rx_dma_buf.phy_addr < min_addr) ? p_link->rx_dma_buf.phy_addr : min_addr;
+ min_addr = (p_link->tx_dma_buf.phy_addr < min_addr) ? p_link->tx_dma_buf.phy_addr : min_addr;
+
+ rx_end = p_link->rx_dma_buf.phy_addr + p_link->rx_dma_buf.len;
+ tx_end = p_link->tx_dma_buf.phy_addr + p_link->tx_dma_buf.len;
+
+ max_addr = (rx_end > min_addr) ? rx_end : max_addr;
+ max_addr = (tx_end > min_addr) ? tx_end : max_addr;
+ }
+ GDL_LOGD("cal from dma buffers: min = 0x%x, max = 0x%x", min_addr, max_addr);
+ gps_dl_emi_remap_set(min_addr, max_addr);
+}
+
+
+unsigned int g_gps_dl_hal_conn_infra_poll_ok_ver;
+
+void gps_dl_hw_gps_set_conn_infra_ver(unsigned int ver)
+{
+ g_gps_dl_hal_conn_infra_poll_ok_ver = ver;
+}
+
+unsigned int gps_dl_hw_gps_get_conn_infra_ver(void)
+{
+ return g_gps_dl_hal_conn_infra_poll_ok_ver;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_dma.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_dma.c
new file mode 100644
index 0000000..6a92b43
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_dma.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+#include "gps_dl_context.h"
+
+#include "gps_dl_hal.h"
+#include "gps_dl_hal_api.h"
+#include "gps_dl_hal_util.h"
+#include "gps_each_link.h"
+
+#if GPS_DL_MOCK_HAL
+#include "gps_mock_hal.h"
+#endif
+#include "gps_dl_hw_api.h"
+
+void gps_dl_hal_dma_init(void)
+{
+}
+
+void gps_dl_hal_dma_config(enum gps_dl_hal_dma_ch_index ch)
+{
+}
+
+
+void gps_dl_hal_a2d_tx_dma_start(enum gps_dl_link_id_enum link_id,
+ struct gdl_dma_buf_entry *p_entry)
+{
+ struct gps_each_link *p_link = gps_dl_link_get(link_id);
+
+ p_link->tx_dma_buf.dma_working_entry = *p_entry;
+
+ GDL_LOGXD(link_id, "");
+
+ if (link_id == GPS_DATA_LINK_ID0)
+ gps_dl_hal_dma_start(GPS_DL_DMA_LINK0_A2D, p_entry);
+ else if (link_id == GPS_DATA_LINK_ID1)
+ gps_dl_hal_dma_start(GPS_DL_DMA_LINK1_A2D, p_entry);
+}
+
+void gps_dl_hal_a2d_tx_dma_stop(enum gps_dl_link_id_enum link_id)
+{
+ if (link_id == GPS_DATA_LINK_ID0)
+ gps_dl_hal_dma_stop(GPS_DL_DMA_LINK0_A2D);
+ else if (link_id == GPS_DATA_LINK_ID1)
+ gps_dl_hal_dma_stop(GPS_DL_DMA_LINK1_A2D);
+}
+
+enum GDL_RET_STATUS gps_dl_hal_a2d_tx_dma_wait_until_done_and_stop_it(
+ enum gps_dl_link_id_enum link_id, int timeout_usec, bool return_if_not_start)
+{
+ GDL_LOGXD(link_id, "");
+ if (link_id == GPS_DATA_LINK_ID0) {
+ return gps_dl_hw_wait_until_dma_complete_and_stop_it(
+ GPS_DL_DMA_LINK0_A2D, timeout_usec, return_if_not_start);
+ } else if (link_id == GPS_DATA_LINK_ID1) {
+ return gps_dl_hw_wait_until_dma_complete_and_stop_it(
+ GPS_DL_DMA_LINK1_A2D, timeout_usec, return_if_not_start);
+ }
+
+ return GDL_FAIL;
+}
+
+void gps_dl_hal_d2a_rx_dma_start(enum gps_dl_link_id_enum link_id,
+ struct gdl_dma_buf_entry *p_entry)
+{
+ struct gps_each_link *p_link = gps_dl_link_get(link_id);
+
+ ASSERT_LINK_ID(link_id, GDL_VOIDF());
+ ASSERT_NOT_NULL(p_entry, GDL_VOIDF());
+
+ p_link->rx_dma_buf.dma_working_entry = *p_entry;
+
+ if (link_id == GPS_DATA_LINK_ID0)
+ gps_dl_hal_dma_start(GPS_DL_DMA_LINK0_D2A, p_entry);
+ else if (link_id == GPS_DATA_LINK_ID1)
+ gps_dl_hal_dma_start(GPS_DL_DMA_LINK1_D2A, p_entry);
+}
+
+void gps_dl_hal_d2a_rx_dma_stop(enum gps_dl_link_id_enum link_id)
+{
+ if (link_id == GPS_DATA_LINK_ID0)
+ gps_dl_hal_dma_stop(GPS_DL_DMA_LINK0_D2A);
+ else if (link_id == GPS_DATA_LINK_ID1)
+ gps_dl_hal_dma_stop(GPS_DL_DMA_LINK1_D2A);
+}
+
+enum GDL_RET_STATUS gps_dl_hal_d2a_rx_dma_wait_until_done(
+ enum gps_dl_link_id_enum link_id, int timeout_usec)
+{
+ if (link_id == GPS_DATA_LINK_ID0) {
+ return gps_dl_hw_wait_until_dma_complete_and_stop_it(
+ GPS_DL_DMA_LINK0_D2A, timeout_usec, false);
+ } else if (link_id == GPS_DATA_LINK_ID1) {
+ return gps_dl_hw_wait_until_dma_complete_and_stop_it(
+ GPS_DL_DMA_LINK1_D2A, timeout_usec, false);
+ }
+
+ return GDL_FAIL;
+}
+
+unsigned int gps_dl_hal_d2a_rx_dma_get_rx_len(enum gps_dl_link_id_enum link_id)
+{
+ return 0;
+}
+
+enum GDL_RET_STATUS gps_dl_real_dma_get_rx_write_index(
+ enum gps_dl_link_id_enum link_id, unsigned int *p_write_index)
+{
+ enum GDL_RET_STATUS gdl_ret;
+ unsigned int left_len;
+ enum gps_dl_hal_dma_ch_index ch;
+ struct gps_each_link *p_link = gps_dl_link_get(link_id);
+
+ ASSERT_LINK_ID(link_id, GDL_FAIL_ASSERT);
+
+ if (link_id == GPS_DATA_LINK_ID0)
+ ch = GPS_DL_DMA_LINK0_D2A;
+ else
+ ch = GPS_DL_DMA_LINK1_D2A;
+
+ left_len = gps_dl_hw_get_dma_left_len(ch);
+ if (!gps_dl_is_1byte_mode())
+ left_len *= 4;
+
+ gdl_ret = gdl_dma_buf_entry_transfer_left_to_write_index(
+ &p_link->rx_dma_buf.dma_working_entry, left_len, p_write_index);
+
+ return gdl_ret;
+}
+
+enum GDL_RET_STATUS gps_dl_hal_d2a_rx_dma_get_write_index(
+ enum gps_dl_link_id_enum link_id, unsigned int *p_write_index)
+{
+#if GPS_DL_MOCK_HAL
+ unsigned int write_index_from_mock;
+ enum GDL_RET_STATUS gdl_from_mock;
+#endif
+ enum GDL_RET_STATUS gdl_ret;
+
+ ASSERT_NOT_NULL(p_write_index, GDL_FAIL_ASSERT);
+#if GPS_DL_MOCK_HAL
+ gdl_from_mock = gps_dl_mock_dma_get_rx_write_index(link_id, &write_index_from_mock);
+ if (gdl_from_mock != GDL_OKAY)
+ return gdl_from_mock;
+#endif
+ gdl_ret = gps_dl_real_dma_get_rx_write_index(link_id, p_write_index);
+ GDL_LOGD("real gdl_ret = %s", gdl_ret_to_name(gdl_ret));
+
+#if GPS_DL_MOCK_HAL
+ *p_write_index = write_index_from_mock;
+ return gdl_from_mock;
+#else
+ return gdl_ret;
+#endif
+}
+
+void gps_dl_real_dma_start(enum gps_dl_hal_dma_ch_index ch,
+ struct gdl_dma_buf_entry *p_entry)
+{
+ enum GDL_RET_STATUS gdl_ret;
+ enum gps_dl_link_id_enum link_id;
+ struct gdl_hw_dma_transfer dma_transfer;
+
+ ASSERT_NOT_NULL(p_entry, GDL_VOIDF());
+
+ link_id = DMA_CH_TO_LINK_ID(ch);
+ ASSERT_LINK_ID(link_id, GDL_VOIDF());
+
+ GDL_LOGXD(link_id, "ch = %d, r = %u, w = %u, addr = 0x%p",
+ ch, p_entry->read_index, p_entry->write_index,
+ p_entry->vir_addr);
+
+ if (DMA_CH_IS_TX(ch))
+ gdl_ret = gdl_dma_buf_entry_to_transfer(p_entry, &dma_transfer, true);
+ else if (DMA_CH_IS_RX(ch))
+ gdl_ret = gdl_dma_buf_entry_to_transfer(p_entry, &dma_transfer, false);
+ else
+ GDL_ASSERT(false, GDL_VOIDF(), "");
+ GDL_ASSERT(gdl_ret == GDL_OKAY, GDL_VOIDF(), "gdl_ret = %d", gdl_ret);
+ gps_dl_hw_set_dma_start(ch, &dma_transfer);
+}
+
+void gps_dl_hal_dma_start(enum gps_dl_hal_dma_ch_index ch,
+ struct gdl_dma_buf_entry *p_entry)
+{
+ gps_dl_real_dma_start(ch, p_entry);
+#if GPS_DL_MOCK_HAL
+ gps_dl_mock_dma_start(ch, p_entry);
+#endif
+}
+
+void gps_dl_hal_dma_stop(enum gps_dl_hal_dma_ch_index ch)
+{
+#if GPS_DL_MOCK_HAL
+ gps_dl_mock_dma_stop(ch);
+#endif
+ gps_dl_hw_set_dma_stop(ch);
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_hal.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_hal.c
new file mode 100644
index 0000000..eb3389d
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_hal.c
@@ -0,0 +1,529 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_hal.h"
+#include "gps_dl_hw_api.h"
+#include "gps_dsp_fsm.h"
+#include "gps_each_link.h"
+#include "gps_dl_isr.h"
+#include "gps_dl_context.h"
+#include "gps_dl_name_list.h"
+#include "gps_dl_subsys_reset.h"
+#if GPS_DL_HAS_CONNINFRA_DRV
+#include "conninfra.h"
+#endif
+
+#include "linux/jiffies.h"
+
+
+static bool s_gps_has_data_irq_masked[GPS_DATA_LINK_NUM];
+
+
+void gps_dl_hal_event_send(enum gps_dl_hal_event_id evt,
+ enum gps_dl_link_id_enum link_id)
+{
+#if (GPS_DL_HAS_CTRLD == 0)
+ gps_dl_hal_event_proc(evt, link_id, gps_each_link_get_session_id(link_id));
+#else
+ {
+ struct gps_dl_osal_lxop *pOp;
+ struct gps_dl_osal_signal *pSignal;
+ int iRet;
+
+ pOp = gps_dl_get_free_op();
+ if (!pOp)
+ return;
+
+ pSignal = &pOp->signal;
+ pSignal->timeoutValue = 0;/* send data need to wait ?ms */
+ if (link_id < GPS_DATA_LINK_NUM) {
+ pOp->op.opId = GPS_DL_OPID_HAL_EVENT_PROC;
+ pOp->op.au4OpData[0] = link_id;
+ pOp->op.au4OpData[1] = evt;
+ pOp->op.au4OpData[2] = gps_each_link_get_session_id(link_id);
+ iRet = gps_dl_put_act_op(pOp);
+ } else {
+ gps_dl_put_op_to_free_queue(pOp);
+ /*printf error msg*/
+ return;
+ }
+ }
+#endif
+}
+
+void gps_dl_hal_event_proc(enum gps_dl_hal_event_id evt,
+ enum gps_dl_link_id_enum link_id, int sid_on_evt)
+{
+ struct gps_each_link *p_link = gps_dl_link_get(link_id);
+ struct gdl_dma_buf_entry dma_buf_entry;
+ enum GDL_RET_STATUS gdl_ret;
+ unsigned int write_index;
+ int curr_sid;
+ bool last_session_msg = false;
+ unsigned long j0, j1;
+ bool show_log, reg_rw_log;
+ bool conninfra_okay, dma_irq_en;
+
+ j0 = jiffies;
+ curr_sid = gps_each_link_get_session_id(link_id);
+
+ if (!gps_dl_reset_level_is_none(link_id) ||
+ gps_each_link_get_bool_flag(link_id, LINK_IS_RESETTING)) {
+ /* ack the reset status */
+ last_session_msg = true;
+ } else if (sid_on_evt != curr_sid && sid_on_evt != GPS_EACH_LINK_SID_NO_CHECK) {
+ GDL_LOGXW_EVT(link_id, "curr_sid = %d, evt = %s, on_sid = %d, not matching",
+ curr_sid, gps_dl_hal_event_name(evt), sid_on_evt);
+ last_session_msg = true;
+ } else if (!gps_each_link_is_active(link_id) ||
+ gps_each_link_get_bool_flag(link_id, LINK_TO_BE_CLOSED)) {
+ GDL_LOGXW_EVT(link_id, "curr_sid = %d, evt = %s, on_sid = %d, not active",
+ curr_sid, gps_dl_hal_event_name(evt), sid_on_evt);
+ last_session_msg = true;
+ }
+
+ if (last_session_msg) {
+ /* unmask irq to make it balance */
+ if (evt == GPS_DL_HAL_EVT_D2A_RX_HAS_NODATA) {
+ gps_dl_irq_each_link_unmask(link_id,
+ GPS_DL_IRQ_TYPE_HAS_NODATA, GPS_DL_IRQ_CTRL_FROM_HAL);
+ } else if (evt == GPS_DL_HAL_EVT_D2A_RX_HAS_DATA) {
+ gps_dl_irq_each_link_unmask(link_id,
+ GPS_DL_IRQ_TYPE_HAS_DATA, GPS_DL_IRQ_CTRL_FROM_HAL);
+ } else if (evt == GPS_DL_HAL_EVT_MCUB_HAS_IRQ) {
+ gps_dl_irq_each_link_unmask(link_id,
+ GPS_DL_IRQ_TYPE_MCUB, GPS_DL_IRQ_CTRL_FROM_HAL);
+ } else if (evt == GPS_DL_HAL_EVT_DMA_ISR_PENDING) {
+ /*
+ * do nothing if last_session_msg
+ */
+ }
+ return;
+ }
+
+ if (sid_on_evt == GPS_EACH_LINK_SID_NO_CHECK) {
+ GDL_LOGXW_EVT(link_id, "curr_sid = %d, evt = %s, on_sid = %d, no check",
+ curr_sid, gps_dl_hal_event_name(evt), sid_on_evt);
+ } else if (sid_on_evt <= 0 || sid_on_evt > GPS_EACH_LINK_SID_MAX) {
+ GDL_LOGXW_EVT(link_id, "curr_sid = %d, evt = %s, on_sid = %d, out of range",
+ curr_sid, gps_dl_hal_event_name(evt), sid_on_evt);
+ } else {
+ GDL_LOGXD_EVT(link_id, "curr_sid = %d, evt = %s, on_sid = %d",
+ curr_sid, gps_dl_hal_event_name(evt), sid_on_evt);
+ }
+
+ GDL_LOGXD_EVT(link_id, "evt = %s", gps_dl_hal_event_name(evt));
+ switch (evt) {
+ case GPS_DL_HAL_EVT_D2A_RX_HAS_DATA:
+ gdl_ret = gdl_dma_buf_get_free_entry(
+ &p_link->rx_dma_buf, &dma_buf_entry, true);
+
+ s_gps_has_data_irq_masked[link_id] = true;
+ if (gdl_ret == GDL_OKAY) {
+ gps_dl_hal_d2a_rx_dma_claim_emi_usage(link_id, true);
+ gps_dl_hal_d2a_rx_dma_start(link_id, &dma_buf_entry);
+ } else {
+
+ /* TODO: has pending rx: GDL_FAIL_NOSPACE_PENDING_RX */
+ GDL_LOGXI_DRW(link_id, "rx dma not start due to %s", gdl_ret_to_name(gdl_ret));
+ }
+ break;
+
+ /* TODO: handle the case data_len is just equal to buf_len, */
+ /* the rx_dma_done and usrt_has_nodata both happen. */
+ case GPS_DL_HAL_EVT_D2A_RX_DMA_DONE:
+ /* TODO: to make mock work with it */
+
+ /* stop and clear int flag in isr */
+ /* gps_dl_hal_d2a_rx_dma_stop(link_id); */
+ p_link->rx_dma_buf.dma_working_entry.write_index =
+ p_link->rx_dma_buf.dma_working_entry.read_index;
+
+ /* check whether no data also happen */
+ if (gps_dl_hw_usrt_has_set_nodata_flag(link_id)) {
+ p_link->rx_dma_buf.dma_working_entry.is_nodata = true;
+ gps_dl_hw_usrt_clear_nodata_irq(link_id);
+ } else
+ p_link->rx_dma_buf.dma_working_entry.is_nodata = false;
+
+ gdl_ret = gdl_dma_buf_set_free_entry(&p_link->rx_dma_buf,
+ &p_link->rx_dma_buf.dma_working_entry);
+
+ if (gdl_ret == GDL_OKAY) {
+ p_link->rx_dma_buf.dma_working_entry.is_valid = false;
+ gps_dl_link_wake_up(&p_link->waitables[GPS_DL_WAIT_READ]);
+ }
+
+ gps_dl_hal_d2a_rx_dma_claim_emi_usage(link_id, false);
+ /* mask data irq */
+ if (s_gps_has_data_irq_masked[link_id] == true) {
+ gps_dl_irq_each_link_unmask(link_id, GPS_DL_IRQ_TYPE_HAS_DATA, GPS_DL_IRQ_CTRL_FROM_HAL);
+ s_gps_has_data_irq_masked[link_id] = false;
+ } else
+ GDL_LOGXW_DRW(link_id, "D2A_RX_DMA_DONE while s_gps_has_data_irq_masked is false");
+ break;
+
+ case GPS_DL_HAL_EVT_D2A_RX_HAS_NODATA:
+ /* get rx length */
+ gdl_ret = gps_dl_hal_d2a_rx_dma_get_write_index(link_id, &write_index);
+
+ /* 20181118 for mock, rx dma stop must after get write index */
+ gps_dl_hal_d2a_rx_dma_stop(link_id);
+
+ if (gdl_ret == GDL_OKAY) {
+ /* no need to mask data irq */
+ p_link->rx_dma_buf.dma_working_entry.write_index = write_index;
+ p_link->rx_dma_buf.dma_working_entry.is_nodata = true;
+
+ gdl_ret = gdl_dma_buf_set_free_entry(&p_link->rx_dma_buf,
+ &p_link->rx_dma_buf.dma_working_entry);
+
+ if (gdl_ret != GDL_OKAY)
+ GDL_LOGD("gdl_dma_buf_set_free_entry ret = %s", gdl_ret_to_name(gdl_ret));
+
+ } else
+ GDL_LOGD("gps_dl_hal_d2a_rx_dma_get_write_index ret = %s", gdl_ret_to_name(gdl_ret));
+
+ if (gdl_ret == GDL_OKAY) {
+ p_link->rx_dma_buf.dma_working_entry.is_valid = false;
+ gps_dl_link_wake_up(&p_link->waitables[GPS_DL_WAIT_READ]);
+ }
+
+ gps_dl_hal_d2a_rx_dma_claim_emi_usage(link_id, false);
+ gps_dl_hw_usrt_clear_nodata_irq(link_id);
+ gps_dl_irq_each_link_unmask(link_id, GPS_DL_IRQ_TYPE_HAS_NODATA, GPS_DL_IRQ_CTRL_FROM_HAL);
+ if (gps_dl_test_mask_hasdata_irq_get(link_id)) {
+ GDL_LOGXE(link_id, "test mask hasdata irq, not unmask irq and wait reset");
+ gps_dl_test_mask_hasdata_irq_set(link_id, false);
+ gps_dl_hal_set_irq_dis_flag(link_id, GPS_DL_IRQ_TYPE_HAS_DATA, true);
+ } else {
+ if (s_gps_has_data_irq_masked[link_id] == true) {
+ gps_dl_irq_each_link_unmask(link_id, GPS_DL_IRQ_TYPE_HAS_DATA,
+ GPS_DL_IRQ_CTRL_FROM_HAL);
+ s_gps_has_data_irq_masked[link_id] = false;
+ } else
+ GDL_LOGXW_DRW(link_id, "D2A_RX_HAS_NODATA while s_gps_has_data_irq_masked is false");
+ }
+ break;
+
+ case GPS_DL_HAL_EVT_A2D_TX_DMA_DONE:
+ /* gps_dl_hw_print_usrt_status(link_id); */
+
+ /* data tx finished */
+ gdl_ret = gdl_dma_buf_set_data_entry(&p_link->tx_dma_buf,
+ &p_link->tx_dma_buf.dma_working_entry);
+
+ p_link->tx_dma_buf.dma_working_entry.is_valid = false;
+
+ GDL_LOGD("gdl_dma_buf_set_data_entry ret = %s", gdl_ret_to_name(gdl_ret));
+
+ /* stop tx dma, should stop and clear int flag in isr */
+ /* gps_dl_hal_a2d_tx_dma_stop(link_id); */
+
+ /* wakeup writer if it's pending on it */
+ gps_dl_link_wake_up(&p_link->waitables[GPS_DL_WAIT_WRITE]);
+ gps_dl_hal_a2d_tx_dma_claim_emi_usage(link_id, false);
+ gps_dl_link_start_tx_dma_if_has_data(link_id);
+ break;
+
+ case GPS_DL_HAL_EVT_DMA_ISR_PENDING:
+ conninfra_okay = gps_dl_conninfra_is_okay_or_handle_it(NULL, true);
+ dma_irq_en = gps_dl_hal_get_dma_irq_en_flag();
+
+ GDL_LOGXE(link_id, "conninfra_okay = %d, dma_irq_en = %d", conninfra_okay, dma_irq_en);
+ if (conninfra_okay && !dma_irq_en) {
+ gps_dl_irq_unmask_dma_intr(GPS_DL_IRQ_CTRL_FROM_HAL);
+ gps_dl_hal_set_dma_irq_en_flag(true);
+ }
+ break;
+
+ case GPS_DL_HAL_EVT_MCUB_HAS_IRQ:
+ reg_rw_log = gps_dl_log_reg_rw_is_on(GPS_DL_REG_RW_MCUB_IRQ_HANDLER);
+ if (reg_rw_log)
+ show_log = gps_dl_set_show_reg_rw_log(true);
+ if (!gps_dl_hal_mcub_flag_handler(link_id)) {
+ GDL_LOGXE(link_id, "mcub_flag_handler not okay, not unmask irq and wait reset");
+ gps_dl_hal_set_mcub_irq_dis_flag(link_id, true);
+ } else
+ gps_dl_irq_each_link_unmask(link_id, GPS_DL_IRQ_TYPE_MCUB, GPS_DL_IRQ_CTRL_FROM_HAL);
+ if (reg_rw_log)
+ gps_dl_set_show_reg_rw_log(show_log);
+ break;
+
+#if 0
+ case GPS_DL_HAL_EVT_DSP_ROM_START:
+ gps_dsp_fsm(GPS_DSP_EVT_RESET_DONE, link_id);
+
+ /* if has pending data, can send it now */
+ gdl_ret = gdl_dma_buf_get_data_entry(&p_link->tx_dma_buf, &dma_buf_entry);
+ if (gdl_ret == GDL_OKAY)
+ gps_dl_hal_a2d_tx_dma_start(link_id, &dma_buf_entry);
+ break;
+
+ case GPS_DL_HAL_EVT_DSP_RAM_START:
+ gps_dsp_fsm(GPS_DSP_EVT_RAM_CODE_READY, link_id);
+
+ /* start reg polling */
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ j1 = jiffies;
+ GDL_LOGXI_EVT(link_id, "evt = %s, on_sid = %d, dj = %lu",
+ gps_dl_hal_event_name(evt), sid_on_evt, j1 - j0);
+}
+
+void gps_dl_hal_mcub_vcore_req_handler(enum gps_dl_link_id_enum link_id, unsigned int param)
+{
+ bool show_log;
+ int status = 0;
+
+ show_log = gps_dl_set_show_reg_rw_log(true);
+ switch (param) {
+ case GPS_MCUB_F0D0_ACTION_VCORE_PARAM_REQUEST_0_6V:
+ status = gps_dl_get_vcore_power();
+ if (status) {
+ GDL_LOGXW(link_id, "gps get vcore power fail, ret = %d\n", status);
+ gps_dl_hw_set_mcub_a2d1_cfg(link_id, GPS_DSP_CFG_ACTION_PARAM_ACK_VCORE_RELEASE);
+ } else
+ gps_dl_hw_set_mcub_a2d1_cfg(link_id, GPS_DSP_CFG_ACTION_PARAM_ACK_VCORE_0_6V);
+ break;
+
+ case GPS_MCUB_F0D0_ACTION_VCORE_PARAM_RELEASE_VCORE:
+ status = gps_dl_put_vcore_power(0);
+ if (status)
+ GDL_LOGXW(link_id, "gps put vcore power fail, ret = %d\n", status);
+ gps_dl_hw_set_mcub_a2d1_cfg(link_id, GPS_DSP_CFG_ACTION_PARAM_ACK_VCORE_RELEASE);
+ break;
+
+ default:
+ /* do nothing */
+ break;
+ }
+ gps_dl_set_show_reg_rw_log(show_log);
+}
+
+void gps_dl_hal_mcub_f0d0_req_handler(enum gps_dl_link_id_enum link_id, unsigned int d2a_data)
+{
+ unsigned int action;
+ unsigned int param;
+
+
+ action = GPS_MCUB_D2A_DATA_GET_ACTION(d2a_data);
+ param = GPS_MCUB_D2A_DATA_GET_PARAM(d2a_data);
+ GDL_LOGXW(link_id, "action = %u, param = %u", action, param);
+
+ switch (action) {
+ case GPS_MCUB_F0D0_ACTION_VCORE:
+ gps_dl_hal_mcub_vcore_req_handler(link_id, param);
+ break;
+
+ default:
+ /* do nothing */
+ break;
+ }
+}
+
+bool gps_dl_hal_mcub_flag_handler(enum gps_dl_link_id_enum link_id)
+{
+ struct gps_dl_hal_mcub_info d2a;
+ bool conninfra_okay;
+ int status = 0;
+
+ /* Todo: while condition make sure DSP is on and session ID */
+ while (1) {
+ conninfra_okay = gps_dl_conninfra_is_okay_or_handle_it(NULL, true);
+ if (!conninfra_okay) {
+ GDL_LOGXE(link_id, "conninfra_okay = %d", conninfra_okay);
+ return false; /* not okay */
+ }
+
+ gps_dl_hw_get_mcub_info(link_id, &d2a);
+ if (d2a.flag == 0)
+ break;
+
+ if (d2a.flag == GPS_MCUB_D2AF_MASK_DSP_REG_READ_READY) {
+ /* do nothing
+ *
+ * only "reg read ready" in flag bits, print the information in
+ * gps_each_dsp_reg_read_ack, rather than here.
+ */
+ } else {
+ GDL_LOGXI(link_id, "d2a: flag = 0x%04x, d0 = 0x%04x, d1 = 0x%04x",
+ d2a.flag, d2a.dat0, d2a.dat1);
+ }
+
+ if (d2a.flag == 0xdeadfeed) {
+ gps_dl_hw_dump_host_csr_gps_info(true);
+ gps_dl_hw_dump_sleep_prot_status();
+
+ GDL_LOGXE(link_id, "deadfeed, trigger connsys reset");
+ gps_dl_trigger_connsys_reset();
+ return false;
+ }
+
+ /* Todo: if (dsp is off) -> break */
+ /* Note: clear flag before check and handle the flage event,
+ * avoiding race condtion when dsp do "too fast twice ack".
+ * EX: gps_each_dsp_reg_gourp_read_next
+ */
+ gps_dl_hw_clear_mcub_d2a_flag(link_id, d2a.flag);
+
+ if (d2a.flag & GPS_MCUB_D2AF_MASK_DSP_RESET_DONE) {
+ /* gps_dl_hal_event_send(GPS_DL_HAL_EVT_DSP_ROM_START, link_id); */
+ gps_dsp_fsm(GPS_DSP_EVT_RESET_DONE, link_id);
+ }
+
+ if (d2a.flag & GPS_MCUB_D2AF_MASK_DSP_RAMCODE_READY) {
+ if (d2a.dat1 == 0xDEAD || d2a.dat1 == 0xBEEF) {
+ GDL_LOGXW(link_id,
+ "d2a: flag = 0x%04x, d0 = 0x%04x, d1 = 0x%04x, do dump",
+ d2a.flag, d2a.dat0, d2a.dat1);
+ gps_dl_hw_dump_host_csr_gps_info(true);
+#if GPS_DL_HAS_CONNINFRA_DRV
+ /* API to check and dump host csr */
+ conninfra_is_bus_hang();
+#else
+ gps_dl_hw_dump_host_csr_conninfra_info(true);
+#endif
+ gps_dl_hw_print_hw_status(link_id, true);
+ gps_dl_hw_dump_host_csr_gps_info(true);
+ continue;
+ }
+
+ /* bypass gps_dsp_fsm if ariving here and the status is already working */
+ if (GPS_DSP_ST_WORKING == gps_dsp_state_get(link_id)) {
+ GDL_LOGXW(link_id,
+ "d2a: flag = 0x%04x, d0 = 0x%04x, d1 = 0x%04x, request",
+ d2a.flag, d2a.dat0, d2a.dat1);
+
+ if (GPS_DATA_LINK_ID0 == link_id) {
+ /* currently, only accept L1 request */
+ gps_dl_hal_mcub_f0d0_req_handler(link_id, d2a.dat0);
+ }
+
+ continue;
+ }
+
+ if (link_id == GPS_DATA_LINK_ID0) {
+ status = gps_dl_put_vcore_power(0);
+ if (status)
+ GDL_LOGXW(link_id, "gps put vcore power fail, ret = %d\n", status);
+ }
+
+ /* gps_dl_hal_event_send(GPS_DL_HAL_EVT_DSP_RAM_START, link_id); */
+ gps_dsp_fsm(GPS_DSP_EVT_RAM_CODE_READY, link_id);
+
+ /* start reg polling */
+ gps_each_dsp_reg_gourp_read_start(link_id, false, 1);
+ }
+
+ if (d2a.flag & GPS_MCUB_D2AF_MASK_DSP_REG_READ_READY)
+ gps_each_dsp_reg_read_ack(link_id, &d2a);
+
+ }
+
+ return true;
+}
+
+
+unsigned int g_gps_dl_hal_emi_usage_bitmask;
+
+void gps_dl_hal_emi_usage_init(void)
+{
+ unsigned int old_mask;
+
+ old_mask = g_gps_dl_hal_emi_usage_bitmask;
+ g_gps_dl_hal_emi_usage_bitmask = 0;
+
+ if (old_mask)
+ GDL_LOGW("mask is 0x%x, force it to 0", old_mask);
+ else
+ GDL_LOGD("mask is 0");
+
+ /* Not claim/disclaim it for low power
+ * gps_dl_hal_emi_usage_claim(GPS_DL_EMI_USER_GPS_ON, true);
+ */
+}
+
+void gps_dl_hal_emi_usage_deinit(void)
+{
+ unsigned int old_mask;
+
+ /* Not claim/disclaim it for low power
+ * gps_dl_hal_emi_usage_claim(GPS_DL_EMI_USER_GPS_ON, false);
+ */
+
+ old_mask = g_gps_dl_hal_emi_usage_bitmask;
+
+ if (old_mask)
+ GDL_LOGW("mask is 0x%x, force to release emi usage", old_mask);
+ else
+ GDL_LOGD("mask is 0");
+
+ /* force to release it anyway */
+ gps_dl_hw_gps_sw_request_emi_usage(false);
+}
+
+void gps_dl_hal_emi_usage_claim(enum gps_dl_hal_emi_user user, bool use_emi)
+{
+ unsigned int old_mask, new_mask;
+ bool changed = false, usage = false;
+
+ /* TODO: protect them using spin lock to make it more safe,
+ * currently only one thread call me, no racing.
+ */
+ old_mask = g_gps_dl_hal_emi_usage_bitmask;
+ if (use_emi)
+ g_gps_dl_hal_emi_usage_bitmask = old_mask | (1UL << user);
+ else
+ g_gps_dl_hal_emi_usage_bitmask = old_mask & ~(1UL << user);
+ new_mask = g_gps_dl_hal_emi_usage_bitmask;
+
+ if (old_mask == 0 && new_mask != 0) {
+ gps_dl_hw_gps_sw_request_emi_usage(true);
+ changed = true;
+ usage = true;
+ } else if (old_mask != 0 && new_mask == 0) {
+ gps_dl_hw_gps_sw_request_emi_usage(false);
+ changed = true;
+ usage = false;
+ }
+
+ if (changed) {
+ GDL_LOGD("user = %d, use = %d, old_mask = 0x%x, new_mask = 0x%x, change = %d/%d",
+ user, use_emi, old_mask, new_mask, changed, usage);
+ } else {
+ GDL_LOGD("user = %d, use = %d, old_mask = 0x%x, new_mask = 0x%x, change = %d",
+ user, use_emi, old_mask, new_mask, changed);
+ }
+}
+
+void gps_dl_hal_a2d_tx_dma_claim_emi_usage(enum gps_dl_link_id_enum link_id, bool use_emi)
+{
+ if (link_id == GPS_DATA_LINK_ID0)
+ gps_dl_hal_emi_usage_claim(GPS_DL_EMI_USER_TX_DMA0, use_emi);
+ else if (link_id == GPS_DATA_LINK_ID1)
+ gps_dl_hal_emi_usage_claim(GPS_DL_EMI_USER_TX_DMA1, use_emi);
+}
+
+void gps_dl_hal_d2a_rx_dma_claim_emi_usage(enum gps_dl_link_id_enum link_id, bool use_emi)
+{
+ if (link_id == GPS_DATA_LINK_ID0)
+ gps_dl_hal_emi_usage_claim(GPS_DL_EMI_USER_RX_DMA0, use_emi);
+ else if (link_id == GPS_DATA_LINK_ID1)
+ gps_dl_hal_emi_usage_claim(GPS_DL_EMI_USER_RX_DMA1, use_emi);
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_hal_util.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_hal_util.c
new file mode 100644
index 0000000..a9bff23
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_hal_util.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+
+
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_isr.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_isr.c
new file mode 100644
index 0000000..87a1c85
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_isr.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+#include "gps_dl_isr.h"
+#include "gps_dl_hal.h"
+#include "gps_dl_hw_api.h"
+#include "gps_dl_hal_util.h"
+#include "gps_dsp_fsm.h"
+#include "gps_each_link.h"
+#include "gps/gps_usrt_apb.h"
+#include "gps/gps_l5_usrt_apb.h"
+
+/* TODO: IRQ hwirq, irq_id, gdl_irq_index */
+/* On CTP: hwirq == irq_id */
+/* On Linux: hwirq != irq_id */
+#if GPS_DL_ON_CTP
+/* x_define_irq.h 198 -> 415 */
+#define GPS_DL_IRQ_BASE_ID (GPS_L1_IRQ_BUS_BIT0_ID)
+#else
+#define GPS_DL_IRQ_BASE_ID (383) /* (415 - 32) */
+#endif
+
+#define GPS_IRQ_ID_DL0_HAS_DATA (GPS_DL_IRQ_BASE_ID + 0)
+#define GPS_IRQ_ID_DL0_HAS_NODATA (GPS_DL_IRQ_BASE_ID + 1)
+#define GPS_IRQ_ID_DL0_MCUB (GPS_DL_IRQ_BASE_ID + 2)
+#define GPS_IRQ_ID_DL1_HAS_DATA (GPS_DL_IRQ_BASE_ID + 3)
+#define GPS_IRQ_ID_DL1_HAS_NODATA (GPS_DL_IRQ_BASE_ID + 4)
+#define GPS_IRQ_ID_DL1_MCUB (GPS_DL_IRQ_BASE_ID + 5)
+#define GPS_IRQ_ID_DMA_DONE (GPS_DL_IRQ_BASE_ID + 6)
+
+#if GPS_DL_ON_LINUX
+/* TODO: hwirq and linux irq id */
+int g_gps_irq_index_to_id_table[GPS_DL_IRQ_NUM];
+void gps_dl_irq_set_id(enum gps_dl_irq_index_enum irq_idx, int irq_id)
+{
+ g_gps_irq_index_to_id_table[irq_idx] = irq_id;
+}
+#else
+int g_gps_irq_index_to_id_table[GPS_DL_IRQ_NUM] = {
+ [GPS_DL_IRQ_LINK0_DATA] = GPS_IRQ_ID_DL0_HAS_DATA,
+ [GPS_DL_IRQ_LINK0_NODATA] = GPS_IRQ_ID_DL0_HAS_NODATA,
+ [GPS_DL_IRQ_LINK0_MCUB] = GPS_IRQ_ID_DL0_MCUB,
+ [GPS_DL_IRQ_LINK1_DATA] = GPS_IRQ_ID_DL1_HAS_DATA,
+ [GPS_DL_IRQ_LINK1_NODATA] = GPS_IRQ_ID_DL1_HAS_NODATA,
+ [GPS_DL_IRQ_LINK1_MCUB] = GPS_IRQ_ID_DL1_MCUB,
+ [GPS_DL_IRQ_DMA] = GPS_IRQ_ID_DMA_DONE,
+};
+#endif
+
+int gps_dl_irq_index_to_id(enum gps_dl_irq_index_enum irq_idx)
+{
+ ASSERT_IRQ_IDX(irq_idx, -1);
+ return g_gps_irq_index_to_id_table[irq_idx];
+}
+
+int g_gps_irq_type_to_hwirq_table[GPS_DATA_LINK_NUM][GPS_DL_IRQ_TYPE_NUM] = {
+ [GPS_DATA_LINK_ID0][GPS_DL_IRQ_TYPE_HAS_DATA] =
+ GPS_IRQ_ID_DL0_HAS_DATA,
+ [GPS_DATA_LINK_ID0][GPS_DL_IRQ_TYPE_HAS_NODATA] =
+ GPS_IRQ_ID_DL0_HAS_NODATA,
+ [GPS_DATA_LINK_ID0][GPS_DL_IRQ_TYPE_MCUB] =
+ GPS_IRQ_ID_DL0_MCUB,
+
+ [GPS_DATA_LINK_ID1][GPS_DL_IRQ_TYPE_HAS_DATA] =
+ GPS_IRQ_ID_DL1_HAS_DATA,
+ [GPS_DATA_LINK_ID1][GPS_DL_IRQ_TYPE_HAS_NODATA] =
+ GPS_IRQ_ID_DL1_HAS_NODATA,
+ [GPS_DATA_LINK_ID1][GPS_DL_IRQ_TYPE_MCUB] =
+ GPS_IRQ_ID_DL1_MCUB,
+};
+
+int gps_dl_irq_type_to_hwirq(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_each_link_irq_type irq_type)
+{
+ ASSERT_LINK_ID(link_id, -1);
+ ASSERT_IRQ_TYPE(irq_type, -1);
+ return g_gps_irq_type_to_hwirq_table[link_id][irq_type];
+}
+
+int g_gps_irq_type_to_index_table[GPS_DATA_LINK_NUM][GPS_DL_IRQ_TYPE_NUM] = {
+ [GPS_DATA_LINK_ID0][GPS_DL_IRQ_TYPE_HAS_DATA] =
+ GPS_DL_IRQ_LINK0_DATA,
+ [GPS_DATA_LINK_ID0][GPS_DL_IRQ_TYPE_HAS_NODATA] =
+ GPS_DL_IRQ_LINK0_NODATA,
+ [GPS_DATA_LINK_ID0][GPS_DL_IRQ_TYPE_MCUB] =
+ GPS_DL_IRQ_LINK0_MCUB,
+
+ [GPS_DATA_LINK_ID1][GPS_DL_IRQ_TYPE_HAS_DATA] =
+ GPS_DL_IRQ_LINK1_DATA,
+ [GPS_DATA_LINK_ID1][GPS_DL_IRQ_TYPE_HAS_NODATA] =
+ GPS_DL_IRQ_LINK1_NODATA,
+ [GPS_DATA_LINK_ID1][GPS_DL_IRQ_TYPE_MCUB] =
+ GPS_DL_IRQ_LINK1_MCUB,
+
+};
+
+int gps_dl_irq_type_to_id(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_each_link_irq_type irq_type)
+{
+ int irq_index;
+ int irq_id;
+
+ ASSERT_LINK_ID(link_id, -1);
+ ASSERT_IRQ_TYPE(irq_type, -1);
+
+ irq_index = g_gps_irq_type_to_index_table[link_id][irq_type];
+ irq_id = g_gps_irq_index_to_id_table[irq_index];
+
+ return irq_id;
+}
+
+void gps_dl_irq_each_link_control(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_each_link_irq_type irq_type, bool mask_it,
+ enum gps_dl_irq_ctrl_from from)
+{
+ int irq_id;
+
+ ASSERT_LINK_ID(link_id, GDL_VOIDF());
+
+ irq_id = gps_dl_irq_type_to_id(link_id, irq_type);
+
+ GDL_LOGXD(link_id, "irq ctrl: from = %d, mask = %d, type = %d, irq_id = %d",
+ from, mask_it, irq_type, irq_id);
+#if !GPS_DL_HW_IS_MOCK
+ if (mask_it)
+ gps_dl_irq_mask(irq_id, from);
+ else
+ gps_dl_irq_unmask(irq_id, from);
+#endif
+}
+
+void gps_dl_irq_each_link_mask(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_each_link_irq_type irq_type, enum gps_dl_irq_ctrl_from from)
+{
+#if (GPS_DL_ON_CTP && !GPS_DL_NO_USE_IRQ)
+ if (irq_type == GPS_DL_IRQ_TYPE_HAS_DATA &&
+ gps_dl_link_is_ready_to_write(link_id))
+ /* Note: CTP isr main always unmask ARM IRQ when return. */
+ /* we need irq not go for some cases, so musk it form GPS side. */
+ gps_dl_hw_usrt_rx_irq_enable(link_id, false);
+#endif
+ gps_dl_irq_each_link_control(link_id, irq_type, true, from);
+}
+
+void gps_dl_irq_each_link_unmask(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_each_link_irq_type irq_type, enum gps_dl_irq_ctrl_from from)
+{
+#if (GPS_DL_ON_CTP && !GPS_DL_NO_USE_IRQ)
+ if (irq_type == GPS_DL_IRQ_TYPE_HAS_DATA &&
+ gps_dl_link_is_ready_to_write(link_id))
+ gps_dl_hw_usrt_rx_irq_enable(link_id, true);
+#endif
+ gps_dl_irq_each_link_control(link_id, irq_type, false, from);
+}
+
+void gps_dl_irq_mask_dma_intr(enum gps_dl_irq_ctrl_from from)
+{
+ GDL_LOGD("from = %d", from);
+#if !GPS_DL_HW_IS_MOCK
+ gps_dl_irq_mask(gps_dl_irq_index_to_id(GPS_DL_IRQ_DMA), from);
+#endif
+}
+
+void gps_dl_irq_unmask_dma_intr(enum gps_dl_irq_ctrl_from from)
+{
+ GDL_LOGD("from = %d", from);
+#if !GPS_DL_HW_IS_MOCK
+ gps_dl_irq_unmask(gps_dl_irq_index_to_id(GPS_DL_IRQ_DMA), from);
+#endif
+}
+
+void gps_dl_isr_usrt_has_data(enum gps_dl_link_id_enum link_id)
+{
+ GDL_LOGXD(link_id, "start");
+ gps_dl_irq_each_link_mask(link_id, GPS_DL_IRQ_TYPE_HAS_DATA, GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR);
+
+ if (gps_each_link_is_active(link_id))
+ gps_dl_hal_event_send(GPS_DL_HAL_EVT_D2A_RX_HAS_DATA, link_id);
+ else {
+ /* NOTE: ctrld has already unmask it, still unmask here to keep balance */
+ gps_dl_irq_each_link_unmask(link_id, GPS_DL_IRQ_TYPE_HAS_DATA,
+ GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR);
+ GDL_LOGXD(link_id, "bypass due to link not active");
+ }
+}
+
+void gps_dl_isr_usrt_has_nodata(enum gps_dl_link_id_enum link_id)
+{
+ GDL_LOGXD(link_id, "ch = %d", GET_RX_DMA_CH_OF(link_id));
+
+ gps_dl_irq_each_link_mask(link_id, GPS_DL_IRQ_TYPE_HAS_NODATA, GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR);
+
+ if (gps_each_link_is_active(link_id))
+ gps_dl_hal_event_send(GPS_DL_HAL_EVT_D2A_RX_HAS_NODATA, link_id);
+ else {
+ gps_dl_irq_each_link_unmask(link_id, GPS_DL_IRQ_TYPE_HAS_NODATA,
+ GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR);
+ GDL_LOGXD(link_id, "bypass due to link not active");
+ }
+}
+
+void gps_dl_isr_d2a_rx_dma_done(enum gps_dl_link_id_enum link_id)
+{
+ GDL_LOGXD(link_id, "ch = %d", GET_RX_DMA_CH_OF(link_id));
+
+ /* gps_dl_irq_each_link_mask(link_id, GPS_DL_IRQ_TYPE_MCUB); */
+ gps_dl_hal_d2a_rx_dma_stop(link_id);
+
+ gps_dl_hal_event_send(GPS_DL_HAL_EVT_D2A_RX_DMA_DONE, link_id);
+}
+
+void gps_dl_isr_a2d_tx_dma_done(enum gps_dl_link_id_enum link_id)
+{
+ GDL_LOGXD(link_id, "ch = %d", GET_TX_DMA_CH_OF(link_id));
+
+ /* gps_dl_irq_mask_dma_intr(); */
+ gps_dl_hal_a2d_tx_dma_stop(link_id);
+
+ /* update dma buf write pointor */
+ /* notify controller thread */
+ gps_dl_hal_event_send(GPS_DL_HAL_EVT_A2D_TX_DMA_DONE, link_id);
+
+ /* by ctrld thread determine whether start next dma session */
+}
+
+void gps_dl_isr_dma_done(void)
+{
+ enum gps_dl_hal_dma_ch_index i;
+
+ gps_dl_irq_mask_dma_intr(GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR);
+
+ if (!gps_dl_conninfra_is_readable()) {
+ /* set it for gps_ctrld to check, avoiding twice mask */
+ gps_dl_hal_set_dma_irq_en_flag(false);
+ gps_dl_hal_event_send(GPS_DL_HAL_EVT_DMA_ISR_PENDING, GPS_DATA_LINK_ID0);
+ gps_dl_hal_event_send(GPS_DL_HAL_EVT_DMA_ISR_PENDING, GPS_DATA_LINK_ID1);
+ GDL_LOGE("pending due to readable check fail");
+ return;
+ }
+
+ /* dma isr must copy the data and restore the intr flag
+ * no need to copy data, the data is copied in ctrld thread
+ */
+
+ /* TODO: not always starts on i = 0 to make it's fair for each DMA ch */
+ for (i = 0; i < GPS_DL_DMA_CH_NUM; i++) {
+ /* TODO: is the dma ch is active */
+
+ if (gps_dl_hw_get_dma_int_status(i)) {
+#if 0
+ DMA_Stop((kal_uint8)(index));
+ set_dma_acki(index);
+ while (DMA_CheckRunStat(index))
+ ;
+ DMA_Clock_Disable(index);
+#endif
+ switch (i) {
+ case GPS_DL_DMA_LINK0_A2D:
+ gps_dl_isr_a2d_tx_dma_done(GPS_DATA_LINK_ID0);
+ break;
+ case GPS_DL_DMA_LINK0_D2A:
+ gps_dl_isr_d2a_rx_dma_done(GPS_DATA_LINK_ID0);
+ break;
+ case GPS_DL_DMA_LINK1_A2D:
+ gps_dl_isr_a2d_tx_dma_done(GPS_DATA_LINK_ID1);
+ break;
+ case GPS_DL_DMA_LINK1_D2A:
+ gps_dl_isr_d2a_rx_dma_done(GPS_DATA_LINK_ID1);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ /* TODO: end for-loop until all DMA is stopped */
+
+ gps_dl_irq_unmask_dma_intr(GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR);
+}
+
+void gps_dl_isr_mcub(enum gps_dl_link_id_enum link_id)
+{
+ GDL_LOGXD(link_id, "start");
+ gps_dl_irq_each_link_mask(link_id, GPS_DL_IRQ_TYPE_MCUB, GPS_DL_IRQ_CTRL_FROM_ISR);
+
+ if (gps_each_link_is_active(link_id))
+ gps_dl_hal_event_send(GPS_DL_HAL_EVT_MCUB_HAS_IRQ, link_id);
+ else {
+ gps_dl_irq_each_link_unmask(link_id, GPS_DL_IRQ_TYPE_MCUB,
+ GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR);
+ GDL_LOGXD(link_id, "bypass due to link not active");
+ }
+}
+
+#if GPS_DL_ON_CTP
+void gps_dl_isr_dl0_has_data(void)
+{
+ gps_dl_isr_usrt_has_data(GPS_DATA_LINK_ID0);
+}
+
+void gps_dl_isr_dl0_has_nodata(void)
+{
+ gps_dl_isr_usrt_has_nodata(GPS_DATA_LINK_ID0);
+}
+
+void gps_dl_isr_dl0_mcub(void)
+{
+ gps_dl_isr_mcub(GPS_DATA_LINK_ID0);
+}
+
+void gps_dl_isr_dl1_has_data(void)
+{
+ gps_dl_isr_usrt_has_data(GPS_DATA_LINK_ID1);
+}
+
+void gps_dl_isr_dl1_has_nodata(void)
+{
+ gps_dl_isr_usrt_has_nodata(GPS_DATA_LINK_ID1);
+}
+
+void gps_dl_isr_dl1_mcub(void)
+{
+ gps_dl_isr_mcub(GPS_DATA_LINK_ID1);
+}
+#endif
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_mcub.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_mcub.c
new file mode 100644
index 0000000..920c8b4
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_mcub.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+#include "gps_dl_log.h"
+#include "gps_dl_hw_api.h"
+#include "gps_dl_hw_dep_api.h"
+#include "gps_dsp_fsm.h"
+
+const unsigned int c_gps_dsp_reg_list[GPS_DATA_LINK_NUM][GPS_DSP_REG_POLL_MAX] = {
+ GPS_L1_REG_POLL_LIST,
+ GPS_L5_REG_POLL_LIST
+};
+
+const unsigned int c_gps_dsp_reg_dbg_list[GPS_DATA_LINK_NUM][GPS_DSP_REG_DBG_POLL_MAX] = {
+ GPS_L1_REG_DBG_POLL_LIST,
+ GPS_L5_REG_DBG_POLL_LIST
+};
+
+struct gps_each_dsp_reg_read_context {
+ bool poll_ongoing;
+ int poll_index;
+ unsigned int poll_addr;
+
+ /* a "poll" means one register in c_gps_dsp_reg_list.
+ * a "round" means a round to poll all registers in c_gps_dsp_reg_list.
+ * sometimes for debug we need for several rounds
+ * to check the changing of the values of each register.
+ */
+ unsigned int round_max;
+ unsigned int round_index;
+ const unsigned int *poll_list_ptr;
+ int poll_list_len;
+};
+
+struct gps_each_dsp_reg_read_context g_gps_each_dsp_reg_read_context[GPS_DATA_LINK_NUM];
+
+
+enum GDL_RET_STATUS gps_each_dsp_reg_read_request(
+ enum gps_dl_link_id_enum link_id, unsigned int reg_addr)
+{
+ enum GDL_RET_STATUS ret;
+
+ ASSERT_LINK_ID(link_id, GDL_FAIL_INVAL);
+ ret = gps_dl_hw_mcub_dsp_read_request(link_id, reg_addr);
+
+ if (ret == GDL_OKAY) {
+ g_gps_each_dsp_reg_read_context[link_id].poll_addr = reg_addr;
+ g_gps_each_dsp_reg_read_context[link_id].poll_ongoing = true;
+ }
+
+ return ret;
+}
+
+void gps_each_dsp_reg_gourp_read_next(enum gps_dl_link_id_enum link_id, bool restart)
+{
+ unsigned int reg_addr;
+ enum GDL_RET_STATUS ret;
+ struct gps_each_dsp_reg_read_context *p_read_context;
+ int i;
+
+ ASSERT_LINK_ID(link_id, GDL_VOIDF());
+ p_read_context = &g_gps_each_dsp_reg_read_context[link_id];
+ if (restart) {
+ p_read_context->poll_index = 0;
+ p_read_context->round_index = 0;
+ } else {
+ p_read_context->poll_index++;
+ if (p_read_context->poll_index >= p_read_context->poll_list_len) {
+ p_read_context->round_index++;
+ if (p_read_context->round_index >= p_read_context->round_max) {
+ /* all polling end */
+ return;
+ }
+ /* next round */
+ p_read_context->poll_index = 0;
+ }
+ }
+
+ i = p_read_context->poll_index;
+ reg_addr = p_read_context->poll_list_ptr[i];
+ ret = gps_each_dsp_reg_read_request(link_id, reg_addr);
+ GDL_LOGXD(link_id, "i = %d/%d, addr = 0x%04x, status = %s",
+ i, p_read_context->poll_list_len, reg_addr, gdl_ret_to_name(ret));
+}
+
+void gps_each_dsp_reg_read_ack(
+ enum gps_dl_link_id_enum link_id, const struct gps_dl_hal_mcub_info *p_d2a)
+{
+ ASSERT_LINK_ID(link_id, GDL_VOIDF());
+
+ GDL_LOGXI(link_id,
+ "n = %d/%d, addr = 0x%04x, val = 0x%04x/0x%04x, round = %d/%d",
+ g_gps_each_dsp_reg_read_context[link_id].poll_index + 1,
+ g_gps_each_dsp_reg_read_context[link_id].poll_list_len,
+ g_gps_each_dsp_reg_read_context[link_id].poll_addr,
+ p_d2a->dat0, p_d2a->dat1,
+ g_gps_each_dsp_reg_read_context[link_id].round_index + 1,
+ g_gps_each_dsp_reg_read_context[link_id].round_max);
+
+ g_gps_each_dsp_reg_read_context[link_id].poll_ongoing = false;
+ gps_each_dsp_reg_gourp_read_next(link_id, false);
+}
+
+void gps_each_dsp_reg_gourp_read_start(enum gps_dl_link_id_enum link_id,
+ bool dbg, unsigned int round_max)
+{
+ unsigned int a2d_flag;
+ struct gps_dl_hal_mcub_info d2a;
+
+ ASSERT_LINK_ID(link_id, GDL_VOIDF());
+
+ if (g_gps_each_dsp_reg_read_context[link_id].poll_ongoing) {
+ GDL_LOGXW(link_id, "n = %d/%d, addr = 0x%04x, seem busy, check it",
+ g_gps_each_dsp_reg_read_context[link_id].poll_index + 1,
+ g_gps_each_dsp_reg_read_context[link_id].poll_list_len,
+ g_gps_each_dsp_reg_read_context[link_id].poll_addr);
+
+ /* TODO: show hw status */
+ a2d_flag = gps_dl_hw_get_mcub_a2d_flag(link_id);
+ gps_dl_hw_get_mcub_info(link_id, &d2a);
+ GDL_LOGXW(link_id, "a2d_flag = %d, d2a_flag = %d, d0 = 0x%04x, d1 = 0x%04x",
+ a2d_flag, d2a.flag, d2a.dat0, d2a.dat1);
+
+ if (a2d_flag & GPS_MCUB_A2DF_MASK_DSP_REG_READ_REQ ||
+ d2a.flag & GPS_MCUB_D2AF_MASK_DSP_REG_READ_READY) {
+ /* real busy, bypass */
+ return;
+ }
+ }
+
+ if (dbg) {
+ g_gps_each_dsp_reg_read_context[link_id].poll_list_ptr =
+ &c_gps_dsp_reg_dbg_list[link_id][0];
+ g_gps_each_dsp_reg_read_context[link_id].poll_list_len = GPS_DSP_REG_DBG_POLL_MAX;
+ } else {
+ g_gps_each_dsp_reg_read_context[link_id].poll_list_ptr =
+ &c_gps_dsp_reg_list[link_id][0];
+ g_gps_each_dsp_reg_read_context[link_id].poll_list_len = GPS_DSP_REG_POLL_MAX;
+ }
+ g_gps_each_dsp_reg_read_context[link_id].round_max = round_max;
+ gps_each_dsp_reg_gourp_read_next(link_id, true);
+}
+
+void gps_each_dsp_reg_gourp_read_init(enum gps_dl_link_id_enum link_id)
+{
+ ASSERT_LINK_ID(link_id, GDL_VOIDF());
+
+ memset(&g_gps_each_dsp_reg_read_context[link_id], 0,
+ sizeof(g_gps_each_dsp_reg_read_context[link_id]));
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_power_ctrl.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_power_ctrl.c
new file mode 100644
index 0000000..1da21c4
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_power_ctrl.c
@@ -0,0 +1,657 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+#include "gps_dl_context.h"
+
+#include "gps_dl_hal.h"
+#include "gps_dl_hw_api.h"
+#include "gps_dl_hal.h"
+#if GPS_DL_MOCK_HAL
+#include "gps_mock_hal.h"
+#endif
+#if GPS_DL_HAS_CONNINFRA_DRV
+#if GPS_DL_ON_LINUX
+#include "conninfra.h"
+#elif GPS_DL_ON_CTP
+#include "conninfra_ext.h"
+#endif
+#endif
+
+#if GPS_DL_HAS_PLAT_DRV
+#include "gps_dl_linux_plat_drv.h"
+#endif
+#if GPS_DL_ON_CTP
+#include "gps_dl_ctp.h"
+#endif
+
+/* TODO: move them into a single structure */
+bool g_gps_common_on;
+bool g_gps_dsp_on_array[GPS_DATA_LINK_NUM];
+int g_gps_dsp_off_ret_array[GPS_DATA_LINK_NUM];
+bool g_gps_conninfa_on;
+bool g_gps_pta_init_done;
+bool g_gps_tia_on;
+bool g_gps_dma_irq_en;
+bool g_gps_irqs_dis[GPS_DATA_LINK_NUM][GPS_DL_IRQ_TYPE_NUM];
+bool g_gps_need_clk_ext[GPS_DATA_LINK_NUM];
+int g_gps_conn_clock_flag = GPSDL_CLOCK_FLAG_COTMS;
+unsigned int g_conn_user;
+
+bool gps_dl_hal_get_dma_irq_en_flag(void)
+{
+ bool enable;
+
+ /* spin lock protection between gps_dl_isr_dma_done and gps_kctrld
+ * both link 0 & 1 spin lock can be used, use 0's.
+ */
+ gps_each_link_spin_lock_take(GPS_DATA_LINK_ID0, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ enable = g_gps_dma_irq_en;
+ gps_each_link_spin_lock_give(GPS_DATA_LINK_ID0, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ return enable;
+}
+
+void gps_dl_hal_set_dma_irq_en_flag(bool enable)
+{
+ gps_each_link_spin_lock_take(GPS_DATA_LINK_ID0, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ g_gps_dma_irq_en = enable;
+ gps_each_link_spin_lock_give(GPS_DATA_LINK_ID0, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+}
+
+bool gps_dl_hal_get_mcub_irq_dis_flag(enum gps_dl_link_id_enum link_id)
+{
+ return gps_dl_hal_get_irq_dis_flag(link_id, GPS_DL_IRQ_TYPE_MCUB);
+}
+
+void gps_dl_hal_set_mcub_irq_dis_flag(enum gps_dl_link_id_enum link_id, bool disable)
+{
+ gps_dl_hal_set_irq_dis_flag(link_id, GPS_DL_IRQ_TYPE_MCUB, disable);
+}
+
+bool gps_dl_hal_get_irq_dis_flag(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_each_link_irq_type type)
+{
+ bool disable;
+
+ ASSERT_LINK_ID(link_id, false);
+ ASSERT_IRQ_TYPE(type, false);
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ disable = g_gps_irqs_dis[link_id][type];
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ return disable;
+}
+
+void gps_dl_hal_set_irq_dis_flag(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_each_link_irq_type type, bool disable)
+{
+ ASSERT_LINK_ID(link_id, GDL_VOIDF());
+ ASSERT_IRQ_TYPE(type, GDL_VOIDF());
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ g_gps_irqs_dis[link_id][type] = disable;
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+}
+
+bool gps_dl_hal_get_need_clk_ext_flag(enum gps_dl_link_id_enum link_id)
+{
+ bool need;
+
+ ASSERT_LINK_ID(link_id, false);
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ need = g_gps_need_clk_ext[link_id];
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ return need;
+}
+
+void gps_dl_hal_set_need_clk_ext_flag(enum gps_dl_link_id_enum link_id, bool need)
+{
+ ASSERT_LINK_ID(link_id, GDL_VOIDF());
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ g_gps_need_clk_ext[link_id] = need;
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+}
+
+void gps_dl_hal_link_on_like_op_ctrl(enum gps_dl_link_id_enum link_id, bool like_on)
+{
+ int status = 0;
+
+ /* vcoer 0.6v operation (only for DL0), the cases include:
+ * 1. like_on/off
+ * 2. enter/exit deep sleep/stop mode
+ */
+ if (link_id == GPS_DATA_LINK_ID0) {
+ if (like_on) {
+ /* vcore ctrl in like_on-like operation */
+ gps_dl_set_vcore_flag(&g_gps_dl_vcore_context.flag, gps_dl_procfs_vcore_action);
+ if (gps_dl_procfs_vcore_action == GPS_PROC_VCORE_REQUIRE_ON) {
+ status = gps_dl_get_vcore_power();
+ if (status)
+ GDL_LOGXW(link_id, "gps get vcore power fail, ret = %d\n", status);
+ }
+ } else {
+ /* vcoer ctrl in off-like operation */
+ status = gps_dl_put_vcore_power(1);
+ if (status)
+ GDL_LOGXW(link_id, "gps put vcore power fail, ret = %d\n", status);
+ }
+ }
+}
+
+int gps_dl_hal_link_power_ctrl(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_hal_power_ctrl_op_enum op)
+{
+ bool wakeup_okay;
+ bool conninfra_okay;
+ bool is_on_like_op;
+ int hung_value = 0;
+ int ret = 0;
+
+ wakeup_okay = gps_dl_hw_gps_force_wakeup_conninfra_top_off(true);
+ conninfra_okay = gps_dl_conninfra_is_okay_or_handle_it(&hung_value, true);
+ is_on_like_op = !!(
+ op == GPS_DL_HAL_POWER_ON ||
+ op == GPS_DL_HAL_LEAVE_DPSLEEP ||
+ op == GPS_DL_HAL_LEAVE_DPSTOP);
+ GDL_LOGXW_ONF(link_id,
+ "op = %d, conn_okay = %d/%d/0x%x, gps_common = %d, L1 = %d, L5 = %d, cfg = %d/0x%x",
+ op, wakeup_okay, conninfra_okay, hung_value, g_gps_common_on,
+ g_gps_dsp_on_array[GPS_DATA_LINK_ID0],
+ g_gps_dsp_on_array[GPS_DATA_LINK_ID1],
+ is_on_like_op,
+ gps_dl_hw_get_mcub_a2d1_boot_cfg(link_id, gps_dl_is_1byte_mode()));
+
+ if (is_on_like_op)
+ gps_dl_hal_link_on_like_op_ctrl(link_id, true);
+
+ if (!wakeup_okay && conninfra_okay) {
+#if (GPS_DL_HAS_CONNINFRA_DRV)
+ int trigger_ret;
+ trigger_ret = conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_GPS, "GPS conninfra wake fail");
+ GDL_LOGXE(link_id, "conninfra wake fail, trigger reset ret = %d", trigger_ret);
+#else
+ GDL_LOGXE(link_id, "conninfra wake fail, trigger reset not support");
+#endif
+ ret = -1;
+ } else if (!conninfra_okay && hung_value != 0) {
+ g_gps_common_on = false;
+ g_gps_dsp_on_array[GPS_DATA_LINK_ID0] = false;
+ g_gps_dsp_on_array[GPS_DATA_LINK_ID1] = false;
+ GDL_LOGXE(link_id, "reset flags due to conninfa not okay");
+ ret = -1;
+ } else {
+#if (GPS_DL_HAS_CONNINFRA_DRV)
+ /* Due to GPS on or GPS exit deep sleep/stop mode may change osc_en from 0 to 1,
+ * keeping conninfra_bus_clock will make it more safety.
+ */
+ if (is_on_like_op) {
+ conninfra_bus_clock_ctrl(CONNDRV_TYPE_GPS,
+ CONNINFRA_BUS_CLOCK_WPLL | CONNINFRA_BUS_CLOCK_BPLL, 1);
+ }
+
+ ret = gps_dl_hal_link_power_ctrl_inner(link_id, op);
+
+ if (is_on_like_op) {
+ conninfra_bus_clock_ctrl(CONNDRV_TYPE_GPS,
+ CONNINFRA_BUS_CLOCK_WPLL | CONNINFRA_BUS_CLOCK_BPLL, 0);
+ }
+#else
+ ret = gps_dl_hal_link_power_ctrl_inner(link_id, op);
+#endif
+ }
+ gps_dl_hw_gps_force_wakeup_conninfra_top_off(false);
+
+ if (!is_on_like_op)
+ gps_dl_hal_link_on_like_op_ctrl(link_id, false);
+
+ return ret;
+}
+
+int gps_dl_hal_link_power_ctrl_inner(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_hal_power_ctrl_op_enum op)
+{
+ int dsp_ctrl_ret;
+
+ if (1 == op) {
+ /* GPS common */
+ if (!g_gps_common_on) {
+ if (gps_dl_hw_gps_common_on() != 0)
+ return -1;
+ gps_dl_hal_md_blanking_ctrl(true);
+ g_gps_common_on = true;
+ }
+
+ if (g_gps_dsp_on_array[link_id])
+ return 0;
+ g_gps_dsp_on_array[link_id] = true;
+
+#if GPS_DL_HAS_PLAT_DRV
+ gps_dl_lna_pin_ctrl(link_id, true, false);
+#endif
+#if GPS_DL_MOCK_HAL
+ gps_dl_mock_open(link_id);
+#endif
+
+ if (GPS_DATA_LINK_ID0 == link_id)
+ dsp_ctrl_ret = gps_dl_hw_gps_dsp_ctrl(GPS_L1_DSP_ON);
+ else if (GPS_DATA_LINK_ID1 == link_id)
+ dsp_ctrl_ret = gps_dl_hw_gps_dsp_ctrl(GPS_L5_DSP_ON);
+ else
+ dsp_ctrl_ret = -1;
+ return dsp_ctrl_ret;
+ } else if (3 == op || 5 == op) {
+ gps_dl_lna_pin_ctrl(link_id, true, false);
+ if (GPS_DATA_LINK_ID0 == link_id) {
+ if (3 == op)
+ gps_dl_hw_gps_dsp_ctrl(GPS_L1_DSP_EXIT_DSLEEP);
+ else if (5 == op)
+ gps_dl_hw_gps_dsp_ctrl(GPS_L1_DSP_EXIT_DSTOP);
+ } else if (GPS_DATA_LINK_ID1 == link_id) {
+ if (3 == op)
+ gps_dl_hw_gps_dsp_ctrl(GPS_L5_DSP_EXIT_DSLEEP);
+ else if (5 == op)
+ gps_dl_hw_gps_dsp_ctrl(GPS_L5_DSP_EXIT_DSTOP);
+ }
+ return 0;
+ } else if (2 == op || 4 == op) {
+ if (GPS_DATA_LINK_ID0 == link_id) {
+ if (2 == op)
+ gps_dl_hw_gps_dsp_ctrl(GPS_L1_DSP_ENTER_DSLEEP);
+ else if (4 == op)
+ gps_dl_hw_gps_dsp_ctrl(GPS_L1_DSP_ENTER_DSTOP);
+ } else if (GPS_DATA_LINK_ID1 == link_id) {
+ if (2 == op)
+ gps_dl_hw_gps_dsp_ctrl(GPS_L5_DSP_ENTER_DSLEEP);
+ else if (4 == op)
+ gps_dl_hw_gps_dsp_ctrl(GPS_L5_DSP_ENTER_DSTOP);
+ }
+ gps_dl_lna_pin_ctrl(link_id, false, false);
+ return 0;
+ } else if (0 == op) {
+ if (g_gps_dsp_on_array[link_id]) {
+ g_gps_dsp_on_array[link_id] = false;
+ if (GPS_DATA_LINK_ID0 == link_id) {
+#if 0
+ if (g_gps_dsp_l5_on &&
+ (0x1 == GDL_HW_GET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_ON)))
+ /* TODO: ASSERT SW status and HW status are same */
+#endif
+ g_gps_dsp_off_ret_array[link_id] = gps_dl_hw_gps_dsp_ctrl(GPS_L1_DSP_OFF);
+ } else if (GPS_DATA_LINK_ID1 == link_id) {
+#if 0
+ if (g_gps_dsp_l1_on &&
+ (0x1 == GDL_HW_GET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_ON)))
+ /* TODO: ASSERT SW status and HW status are same */
+#endif
+ g_gps_dsp_off_ret_array[link_id] = gps_dl_hw_gps_dsp_ctrl(GPS_L5_DSP_OFF);
+ }
+
+#if GPS_DL_HAS_PLAT_DRV
+ gps_dl_lna_pin_ctrl(link_id, false, false);
+#endif
+#if GPS_DL_MOCK_HAL
+ gps_dl_mock_close(link_id);
+#endif
+ }
+
+ if (!g_gps_dsp_on_array[GPS_DATA_LINK_ID0] && !g_gps_dsp_on_array[GPS_DATA_LINK_ID1]) {
+ if ((g_gps_dsp_off_ret_array[GPS_DATA_LINK_ID0] != 0) ||
+ (g_gps_dsp_off_ret_array[GPS_DATA_LINK_ID1] != 0)) {
+ GDL_LOGXE(link_id, "l1 ret = %d, l5 ret = %d, force adie off",
+ g_gps_dsp_off_ret_array[GPS_DATA_LINK_ID0],
+ g_gps_dsp_off_ret_array[GPS_DATA_LINK_ID1]);
+ gps_dl_hw_gps_adie_force_off();
+ }
+
+ if (g_gps_common_on) {
+ gps_dl_hal_md_blanking_ctrl(false);
+ g_gps_common_on = false;
+ g_gps_dsp_off_ret_array[GPS_DATA_LINK_ID0] = 0;
+ g_gps_dsp_off_ret_array[GPS_DATA_LINK_ID1] = 0;
+ if (gps_dl_hw_gps_common_off() != 0) {
+ /* already trigger connssy reset if arrive here,
+ * no need to call gps_dl_hw_gps_force_wakeup_conninfra_top_off.
+ */
+ GDL_LOGE("gps_dl_hw_gps_common_off fail");
+ return -1;
+ }
+ }
+ }
+ return 0;
+ }
+ return -1;
+}
+
+void gps_dl_hal_link_clear_hw_pwr_stat(enum gps_dl_link_id_enum link_id)
+{
+ if (GPS_DATA_LINK_ID0 == link_id)
+ gps_dl_hw_gps_dsp_ctrl(GPS_L1_DSP_CLEAR_PWR_STAT);
+ else if (GPS_DATA_LINK_ID1 == link_id)
+ gps_dl_hw_gps_dsp_ctrl(GPS_L5_DSP_CLEAR_PWR_STAT);
+}
+
+int gps_dl_hal_conn_power_ctrl(enum gps_dl_link_id_enum link_id, int op)
+{
+ bool dma_en_flag = gps_dl_hal_get_dma_irq_en_flag();
+
+ GDL_LOGXI_ONF(link_id,
+ "sid = %d, op = %d, conn_user = 0x%x,%d, tia_on = %d, dma_irq_en = %d, mcub_cfg = 0x%x",
+ gps_each_link_get_session_id(link_id),
+ op, g_conn_user, g_gps_conninfa_on, g_gps_tia_on, dma_en_flag,
+ gps_dl_hw_get_mcub_a2d1_boot_cfg(link_id, gps_dl_is_1byte_mode()));
+
+ if (1 == op) {
+ if (g_conn_user == 0) {
+ gps_dl_log_info_show();
+ if (!gps_dl_hal_conn_infra_driver_on())
+ return -1;
+
+ gps_dl_hal_load_clock_flag();
+ gps_dl_emi_remap_calc_and_set();
+#if GPS_DL_HAS_PLAT_DRV
+ gps_dl_wake_lock_hold(true);
+#if GPS_DL_USE_TIA
+ gps_dl_tia_gps_ctrl(true);
+ g_gps_tia_on = true;
+#endif
+#endif
+ gps_dl_irq_unmask_dma_intr(GPS_DL_IRQ_CTRL_FROM_THREAD);
+ gps_dl_hal_set_dma_irq_en_flag(true);
+ }
+ g_conn_user |= (1UL << link_id);
+ } else if (0 == op) {
+ g_conn_user &= ~(1UL << link_id);
+ if (g_conn_user == 0) {
+ if (dma_en_flag) {
+ gps_dl_irq_mask_dma_intr(GPS_DL_IRQ_CTRL_FROM_THREAD);
+ gps_dl_hal_set_dma_irq_en_flag(false);
+ }
+#if GPS_DL_HAS_PLAT_DRV
+#if GPS_DL_USE_TIA
+ if (g_gps_tia_on) {
+ gps_dl_tia_gps_ctrl(false);
+ g_gps_tia_on = false;
+ }
+#endif
+ gps_dl_wake_lock_hold(false);
+#endif
+ gps_dl_hal_conn_infra_driver_off();
+ }
+ }
+
+ return 0;
+}
+
+#define GPS_DL_WAIT_DMA_DONE_TIMEOUT_MS (5)
+void gps_dl_hal_link_confirm_dma_stop(enum gps_dl_link_id_enum link_id)
+{
+ struct gps_each_link *p_link = gps_dl_link_get(link_id);
+ unsigned int conn_user;
+ bool tx_working, rx_working;
+ enum GDL_RET_STATUS stop_tx_status, stop_rx_status;
+ bool old_dma_en, do_dma_en_ctrl;
+
+ /* make sure dma irq is mask done */
+ old_dma_en = gps_dl_hal_get_dma_irq_en_flag();
+ do_dma_en_ctrl = false;
+ if (old_dma_en) {
+ /* Note1: currently, twice mask should not happen here,
+ * due to ISR does mask/unmask pair operations,
+ * except one case, please see Note2
+ */
+ gps_dl_irq_mask_dma_intr(GPS_DL_IRQ_CTRL_FROM_THREAD);
+
+ /* Note2: double-get to check race condition, if en_flag changed
+ * it must gps_dl_isr_dma_done change it, need to unmask to make balance
+ */
+ if (!gps_dl_hal_get_dma_irq_en_flag())
+ gps_dl_irq_unmask_dma_intr(GPS_DL_IRQ_CTRL_FROM_THREAD);
+ else {
+ gps_dl_hal_set_dma_irq_en_flag(false);
+ do_dma_en_ctrl = true;
+ }
+ }
+
+ /* If DMA is working, must stop it when it at proper status ->
+ * polling until it done or timeout
+ */
+ tx_working = p_link->tx_dma_buf.dma_working_entry.is_valid;
+ rx_working = p_link->rx_dma_buf.dma_working_entry.is_valid;
+ stop_tx_status = GDL_OKAY;
+ stop_rx_status = GDL_OKAY;
+
+ if (tx_working) {
+ stop_tx_status = gps_dl_hal_a2d_tx_dma_wait_until_done_and_stop_it(
+ link_id, GPS_DL_WAIT_DMA_DONE_TIMEOUT_MS * 1000, true);
+
+ if (stop_tx_status == GDL_FAIL_TIMEOUT)
+ gps_dl_hal_a2d_tx_dma_stop(link_id);
+ }
+
+ if (rx_working && stop_tx_status != GDL_FAIL_CONN_NOT_OKAY) {
+ stop_rx_status = gps_dl_hal_wait_and_handle_until_usrt_has_nodata_or_rx_dma_done(
+ link_id, GPS_DL_WAIT_DMA_DONE_TIMEOUT_MS * 1000, false);
+
+ if (stop_rx_status == GDL_FAIL_TIMEOUT)
+ gps_dl_hal_d2a_rx_dma_stop(link_id);
+ }
+
+ /* enable the dma irq anyway, leave gps_dl_hal_conn_power_ctrl to disable it */
+ if (do_dma_en_ctrl) {
+ gps_dl_hal_set_dma_irq_en_flag(true);
+ gps_dl_irq_unmask_dma_intr(GPS_DL_IRQ_CTRL_FROM_THREAD);
+ }
+
+ /* check the active users */
+ conn_user = g_conn_user;
+ GDL_LOGXW(link_id, "conn_user = 0x%x, old_dma_en = %d/%d, tx = %d/%s, rx = %d/%s",
+ conn_user, old_dma_en, do_dma_en_ctrl,
+ tx_working, gdl_ret_to_name(stop_tx_status),
+ rx_working, gdl_ret_to_name(stop_rx_status));
+}
+
+bool gps_dl_hal_conn_infra_driver_on(void)
+{
+#if GPS_DL_HAS_CONNINFRA_DRV
+ int ret;
+
+#if GPS_DL_ON_LINUX
+ ret = conninfra_pwr_on(CONNDRV_TYPE_GPS);
+#elif GPS_DL_ON_CTP
+ ret = conninfra_power_on(CONNDRV_TYPE_GPS);
+#endif
+ if (ret != 0) {
+ GDL_LOGE("conninfra_pwr_on fail, ret = %d", ret);
+ return false; /* not okay */
+ }
+ g_gps_conninfa_on = true;
+#endif
+ return true; /* okay */
+}
+
+void gps_dl_hal_conn_infra_driver_off(void)
+{
+#if GPS_DL_HAS_CONNINFRA_DRV
+ int ret;
+
+ if (g_gps_conninfa_on) {
+#if GPS_DL_ON_LINUX
+ ret = conninfra_pwr_off(CONNDRV_TYPE_GPS);
+#elif GPS_DL_ON_CTP
+ ret = conninfra_power_off(CONNDRV_TYPE_GPS);
+#endif
+ if (ret != 0) {
+ GDL_LOGE("conninfra_pwr_off fail, ret = %d", ret);
+
+ /* TODO: trigger whole chip reset? */
+ return;
+ }
+
+ GDL_LOGW("conninfra_pwr_off okay");
+ g_gps_conninfa_on = false;
+ } else
+ GDL_LOGW("conninfra_pwr_off already done");
+#endif
+}
+
+void gps_dl_hal_conn_infra_driver_debug_dump(void)
+{
+#if GPS_DL_HAS_CONNINFRA_DRV
+ GDL_LOGW("conninfra_debug_dump - start");
+ conninfra_debug_dump();
+ GDL_LOGW("conninfra_debug_dump - end");
+ #else
+ GDL_LOGW("conninfra_debug_dump - not support");
+#endif
+}
+
+#if GPS_DL_HAS_PTA
+bool gps_dl_hal_md_blanking_init_pta(void)
+{
+ bool okay, done;
+
+ if (g_gps_pta_init_done) {
+ GDL_LOGW("already init done, do nothing return");
+ return false;
+ }
+
+ if (!gps_dl_hw_is_pta_clk_cfg_ready()) {
+ GDL_LOGE("gps_dl_hw_is_pta_clk_cfg_ready fail");
+ return false;
+ }
+
+ okay = gps_dl_hw_take_conn_coex_hw_sema(100);
+ if (!okay) {
+ GDL_LOGE("gps_dl_hw_take_conn_coex_hw_sema fail");
+ return false;
+ }
+
+ /* do pta uart init firstly */
+ done = gps_dl_hw_is_pta_uart_init_done();
+ if (!done) {
+ okay = gps_dl_hw_init_pta_uart();
+ if (!okay) {
+ gps_dl_hw_give_conn_coex_hw_sema();
+ GDL_LOGE("gps_dl_hw_init_pta_uart fail");
+ return false;
+ }
+ } else
+ GDL_LOGW("pta uart already init done");
+
+ /* do pta init secondly */
+ done = gps_dl_hw_is_pta_init_done();
+ if (!done)
+ gps_dl_hw_init_pta();
+ else
+ GDL_LOGW("pta already init done");
+
+ gps_dl_hw_claim_pta_used_by_gps();
+
+ gps_dl_hw_set_pta_blanking_parameter();
+
+ gps_dl_hw_give_conn_coex_hw_sema();
+
+ /* okay, update flags */
+#if GPS_DL_HAS_PLAT_DRV
+ gps_dl_update_status_for_md_blanking(true);
+#endif
+ g_gps_pta_init_done = true;
+
+ return true; /* okay */
+}
+
+void gps_dl_hal_md_blanking_deinit_pta(void)
+{
+ bool okay;
+
+ /* clear the flags anyway */
+#if GPS_DL_HAS_PLAT_DRV
+ gps_dl_update_status_for_md_blanking(false);
+#endif
+ if (!g_gps_pta_init_done) {
+ GDL_LOGW("already deinit done, do nothing return");
+ return;
+ }
+ g_gps_pta_init_done = false;
+
+ /* Currently, deinit is no need.
+ * Just keep the bellow code for future usage.
+ */
+ okay = gps_dl_hw_take_conn_coex_hw_sema(0); /* 0 stands for polling just one time */
+ if (!okay) {
+ GDL_LOGE("gps_dl_hw_take_conn_coex_hw_sema fail");
+ return;
+ }
+
+ gps_dl_hw_disclaim_pta_used_by_gps();
+
+ if (gps_dl_hw_is_pta_init_done())
+ gps_dl_hw_deinit_pta();
+ else
+ GDL_LOGW("pta already deinit done");
+
+ if (gps_dl_hw_is_pta_uart_init_done())
+ gps_dl_hw_deinit_pta_uart();
+ else
+ GDL_LOGW("pta uart already deinit done");
+
+ gps_dl_hw_give_conn_coex_hw_sema();
+}
+#endif /* GPS_DL_HAS_PTA */
+
+void gps_dl_hal_md_blanking_ctrl(bool on)
+{
+#if GPS_DL_HAS_PTA
+ if (on)
+ gps_dl_hal_md_blanking_init_pta();
+ else
+ gps_dl_hal_md_blanking_deinit_pta();
+#else
+ /* For directly connection case, there is no PTA, just update status for md. */
+#if GPS_DL_HAS_PLAT_DRV
+ gps_dl_update_status_for_md_blanking(on);
+#endif
+#endif
+}
+
+int gps_dl_hal_get_clock_flag(void)
+{
+ return g_gps_conn_clock_flag;
+}
+
+void gps_dl_hal_load_clock_flag(void)
+{
+ int gps_clock_flag;
+#if GPS_DL_HAS_CONNINFRA_DRV
+ enum connsys_clock_schematic clock_sch;
+
+ clock_sch = (enum connsys_clock_schematic)conninfra_get_clock_schematic();
+ switch (clock_sch) {
+ case CONNSYS_CLOCK_SCHEMATIC_26M_COTMS:
+ gps_clock_flag = GPSDL_CLOCK_FLAG_COTMS;
+ break;
+ case CONNSYS_CLOCK_SCHEMATIC_52M_COTMS:
+ gps_clock_flag = GPSDL_CLOCK_FLAG_52M_COTMS;
+ break;
+ case CONNSYS_CLOCK_SCHEMATIC_26M_EXTCXO:
+ gps_clock_flag = GPSDL_CLOCK_FLAG_TCXO;
+ break;
+ default:
+ gps_clock_flag = GPSDL_CLOCK_FLAG_COTMS;
+ break;
+ }
+ GDL_LOGW("clk: sch from conninfra = %d, mapping to flag = 0x%x", clock_sch, gps_clock_flag);
+#else
+ gps_clock_flag = GPSDL_CLOCK_FLAG_COTMS;
+ GDL_LOGW("clk: no conninfra drv, default flag = 0x%x", gps_clock_flag);
+#endif
+ g_gps_conn_clock_flag = gps_clock_flag;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_zbus.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_zbus.c
new file mode 100644
index 0000000..3187861
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dl_zbus.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dsp_fsm.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dsp_fsm.c
new file mode 100644
index 0000000..70df18e
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/gps_dsp_fsm.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+/* #include "autoconf.h" */
+
+#if 1
+
+/* #ifdef CONFIG_GPS_SUPPORT */
+#if 0
+#include "gps_reroute.h"
+#include "gps_reroute_emi.h"
+#include "emi_symbol_hook.h"
+#include "gps_util.h"
+#include "wmt_task.h"
+#include "cos_api.h"
+#endif
+
+#include "gps_dsp_fsm.h"
+#include "gps_dl_log.h"
+#include "gps_each_link.h"
+#include "gps_dl_name_list.h"
+#include "gps_dl_hal.h"
+#include "gps_dl_hw_api.h"
+
+
+/* extern kal_uint32 g_mcu_real_clock_rate; */
+/* extern kal_uint32 g_max_mcu_clock_rate; */
+/* #define GPS_REQ_CLOCK_FREQ_MHZ_MVCD (g_max_mcu_clock_rate/ 1000000UL) */
+/* #define GPS_REQ_CLOCK_FREQ_MHZ_NORMAL (1) 1MHz */
+
+enum gps_dsp_state_t g_gps_dsp_state[GPS_DATA_LINK_NUM];
+
+
+enum gps_dsp_state_t gps_dsp_state_get(enum gps_dl_link_id_enum link_id)
+{
+ return g_gps_dsp_state[link_id];
+}
+
+bool gps_dsp_state_is(enum gps_dsp_state_t state, enum gps_dl_link_id_enum link_id)
+{
+ ASSERT_LINK_ID(link_id, false);
+ return !!(g_gps_dsp_state[link_id] == state);
+}
+
+void gps_dsp_state_change_to(enum gps_dsp_state_t next_state, enum gps_dl_link_id_enum link_id)
+{
+ ASSERT_LINK_ID(link_id, GDL_VOIDF());
+
+ if (next_state == GPS_DSP_ST_TURNED_ON) {
+ /* gps_clock_switch (GPS_REQ_CLOCK_FREQ_MHZ_MVCD); */
+ /* gps_ctrl_timer_start(GPS_DSP_RESET_TIMEOUT_MS); */
+ }
+
+ if (next_state == GPS_DSP_ST_RESET_DONE) {
+ /* Note: here is just a candidate caller, if no problem, we call it */
+ /* in GPS_Reroute_Ext_Power_Ctrl_Inner */
+ /* GPS_Reroute_Set_DSP_Config_By_MCUB(); */
+
+ /* gps_clock_switch (GPS_REQ_CLOCK_FREQ_MHZ_MVCD); */
+ /* gps_ctrl_timer_start(GPS_DSP_MVCD_TIMEOUT_MS); */
+#if 0
+ if (!g_gps_bypass_dsp_turned_on_state) {
+ /* ready to do reroute */
+ gps_data_reroute_set_pending(false);
+ GPS_Reroute_Buffer_to_GPS_port_real();
+ }
+#endif
+ gps_dl_link_set_ready_to_write(link_id, true);
+ gps_dl_link_start_tx_dma_if_has_data(link_id);
+ }
+
+ if (next_state == GPS_DSP_ST_WAKEN_UP) {
+ /* gps_ctrl_timer_start(GPS_DSP_WAKEUP_TIMEOUT_MS);
+ */
+ }
+
+ if (next_state == GPS_DSP_ST_WORKING) {
+ /* gps_clock_switch (GPS_REQ_CLOCK_FREQ_MHZ_NORMAL); */
+ gps_dl_hal_link_clear_hw_pwr_stat(link_id);
+ gps_dl_hal_set_need_clk_ext_flag(link_id, false);
+ }
+
+ if (next_state == GPS_DSP_ST_OFF) {
+ /* gps_clock_switch (0); - already done before gps_dsp_fsm */
+ /* gps_ctrl_timer_stop(); */
+ }
+
+ g_gps_dsp_state[link_id] = next_state;
+}
+
+void gps_dsp_fsm(enum gps_dsp_event_t evt, enum gps_dl_link_id_enum link_id)
+{
+#if 1
+ bool abnormal_flag = true;
+ enum gps_dsp_state_t last_state = gps_dsp_state_get(link_id);
+
+ if (GPS_DSP_EVT_FUNC_ON != evt && GPS_DSP_ST_OFF == last_state) {
+ /* bypass all event except gps func on when gps is off */
+ abnormal_flag = true;
+ goto _last_check;
+ }
+
+ if (GPS_DSP_EVT_FUNC_OFF == evt) {
+#if 0
+ if (GPS_DSP_ST_HW_SLEEP_MODE == last_state ||
+ GPS_DSP_ST_HW_STOP_MODE == last_state) {
+ /* Special handing rather than GPS_Reroute_Ext_Power_Ctrl_Inner */
+ if (GPS_DSP_ST_HW_SLEEP_MODE == last_state)
+ ; /* wmt_task_subsystem_power_ctrl_handler(COS_GPS_CTRL, 3); */
+ else if (GPS_DSP_ST_HW_STOP_MODE == last_state)
+ ; /* wmt_task_subsystem_power_ctrl_handler(COS_GPS_CTRL, 5); */
+
+ /* wmt_task_subsystem_power_ctrl_handler(COS_GPS_CTRL, 0); */
+ /* GPS_Reroute_Buffer_to_GPS_port_drop(); */
+ /* GPS_Reroute_Cos_Sleep_Enable(); */
+ }
+#endif
+ if (GPS_DSP_ST_RESET_DONE == last_state ||
+ GPS_DSP_ST_HW_STOP_MODE == last_state)
+ abnormal_flag = false;
+ gps_dsp_state_change_to(GPS_DSP_ST_OFF, link_id);
+ goto _last_check;
+ }
+
+ if (GPS_DSP_EVT_CTRL_TIMER_EXPIRE == evt) {
+ /* if (!gps_ctrl_timer_check_valid()) */
+ {
+ abnormal_flag = true;
+ goto _last_check;
+ }
+
+ /* TODO: unmask it when timer ready */
+#if 0
+ switch (last_state) {
+ case GPS_DSP_ST_TURNED_ON:
+ /* GPS_DSP_EVT_RESET_DONE timeout (180ms) */
+ /* GPS_Reroute_Buffer_to_GPS_port_drop(); */
+ /* gps_dsp_state_change_to(GPS_DSP_ST_RESET_DONE, link_id); */
+ /* ERROR timeout - each DSP restart */
+
+ /* TODO: gps_each_link_reset(link_id); */
+ break;
+ case GPS_DSP_ST_RESET_DONE:
+ /* GPS_DSP_EVT_RAM_CODE_READY timeout (1s) */
+ gps_dsp_state_change_to(GPS_DSP_ST_WORKING, link_id);
+ break;
+#if 0
+ case GPS_DSP_ST_HW_SLEEP_MODE:
+ GPS_Reroute_Ext_Power_Ctrl_Inner(3);
+ /* cos_resource_enable(COS_SLEEP_MODE, g_gps_sleep_handle); */
+ gps_dsp_state_change_to(GPS_DSP_ST_WAKEN_UP, link_id);
+ break;
+ case GPS_DSP_ST_WAKEN_UP:
+ gps_dsp_state_change_to(GPS_DSP_ST_WORKING, link_id);
+ break;
+#endif
+ default:
+ abnormal_flag = true;
+ }
+ goto _last_check;
+#endif
+ }
+
+ switch (last_state) {
+ case GPS_DSP_ST_OFF:
+ if (GPS_DSP_EVT_FUNC_ON == evt) {
+#if 0
+ if (g_gps_bypass_dsp_turned_on_state)
+ gps_dsp_state_change_to(GPS_DSP_ST_RESET_DONE, link_id);
+ else
+ gps_dsp_state_change_to(GPS_DSP_ST_TURNED_ON, link_id);
+#endif
+ gps_dsp_state_change_to(GPS_DSP_ST_TURNED_ON, link_id);
+ abnormal_flag = false;
+ }
+ break;
+
+ case GPS_DSP_ST_TURNED_ON:
+ if (GPS_DSP_EVT_RESET_DONE == evt) {
+ gps_dsp_state_change_to(GPS_DSP_ST_RESET_DONE, link_id);
+ abnormal_flag = false;
+ } else
+ abnormal_flag = true;
+ break;
+
+ case GPS_DSP_ST_RESET_DONE:
+ if (GPS_DSP_EVT_RAM_CODE_READY == evt) {
+ /* TODO */
+ /* gps_ctrl_timer_stop(); */
+ gps_dsp_state_change_to(GPS_DSP_ST_WORKING, link_id);
+ abnormal_flag = false;
+ } else if (GPS_DSP_EVT_HW_STOP_REQ == evt) {
+ /* already done outside
+ * GPS_Reroute_Ext_Power_Ctrl_Inner(4);
+ */
+ gps_dsp_state_change_to(GPS_DSP_ST_HW_STOP_MODE, link_id);
+ abnormal_flag = false;
+ } else
+ abnormal_flag = true;
+ break;
+
+ case GPS_DSP_ST_WORKING:
+ if (GPS_DSP_EVT_RESET_DONE == evt) {
+ /* PMTK101 like restart or to be powered off */
+ gps_dsp_state_change_to(GPS_DSP_ST_RESET_DONE, link_id);
+ abnormal_flag = false;
+ } else if (GPS_DSP_EVT_HW_STOP_REQ == evt) {
+ /* already done outside
+ * GPS_Reroute_Ext_Power_Ctrl_Inner(4);
+ */
+ gps_dsp_state_change_to(GPS_DSP_ST_HW_STOP_MODE, link_id);
+ abnormal_flag = true; /* just show warning */
+ } else
+ abnormal_flag = true;
+#if 0
+ else if (GPS_DSP_EVT_HW_SLEEP_REQ == evt) {
+ GPS_Reroute_Ext_Power_Ctrl_Inner(2);
+ /* to_do_timer check!!! - dynamic change timer */
+ /* gps_ctrl_timer_start(800); */
+ gps_dsp_state_change_to(GPS_DSP_ST_HW_SLEEP_MODE, link_id);
+ } else
+ abnormal_flag = true;
+#endif
+ break;
+
+ case GPS_DSP_ST_HW_SLEEP_MODE:
+#if 0
+ if (GPS_DSP_EVT_HW_SLEEP_EXIT == evt) {
+ /* from host - only for test */
+ GPS_Reroute_Ext_Power_Ctrl_Inner(3);
+ gps_dsp_state_change_to(GPS_DSP_ST_WAKEN_UP, link_id);
+ } else
+ abnormal_flag = true;
+#endif
+ abnormal_flag = true;
+ break;
+
+ case GPS_DSP_ST_HW_STOP_MODE:
+ if (GPS_DSP_EVT_HW_STOP_EXIT == evt) {
+ /* GPS_Reroute_Ext_Power_Ctrl_Inner(5); */
+ gps_dsp_state_change_to(GPS_DSP_ST_WAKEN_UP, link_id);
+ abnormal_flag = false;
+ } else if (GPS_DSP_EVT_RESET_DONE == evt) {
+ gps_dsp_state_change_to(GPS_DSP_ST_RESET_DONE, link_id);
+ abnormal_flag = false;
+ } else
+ abnormal_flag = true;
+ break;
+
+ case GPS_DSP_ST_WAKEN_UP:
+ if (GPS_DSP_EVT_RAM_CODE_READY == evt) {
+ /* gps_ctrl_timer_stop(); */
+ gps_dl_link_set_ready_to_write(link_id, true);
+ gps_dl_link_start_tx_dma_if_has_data(link_id);
+ gps_dsp_state_change_to(GPS_DSP_ST_WORKING, link_id);
+ abnormal_flag = false;
+ } else
+ abnormal_flag = true;
+ break;
+
+ default:
+ abnormal_flag = true;
+ }
+
+_last_check:
+ if (abnormal_flag) {
+ GDL_LOGXW_STA(link_id, "gps_dsp_fsm: old_st=%s, evt=%s, new_st=%s, is_err=%d",
+ gps_dl_dsp_state_name(last_state), gps_dl_dsp_event_name(evt),
+ gps_dl_dsp_state_name(gps_dsp_state_get(link_id)), abnormal_flag);
+ } else {
+ GDL_LOGXI_STA(link_id, "gps_dsp_fsm: old_st=%s, evt=%s, new_st=%s",
+ gps_dl_dsp_state_name(last_state), gps_dl_dsp_event_name(evt),
+ gps_dl_dsp_state_name(gps_dsp_state_get(link_id)));
+ }
+ return;
+#endif
+}
+
+#endif /* CONFIG_GPS_SUPPORT */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/gps_dl_hal.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/gps_dl_hal.h
new file mode 100644
index 0000000..829ce0e
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/gps_dl_hal.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_HAL_H
+#define _GPS_DL_HAL_H
+
+#include "gps_dl_config.h"
+#include "gps_dl_dma_buf.h"
+#include "gps_dl_hal_type.h"
+#include "gps_dl_isr.h"
+
+/* for gps_each_device.c */
+
+
+/* for gps_each_link.c */
+enum gps_dl_hal_power_ctrl_op_enum {
+ GPS_DL_HAL_POWER_OFF = 0,
+ GPS_DL_HAL_POWER_ON = 1,
+ GPS_DL_HAL_ENTER_DPSLEEP = 2,
+ GPS_DL_HAL_LEAVE_DPSLEEP = 3,
+ GPS_DL_HAL_ENTER_DPSTOP = 4,
+ GPS_DL_HAL_LEAVE_DPSTOP = 5,
+ GPS_DL_HAL_POWER_OP_MAX
+};
+
+bool gps_dl_hal_conn_infra_driver_on(void);
+void gps_dl_hal_conn_infra_driver_off(void);
+void gps_dl_hal_conn_infra_driver_debug_dump(void);
+void gps_dl_hal_link_confirm_dma_stop(enum gps_dl_link_id_enum link_id);
+int gps_dl_hal_conn_power_ctrl(enum gps_dl_link_id_enum link_id, int op);
+int gps_dl_hal_link_power_ctrl(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_hal_power_ctrl_op_enum op);
+int gps_dl_hal_link_power_ctrl_inner(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_hal_power_ctrl_op_enum op);
+void gps_dl_hal_link_clear_hw_pwr_stat(enum gps_dl_link_id_enum link_id);
+#if GPS_DL_ON_LINUX
+bool gps_dl_hal_md_blanking_init_pta(void);
+void gps_dl_hal_md_blanking_deinit_pta(void);
+#endif
+void gps_dl_hal_md_blanking_ctrl(bool on);
+void gps_dl_hal_a2d_tx_dma_start(enum gps_dl_link_id_enum link_id,
+ struct gdl_dma_buf_entry *p_entry);
+void gps_dl_hal_d2a_rx_dma_start(enum gps_dl_link_id_enum link_id,
+ struct gdl_dma_buf_entry *p_entry);
+
+void gps_dl_hal_a2d_tx_dma_stop(enum gps_dl_link_id_enum link_id);
+void gps_dl_hal_d2a_rx_dma_stop(enum gps_dl_link_id_enum link_id);
+
+unsigned int gps_dl_hal_d2a_rx_dma_get_rx_len(enum gps_dl_link_id_enum link_id);
+enum GDL_RET_STATUS gps_dl_hal_d2a_rx_dma_get_write_index(
+ enum gps_dl_link_id_enum link_id, unsigned int *p_write_index);
+
+enum GDL_RET_STATUS gps_dl_hal_a2d_tx_dma_wait_until_done_and_stop_it(
+ enum gps_dl_link_id_enum link_id, int timeout_usec, bool return_if_not_start);
+enum GDL_RET_STATUS gps_dl_hal_d2a_rx_dma_wait_until_done(
+ enum gps_dl_link_id_enum link_id, int timeout_usec);
+enum GDL_RET_STATUS gps_dl_hal_wait_and_handle_until_usrt_has_data(
+ enum gps_dl_link_id_enum link_id, int timeout_usec);
+enum GDL_RET_STATUS gps_dl_hal_wait_and_handle_until_usrt_has_nodata_or_rx_dma_done(
+ enum gps_dl_link_id_enum link_id, int timeout_usec, bool to_handle);
+
+enum GDL_RET_STATUS gps_dl_hal_poll_event(
+ unsigned int L1_evt_in, unsigned int L5_evt_in,
+ unsigned int *pL1_evt_out, unsigned int *pL5_evt_out, unsigned int timeout_usec);
+
+int gps_dl_hal_usrt_direct_write(enum gps_dl_link_id_enum link_id,
+ unsigned char *buf, unsigned int len);
+int gps_dl_hal_usrt_direct_read(enum gps_dl_link_id_enum link_id,
+ unsigned char *buf, unsigned int len);
+
+void gps_each_dsp_reg_read_ack(
+ enum gps_dl_link_id_enum link_id, const struct gps_dl_hal_mcub_info *p_d2a);
+void gps_each_dsp_reg_gourp_read_init(enum gps_dl_link_id_enum link_id);
+void gps_each_dsp_reg_gourp_read_start(enum gps_dl_link_id_enum link_id,
+ bool dbg, unsigned int round_max);
+
+enum GDL_RET_STATUS gps_each_dsp_reg_read_request(
+ enum gps_dl_link_id_enum link_id, unsigned int reg_addr);
+void gps_each_dsp_reg_gourp_read_next(enum gps_dl_link_id_enum link_id, bool restart);
+
+bool gps_dl_hal_get_dma_irq_en_flag(void);
+void gps_dl_hal_set_dma_irq_en_flag(bool enable);
+bool gps_dl_hal_get_mcub_irq_dis_flag(enum gps_dl_link_id_enum link_id);
+void gps_dl_hal_set_mcub_irq_dis_flag(enum gps_dl_link_id_enum link_id, bool disable);
+bool gps_dl_hal_get_irq_dis_flag(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_each_link_irq_type type);
+void gps_dl_hal_set_irq_dis_flag(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_each_link_irq_type type, bool disable);
+bool gps_dl_hal_get_need_clk_ext_flag(enum gps_dl_link_id_enum link_id);
+void gps_dl_hal_set_need_clk_ext_flag(enum gps_dl_link_id_enum link_id, bool need);
+
+#define GPSDL_CLOCK_FLAG_TCXO (0x00)
+#define GPSDL_CLOCK_FLAG_COTMS (0x21)
+#define GPSDL_CLOCK_FLAG_52M_COTMS (0x51)
+int gps_dl_hal_get_clock_flag(void);
+void gps_dl_hal_load_clock_flag(void);
+
+void gps_dl_hw_gps_set_conn_infra_ver(unsigned int ver);
+unsigned int gps_dl_hw_gps_get_conn_infra_ver(void);
+
+#endif /* _GPS_DL_HAL_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/gps_dl_hal_api.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/gps_dl_hal_api.h
new file mode 100644
index 0000000..bc55ec0
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/gps_dl_hal_api.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_HAL_API_H
+#define _GPS_DL_HAL_API_H
+
+#include "gps_dl_config.h"
+#include "gps_dl_dma_buf.h"
+
+/* provide function declaration for gps_dl_hal.c */
+/* the functions are implemented in hal/gps_dl*.c */
+enum gps_dl_hal_event_id {
+ GPS_DL_HAL_EVT_A2D_TX_DMA_DONE,
+ GPS_DL_HAL_EVT_D2A_RX_HAS_DATA,
+ GPS_DL_HAL_EVT_D2A_RX_DMA_DONE,
+ GPS_DL_HAL_EVT_D2A_RX_HAS_NODATA,
+ GPS_DL_HAL_EVT_MCUB_HAS_IRQ,
+ GPS_DL_HAL_EVT_DSP_ROM_START,
+ GPS_DL_HAL_EVT_DSP_RAM_START,
+ GPS_DL_HAL_EVT_A2D_TX_DMA_TIMEOUT, /* exception */
+ GPS_DL_HAL_EVT_A2D_RX_DMA_TIMEOUT,
+ GPS_DL_HAL_EVT_DMA_ISR_PENDING,
+ GPD_DL_HAL_EVT_NUM
+};
+
+enum gps_dl_hal_poll_id {
+ GPS_DL_POLL_TX_DMA_DONE,
+ GPS_DL_POLL_RX_DMA_DONE,
+ GPS_DL_POLL_USRT_HAS_DATA,
+ GPS_DL_POLL_USRT_HAS_NODATA,
+ GPS_DL_POLL_MCUB_D2A_FLAG_SET,
+ GPS_DL_POLL_MAX
+};
+
+void gps_dl_hal_event_send(enum gps_dl_hal_event_id evt,
+ enum gps_dl_link_id_enum link_id);
+
+void gps_dl_hal_event_proc(enum gps_dl_hal_event_id evt,
+ enum gps_dl_link_id_enum link_id, int sid_on_evt);
+
+/* DMA operations */
+enum gps_dl_hal_dma_ch_index {
+ GPS_DL_DMA_LINK0_A2D,
+ GPS_DL_DMA_LINK0_D2A,
+ GPS_DL_DMA_LINK1_A2D,
+ GPS_DL_DMA_LINK1_D2A,
+ GPS_DL_DMA_CH_NUM,
+};
+
+enum gps_dl_hal_emi_user {
+ GPS_DL_EMI_USER_TX_DMA0 = GPS_DL_DMA_LINK0_A2D,
+ GPS_DL_EMI_USER_RX_DMA0 = GPS_DL_DMA_LINK0_D2A,
+ GPS_DL_EMI_USER_TX_DMA1 = GPS_DL_DMA_LINK1_A2D,
+ GPS_DL_EMI_USER_RX_DMA1 = GPS_DL_DMA_LINK1_D2A,
+ GPS_DL_EMI_USER_ICAP, /* reserved, driver not use it */
+ GPS_DL_EMI_USER_GPS_ON, /* may remove this user later */
+ GPS_DL_EMI_USER_NUM
+};
+
+#define DMA_CH_TO_LINK_ID(ch) (\
+ ((ch) == GPS_DL_DMA_LINK0_A2D || (ch) == GPS_DL_DMA_LINK0_D2A) ? GPS_DATA_LINK_ID0 : (\
+ ((ch) == GPS_DL_DMA_LINK1_A2D || (ch) == GPS_DL_DMA_LINK1_D2A) ? GPS_DATA_LINK_ID1 : (\
+ 0xFF)))
+
+#define DMA_CH_IS_TX(ch) \
+ ((ch) == GPS_DL_DMA_LINK0_A2D || (ch) == GPS_DL_DMA_LINK1_A2D)
+
+#define DMA_CH_IS_RX(ch) \
+ ((ch) == GPS_DL_DMA_LINK0_D2A || (ch) == GPS_DL_DMA_LINK1_D2A)
+
+#define GET_TX_DMA_CH_OF(link_id) \
+ CHOOSE_BY_LINK_ID(link_id, GPS_DL_DMA_LINK0_A2D, GPS_DL_DMA_LINK1_A2D, 0xFF)
+
+#define GET_RX_DMA_CH_OF(link_id) \
+ CHOOSE_BY_LINK_ID(link_id, GPS_DL_DMA_LINK0_D2A, GPS_DL_DMA_LINK1_D2A, 0xFF)
+
+void gps_dl_hal_dma_init(void);
+
+void gps_dl_hal_dma_config(enum gps_dl_hal_dma_ch_index ch);
+void gps_dl_hal_dma_start(enum gps_dl_hal_dma_ch_index ch,
+ struct gdl_dma_buf_entry *p_entry);
+void gps_dl_hal_dma_stop(enum gps_dl_hal_dma_ch_index ch);
+
+void gps_dl_emi_remap_calc_and_set(void);
+enum GDL_RET_STATUS gps_dl_emi_remap_phy_to_bus_addr(unsigned int phy_addr, unsigned int *bus_addr);
+
+void gps_dl_hal_emi_usage_init(void);
+void gps_dl_hal_emi_usage_deinit(void);
+void gps_dl_hal_emi_usage_claim(enum gps_dl_hal_emi_user user, bool use_emi);
+void gps_dl_hal_a2d_tx_dma_claim_emi_usage(enum gps_dl_link_id_enum link_id, bool use_emi);
+void gps_dl_hal_d2a_rx_dma_claim_emi_usage(enum gps_dl_link_id_enum link_id, bool use_emi);
+
+
+#endif /* _GPS_DL_HAL_API_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/gps_dl_hal_type.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/gps_dl_hal_type.h
new file mode 100644
index 0000000..20a4b3e
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/gps_dl_hal_type.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_HAL_TYPE_H
+#define _GPS_DL_HAL_TYPE_H
+
+struct gps_dl_hal_mcub_info {
+ unsigned int flag;
+ unsigned int dat0;
+ unsigned int dat1;
+};
+
+#endif /* _GPS_DL_HAL_TYPE_H */
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/gps_dl_hal_util.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/gps_dl_hal_util.h
new file mode 100644
index 0000000..f32ef2c
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/gps_dl_hal_util.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_HAL_UTIL_H
+#define _GPS_DL_HAL_UTIL_H
+
+
+
+/* bool gps_dl_hal_get_dma_int_status(enum gps_dl_hal_dma_ch_index channel); */
+
+
+enum GPS_DL_HWCR_OWNER_ENUM {
+ GPS_DL_HWCR_OWNER_POS, /* for power on sequence */
+ GPS_DL_HWCR_OWNER_DMA, /* for dma control */
+ GPS_DL_HWCR_OWNER_NUM
+};
+
+
+/* Must claim the owner before access hardware control registers */
+enum GDL_RET_STATUS gps_dl_hwcr_access_claim(enum GPS_DL_HWCR_OWNER_ENUM owner);
+enum GDL_RET_STATUS gps_dl_hwcr_access_disclaim(enum GPS_DL_HWCR_OWNER_ENUM owner);
+
+
+#endif /* _GPS_DL_HAL_UTIL_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/gps_dl_isr.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/gps_dl_isr.h
new file mode 100644
index 0000000..a478d0e
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/gps_dl_isr.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_ISR_H
+#define _GPS_DL_ISR_H
+
+#include "gps_dl_config.h"
+#include "gps_each_link.h"
+
+enum gps_dl_irq_index_enum {
+ GPS_DL_IRQ_LINK0_DATA,
+ GPS_DL_IRQ_LINK0_NODATA,
+ GPS_DL_IRQ_LINK0_MCUB,
+ GPS_DL_IRQ_LINK1_DATA,
+ GPS_DL_IRQ_LINK1_NODATA,
+ GPS_DL_IRQ_LINK1_MCUB,
+ GPS_DL_IRQ_DMA,
+ GPS_DL_IRQ_NUM,
+};
+
+enum gps_dl_irq_trigger_type {
+ GPS_DL_IRQ_TRIG_LEVEL_HIGH,
+ GPS_DL_IRQ_TRIG_EDGE_RISING,
+ GPS_DL_IRQ_TRIG_NUM,
+};
+
+struct gps_each_irq_cfg {
+ int sens_type;
+ enum gps_dl_irq_index_enum index;
+ void *isr;
+ const char *name;
+ enum gps_dl_irq_trigger_type trig_type;
+};
+
+struct gps_each_irq {
+ struct gps_each_irq_cfg cfg;
+ bool register_done;
+ int reg_irq_id;
+};
+
+#define IRQ_IDX_IS_VALID(irq_idx) \
+ (((irq_idx) >= 0) && ((irq_idx) < GPS_DL_IRQ_NUM))
+
+#define ASSERT_IRQ_IDX(irq_idx, ret) \
+ GDL_ASSERT(IRQ_IDX_IS_VALID(irq_idx), ret, "invalid irq index: %d", irq_idx)
+
+struct gps_each_irq *gps_dl_irq_get(enum gps_dl_irq_index_enum irq_idx);
+
+
+enum gps_dl_each_link_irq_type {
+ GPS_DL_IRQ_TYPE_HAS_DATA,
+ GPS_DL_IRQ_TYPE_HAS_NODATA,
+ GPS_DL_IRQ_TYPE_MCUB,
+ GPS_DL_IRQ_TYPE_NUM,
+};
+#define IRQ_TYPE_IS_VALID(irq_type) \
+ (((irq_type) >= 0) && ((irq_type) < GPS_DL_IRQ_TYPE_NUM))
+
+#define ASSERT_IRQ_TYPE(irq_type, ret) \
+ GDL_ASSERT(IRQ_TYPE_IS_VALID(irq_type), ret, "invalid irq type: %d", irq_type)
+
+
+enum gps_dl_irq_ctrl_from {
+ GPS_DL_IRQ_CTRL_FROM_ISR,
+ GPS_DL_IRQ_CTRL_FROM_THREAD,
+ GPS_DL_IRQ_CTRL_FROM_MAX,
+};
+
+#if GPS_DL_USE_THREADED_IRQ
+/*
+ * #define GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR GPS_DL_IRQ_CTRL_FROM_THREAD
+ * threaded_irq still can't call disable_irq
+ */
+#define GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR GPS_DL_IRQ_CTRL_FROM_ISR
+#else
+#define GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR GPS_DL_IRQ_CTRL_FROM_ISR
+#endif
+
+#if GPS_DL_HAS_CTRLD
+#define GPS_DL_IRQ_CTRL_FROM_HAL GPS_DL_IRQ_CTRL_FROM_THREAD
+#else
+#define GPS_DL_IRQ_CTRL_FROM_HAL GPS_DL_IRQ_CTRL_POSSIBLE_FROM_ISR
+#endif
+
+
+void gps_dl_irq_mask(int irq_id, enum gps_dl_irq_ctrl_from from);
+void gps_dl_irq_unmask(int irq_id, enum gps_dl_irq_ctrl_from from);
+
+#if GPS_DL_ON_LINUX
+void gps_dl_irq_set_id(enum gps_dl_irq_index_enum irq_idx, int irq_id);
+#endif
+
+int gps_dl_irq_index_to_id(enum gps_dl_irq_index_enum irq_idx);
+int gps_dl_irq_type_to_id(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_each_link_irq_type irq_type);
+int gps_dl_irq_type_to_hwirq(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_each_link_irq_type irq_type);
+
+void gps_dl_irq_each_link_control(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_each_link_irq_type irq_type, bool mask_it, enum gps_dl_irq_ctrl_from from);
+void gps_dl_irq_each_link_mask(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_each_link_irq_type irq_type, enum gps_dl_irq_ctrl_from from);
+void gps_dl_irq_each_link_unmask(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_each_link_irq_type irq_type, enum gps_dl_irq_ctrl_from from);
+
+int gps_dl_irq_init(void);
+int gps_dl_irq_deinit(void);
+void gps_dl_irq_mask_dma_intr(enum gps_dl_irq_ctrl_from from);
+void gps_dl_irq_unmask_dma_intr(enum gps_dl_irq_ctrl_from from);
+
+void gps_dl_isr_usrt_has_data(enum gps_dl_link_id_enum link_id);
+void gps_dl_isr_usrt_has_nodata(enum gps_dl_link_id_enum link_id);
+void gps_dl_isr_a2d_tx_dma_done(enum gps_dl_link_id_enum link_id);
+void gps_dl_isr_d2a_rx_dma_done(enum gps_dl_link_id_enum link_id);
+void gps_dl_isr_mcub(enum gps_dl_link_id_enum link_id);
+bool gps_dl_hal_mcub_flag_handler(enum gps_dl_link_id_enum link_id);
+
+#if GPS_DL_ON_CTP
+void gps_dl_isr_dl0_has_data(void);
+void gps_dl_isr_dl0_has_nodata(void);
+void gps_dl_isr_dl0_mcub(void);
+void gps_dl_isr_dl1_has_data(void);
+void gps_dl_isr_dl1_has_nodata(void);
+void gps_dl_isr_dl1_mcub(void);
+#endif
+
+void gps_dl_isr_dma_done(void);
+
+#endif /* _GPS_DL_ISR_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/gps_dsp_fsm.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/gps_dsp_fsm.h
new file mode 100644
index 0000000..3f17e97
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/gps_dsp_fsm.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DSP_FSM_H_
+#define _GPS_DSP_FSM_H_
+
+#include "gps_dl_config.h"
+
+enum gps_dsp_state_t {
+ /* GPS and DSP are function off */
+ GPS_DSP_ST_OFF, /* 0 */
+
+ /* MCU turned DSP on and just released the reset flag */
+ GPS_DSP_ST_TURNED_ON, /* 1 */
+
+ /* DSP notified MCU about it's reset flow done */
+ /* It will also stand for DSP finished Mbist flow if DSP has this flow */
+ /* MCU should suspend the data reoute until change to this state */
+ /* When change to this state, MVCD flow should start immediately */
+ GPS_DSP_ST_RESET_DONE, /* 2 */
+
+ /* DSP raw code download finish/DSP wakeup and raw code start working */
+ GPS_DSP_ST_WORKING, /* 3 */
+
+ /* DSP in HW sleep mode for GLP duty cycle mode */
+ GPS_DSP_ST_HW_SLEEP_MODE, /* 4 */
+
+ /* DSP in HW stop mode. MVCD flow can be skipped after wakeup */
+ GPS_DSP_ST_HW_STOP_MODE, /* 5 */
+
+ /* Wakeup from sleep/stop mode */
+ /* No MVCD procedure, should directly goto GPS_DSP_ST_WORKING */
+ GPS_DSP_ST_WAKEN_UP, /* 6 */
+
+ GPS_DSP_ST_MAX
+};
+
+
+
+/*
+ * DSP to MCU MCUB flag bit usage definition
+ */
+#define GPS_MCUB_D2AF_MASK_DSP_RAMCODE_READY 0x1 /* bit0 */
+#define GPS_MCUB_D2AF_MASK_DSP_REG_READ_READY 0x2 /* bit1 */
+#define GPS_MCUB_D2AF_MASK_DSP_REQUEST_MCU_ACTION 0x4 /* bit2 */
+/* To be renamed to GPS_MCUB_D2AF_MASK_DSP_RESET_DONE */
+/* #define GPS_MCUB_D2AF_MASK_DSP_MBIST_READY 0b1000 */
+#define GPS_MCUB_D2AF_MASK_DSP_RESET_DONE 0x8 /* bit3 */
+
+
+/* Get action and parameter from D2A data
+ * bit15 ~ bit12: action
+ * bit11 ~ bit0 : parameter
+ */
+#define GPS_MCUB_D2A_DATA_GET_ACTION(x) (((x) & 0xF000) >> 12)
+#define GPS_MCUB_D2A_DATA_GET_PARAM(x) (((x) & 0x0FFF))
+#define GPS_MCUB_D2A_DATA_MAKE_ACTION_PARAM(a, p) ((((a) << 12) & 0xF000) | ((p) & 0xFFF))
+
+
+/* Request from D2A flag bit0, the actiton+param in D2A data0 */
+#define GPS_MCUB_F0D0_ACTION_RAM_STATUS (0)
+#define GPS_MCUB_F0D0_ACTION_VCORE (1)
+
+/* PARAM of GPS_MCUB_F0D0_ACTION_RAM_STATUS */
+#define GPS_MCUB_F0D0_ACTION_RAM_STATUS_PARAM_RAM_READY (1)
+
+/* PARAM of GPS_MCUB_F0D0_ACTION_VCORE */
+#define GPS_MCUB_F0D0_ACTION_VCORE_PARAM_RELEASE_VCORE (0)
+#define GPS_MCUB_F0D0_ACTION_VCORE_PARAM_REQUEST_0_6V (1)
+
+
+
+/*
+ * MCU to DSP MCUB flag bit usage definition
+ */
+#define GPS_MCUB_A2DF_MASK_DSP_DCLK_79MHZ_REQ 0x1 /* bit0 */
+#define GPS_MCUB_A2DF_MASK_DSP_DCLK_88MHZ_REQ 0x2 /* bit1 */
+#define GPS_MCUB_A2DF_MASK_DSP_REG_READ_REQ 0x4 /* bit2 */
+/* Will be available on MT6779. The previous chips don't use it */
+#define GPS_MCUB_A2DF_MASK_DSP_SET_CFG_REQ 0x8 /* bit3 */
+
+
+/*
+ * MCU to DSP MCUB data1 bit usage definition - boot stage
+ * with GPS_MCUB_A2DF_MASK_DSP_SET_CFG_REQ
+ */
+#define GPS_DSP_CFG_BITMASK_ADIE_IS_MT6631 (1UL << 0)
+#define GPS_DSP_CFG_BITMASK_MVCD_SPEED_UP (1UL << 1)
+#define GPS_DSP_CFG_BITMASK_ADIE_IS_MT6635_E2_OR_AFTER (1UL << 2)
+#define GPS_DSP_CFG_BITMASK_USRT_4BYTE_MODE (1UL << 3)
+#define GPS_DSP_CFG_BITMASK_COLOCK_USE_TIA (1UL << 6)
+#define GPS_DSP_CFG_BITMASK_CLOCK_EXTENSION_WAKEUP (1UL << 7)
+
+/*
+ * MCU to DSP MCUB data1 bit usage definition - workiing stage
+ * (@GPS_DSP_ST_WORKING)
+ * with GPS_MCUB_A2DF_MASK_DSP_SET_CFG_REQ
+ * it's action + param rather than bitmask in boot stage
+ */
+
+/* 0x1000 */
+#define GPS_DSP_CFG_ACTION_PARAM_ACK_VCORE_RELEASE (GPS_MCUB_D2A_DATA_MAKE_ACTION_PARAM( \
+ GPS_MCUB_F0D0_ACTION_VCORE, GPS_MCUB_F0D0_ACTION_VCORE_PARAM_RELEASE_VCORE))
+
+/* 0x1001 */
+#define GPS_DSP_CFG_ACTION_PARAM_ACK_VCORE_0_6V (GPS_MCUB_D2A_DATA_MAKE_ACTION_PARAM( \
+ GPS_MCUB_F0D0_ACTION_VCORE, GPS_MCUB_F0D0_ACTION_VCORE_PARAM_REQUEST_0_6V))
+
+
+
+enum gps_dsp_event_t {
+ GPS_DSP_EVT_FUNC_OFF, /* 0 From host */
+ GPS_DSP_EVT_FUNC_ON, /* 1 From host */
+ GPS_DSP_EVT_RESET_DONE, /* 2 From DSP D2AF[3] */
+ GPS_DSP_EVT_RAM_CODE_READY, /* 3 From DSP D2AF[0] */
+ GPS_DSP_EVT_CTRL_TIMER_EXPIRE, /* 4 From timer */
+ GPS_DSP_EVT_HW_SLEEP_REQ, /* 5 From DSP D2AF[2] - DSP request it; from host for test */
+ GPS_DSP_EVT_HW_SLEEP_EXIT, /* 6 From host - just for test */
+ GPS_DSP_EVT_HW_STOP_REQ, /* 7 From host */
+ GPS_DSP_EVT_HW_STOP_EXIT, /* 8 From host */
+ GPS_DSP_EVT_MAX
+};
+
+#define GPS_DSP_RESET_TIMEOUT_MS (180)
+#define GPS_DSP_MVCD_TIMEOUT_MS (1000)
+#define GPS_DSP_WAKEUP_TIMEOUT_MS (180)
+
+
+enum gps_dsp_state_t gps_dsp_state_get(enum gps_dl_link_id_enum link_id);
+void gps_dsp_state_change_to(enum gps_dsp_state_t state, enum gps_dl_link_id_enum link_id);
+bool gps_dsp_state_is(enum gps_dsp_state_t state, enum gps_dl_link_id_enum link_id);
+
+void gps_dsp_fsm(enum gps_dsp_event_t evt, enum gps_dl_link_id_enum link_id);
+
+#endif /* _GPS_DSP_FSM_H_ */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/hal_common.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/hal_common.h
new file mode 100644
index 0000000..ca22ff3
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hal/inc/hal_common.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef ___HAL_COMMON_H__
+#define ___HAL_COMMON_H__
+
+
+#endif /* ___HAL_COMMON_H__ */
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_bgf.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_bgf.c
new file mode 100644
index 0000000..8faa311
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_bgf.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+#include "gps_dl_hw_priv_util.h"
+/* #include "bgf/bgf_cfg.h" */
+/* #include "bgf/bgf_cfg_on.h" */
+
+#define BGF_ADDR_ENTRY_NUM (1)
+static const struct gps_dl_addr_map_entry g_bfg_addr_table[BGF_ADDR_ENTRY_NUM] = {
+ {0, 0, 0}
+ /* {0x18812000, BGF_CFG_BASE, 0x1000}, */
+ /* {0x18813000, BGF_CFG_ON_BASE, 0x1000}, */
+};
+
+unsigned int bgf_bus_to_host(unsigned int bgf_addr)
+{
+ unsigned int i;
+ const struct gps_dl_addr_map_entry *p;
+
+ for (i = 0; i < BGF_ADDR_ENTRY_NUM; i++) {
+ p = &g_bfg_addr_table[i];
+ if (bgf_addr >= p->bus_addr &&
+ bgf_addr < (p->bus_addr + p->length))
+ return ((bgf_addr - p->bus_addr) + p->host_addr);
+ }
+
+ return 0;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_conn_infra.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_conn_infra.c
new file mode 100644
index 0000000..08676d7
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_conn_infra.c
@@ -0,0 +1,670 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+
+#include "gps_dl_context.h"
+#include "gps_dl_hw_api.h"
+#include "gps_dl_hw_dep_api.h"
+#include "gps_dl_hw_priv_util.h"
+
+#include "conn_infra/conn_host_csr_top.h"
+#include "conn_infra/conn_infra_cfg.h"
+#if GPS_DL_HAS_PTA
+#include "conn_infra/conn_uart_pta.h"
+#include "conn_infra/conn_pta6.h"
+#endif
+#include "conn_infra/conn_semaphore.h"
+#include "conn_infra/conn_rf_spi_mst_reg.h"
+
+void gps_dl_hw_set_gps_emi_remapping(unsigned int _20msb_of_36bit_phy_addr)
+{
+ GDL_HW_SET_CONN_INFRA_ENTRY(
+ CONN_HOST_CSR_TOP_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_CONN2AP_REMAP_GPS_EMI_BASE_ADDR,
+ _20msb_of_36bit_phy_addr);
+}
+
+unsigned int gps_dl_hw_get_gps_emi_remapping(void)
+{
+ return GDL_HW_GET_CONN_INFRA_ENTRY(
+ CONN_HOST_CSR_TOP_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_CONN2AP_REMAP_GPS_EMI_BASE_ADDR);
+}
+
+void gps_dl_hw_print_hw_status(enum gps_dl_link_id_enum link_id, bool dump_rf_cr)
+{
+ struct gps_dl_hw_dma_status_struct a2d_dma_status, d2a_dma_status;
+ struct gps_dl_hw_usrt_status_struct usrt_status;
+ enum gps_dl_hal_dma_ch_index a2d_dma_ch, d2a_dma_ch;
+
+ if (gps_dl_show_reg_wait_log())
+ GDL_LOGXD(link_id, "");
+
+ if (link_id == GPS_DATA_LINK_ID0) {
+ a2d_dma_ch = GPS_DL_DMA_LINK0_A2D;
+ d2a_dma_ch = GPS_DL_DMA_LINK0_D2A;
+ } else if (link_id == GPS_DATA_LINK_ID1) {
+ a2d_dma_ch = GPS_DL_DMA_LINK1_A2D;
+ d2a_dma_ch = GPS_DL_DMA_LINK1_D2A;
+ } else
+ return;
+
+ gps_dl_hw_save_usrt_status_struct(link_id, &usrt_status);
+ gps_dl_hw_print_usrt_status_struct(link_id, &usrt_status);
+
+ gps_dl_hw_save_dma_status_struct(a2d_dma_ch, &a2d_dma_status);
+ gps_dl_hw_print_dma_status_struct(a2d_dma_ch, &a2d_dma_status);
+
+ gps_dl_hw_save_dma_status_struct(d2a_dma_ch, &d2a_dma_status);
+ gps_dl_hw_print_dma_status_struct(d2a_dma_ch, &d2a_dma_status);
+
+ GDL_HW_RD_GPS_REG(0x80073160); /* DL0 */
+ GDL_HW_RD_GPS_REG(0x80073134); /* DL1 */
+
+ GDL_HW_RD_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_STA_ADDR);
+ GDL_HW_RD_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_GPS_GPS_ADDR_ADDR);
+ GDL_HW_RD_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_GPS_GPS_WDAT_ADDR);
+ GDL_HW_RD_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_GPS_GPS_RDAT_ADDR);
+ GDL_HW_RD_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_STA_ADDR);
+
+ if (dump_rf_cr) {
+ gps_dl_hw_gps_dump_top_rf_cr();
+ gps_dl_hw_gps_dump_gps_rf_cr();
+ }
+
+ /* only need for L1 */
+ gps_each_link_set_bool_flag(GPS_DATA_LINK_ID0, LINK_NEED_A2Z_DUMP, true);
+}
+
+void gps_dl_hw_do_gps_a2z_dump(void)
+{
+ GDL_HW_WR_GPS_REG(0x80073120, 1); /* enable A2Z */
+ GDL_HW_RD_GPS_REG(0x800706C0);
+ GDL_HW_RD_GPS_REG(0x80070450);
+ GDL_HW_RD_GPS_REG(0x80080450);
+}
+
+void gps_dl_hw_dump_sleep_prot_status(void)
+{
+ bool show_log = true;
+
+ show_log = gps_dl_set_show_reg_rw_log(true);
+ GDL_HW_DUMP_SLP_RPOT_STATUS();
+ gps_dl_set_show_reg_rw_log(show_log);
+}
+
+void gps_dl_hw_dump_host_csr_gps_info(bool force_show_log)
+{
+ int i;
+ bool show_log = true;
+
+ if (force_show_log)
+ show_log = gps_dl_set_show_reg_rw_log(true);
+
+#if 0
+ GDL_HW_GET_CONN_INFRA_ENTRY(CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_HOST2GPS_DEGUG_SEL);
+ GDL_HW_GET_CONN_INFRA_ENTRY(CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_GPS_CFG2HOST_DEBUG);
+#else
+ gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS,
+ CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_ADDR,
+ BMASK_RW_FORCE_PRINT);
+ gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS,
+ CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_ADDR,
+ BMASK_RW_FORCE_PRINT);
+#endif
+
+ for (i = 0xA2; i <= 0xB7; i++) {
+#if 0
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_HOST2GPS_DEGUG_SEL, i);
+ GDL_HW_GET_CONN_INFRA_ENTRY(CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_GPS_CFG2HOST_DEBUG);
+#else
+ gps_dl_bus_wr_opt(GPS_DL_CONN_INFRA_BUS,
+ CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_ADDR, i,
+ BMASK_RW_FORCE_PRINT);
+ gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS,
+ CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_ADDR,
+ BMASK_RW_FORCE_PRINT);
+#endif
+ }
+
+ if (force_show_log)
+ gps_dl_set_show_reg_rw_log(show_log);
+}
+
+void gps_dl_bus_check_and_print(unsigned int host_addr)
+{
+ /* not do rw check because here is the checking */
+ GDL_LOGI("for addr = 0x%08x", host_addr);
+ gps_dl_bus_wr_opt(GPS_DL_CONN_INFRA_BUS,
+ CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_ADDR, 0x000D0001,
+ BMASK_RW_FORCE_PRINT);
+
+ gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS,
+ CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_ADDR,
+ BMASK_RW_FORCE_PRINT);
+
+ gps_dl_bus_wr_opt(GPS_DL_CONN_INFRA_BUS,
+ CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_ADDR, 0x000B0001,
+ BMASK_RW_FORCE_PRINT);
+
+ gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS,
+ CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_ADDR,
+ BMASK_RW_FORCE_PRINT);
+
+ gps_dl_bus_wr_opt(GPS_DL_CONN_INFRA_BUS,
+ CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_ADDR, 0x000A0001,
+ BMASK_RW_FORCE_PRINT);
+
+ gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS,
+ CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_ADDR,
+ BMASK_RW_FORCE_PRINT);
+}
+
+void gps_dl_hw_dump_host_csr_conninfra_info_inner(unsigned int selection, int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++) {
+#if 0
+ GDL_HW_SET_CONN_INFRA_ENTRY(
+ CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_CONN_INFRA_DEBUG_CTRL_AO_DEBUGSYS_CTRL,
+ selection);
+ GDL_HW_GET_CONN_INFRA_ENTRY(
+ CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT);
+#else
+ /* Due to RW_DO_CHECK might be enabled, not use
+ * GDL_HW_SET_CONN_INFRA_ENTRY and GDL_HW_GET_CONN_INFRA_ENTRY to avoid redundant print.
+ */
+ gps_dl_bus_wr_opt(GPS_DL_CONN_INFRA_BUS,
+ CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_ADDR, selection,
+ BMASK_RW_FORCE_PRINT);
+
+ gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS,
+ CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_ADDR,
+ BMASK_RW_FORCE_PRINT);
+#endif
+ selection -= 0x10000;
+ }
+}
+
+void gps_dl_hw_dump_host_csr_conninfra_info(bool force_show_log)
+{
+ bool show_log = true;
+
+ if (force_show_log)
+ show_log = gps_dl_set_show_reg_rw_log(true);
+
+ gps_dl_hw_dump_host_csr_conninfra_info_inner(0x000F0001, 15);
+ gps_dl_hw_dump_host_csr_conninfra_info_inner(0x00030002, 3);
+ gps_dl_hw_dump_host_csr_conninfra_info_inner(0x00040003, 4);
+
+ if (force_show_log)
+ gps_dl_set_show_reg_rw_log(show_log);
+}
+
+#if GPS_DL_HAS_PTA
+/* CONN_INFRA_CFG_CKGEN_BUS_ADDR[5:2] */
+#define CONN_INFRA_CFG_PTA_CLK_ADDR CONN_INFRA_CFG_CKGEN_BUS_ADDR
+#define CONN_INFRA_CFG_PTA_CLK_MASK (\
+ CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA_OSC_CKEN_MASK | \
+ CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA_HCLK_CKEN_MASK | \
+ CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA5_OSC_CKEN_MASK | \
+ CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA5_HCLK_CKEN_MASK)
+#define CONN_INFRA_CFG_PTA_CLK_SHFT \
+ CONN_INFRA_CFG_CKGEN_BUS_CONN_CO_EXT_UART_PTA5_HCLK_CKEN_SHFT
+
+bool gps_dl_hw_is_pta_clk_cfg_ready(void)
+{
+ unsigned int pta_clk_cfg;
+ bool okay = true;
+
+ pta_clk_cfg = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_INFRA_CFG_PTA_CLK);
+ if (pta_clk_cfg != 0xF) {
+ /* clock cfg is default ready, no need to set it
+ * if not as excepted, skip pta and pta_uart init
+ */
+ okay = false;
+ }
+
+ if (!okay)
+ GDL_LOGE("pta_clk_cfg = 0x%x", pta_clk_cfg);
+ return okay;
+}
+
+
+bool gps_dl_hw_is_pta_uart_init_done(void)
+{
+ bool done;
+ unsigned int pta_uart_en;
+
+ pta_uart_en = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_PTA6_RO_PTA_CTRL_ro_uart_apb_hw_en);
+ done = (pta_uart_en == 1);
+ GDL_LOGD("done = %d, pta_uart_en = %d", done, pta_uart_en);
+
+ return done;
+}
+
+/* Only check bit7, so not use CONN_UART_PTA_FCR_RFTL */
+#define CONN_UART_PTA_FCR_RFTL_HIGH_BIT_ADDR CONN_UART_PTA_FCR_ADDR
+#define CONN_UART_PTA_FCR_RFTL_HIGH_BIT_MASK 0x00000080
+#define CONN_UART_PTA_FCR_RFTL_HIGH_BIT_SHFT 7
+
+bool gps_dl_hw_init_pta_uart(void)
+{
+#if 0
+ unsigned int pta_uart_en;
+#endif
+ bool show_log;
+ bool poll_okay;
+ bool reg_rw_log = gps_dl_log_reg_rw_is_on(GPS_DL_REG_RW_HOST_CSR_PTA_INIT);
+
+ /* 20191008 after DE checking, bellow steps are no need */
+#if 0
+ /* Set pta uart to MCU mode before init it.
+ * Note: both wfset and btset = 0, then pta_uart_en should become 0,
+ * set one of them = 1, then pta_uart_en should become 1.
+ */
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_WFSET_PTA_CTRL_r_wfset_uart_apb_hw_en, 0);
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_BTSET_PTA_CTRL_r_btset_uart_apb_hw_en, 0);
+ pta_uart_en = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_PTA6_RO_PTA_CTRL_ro_uart_apb_hw_en);
+
+ if (pta_uart_en != 0) {
+ GDL_LOGE("ro_uart_apb_hw_en not become 0, fail");
+ return false;
+ }
+#endif
+
+ if (reg_rw_log) {
+ gps_dl_hw_dump_host_csr_conninfra_info(true);
+ show_log = gps_dl_set_show_reg_rw_log(true);
+ }
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_HIGHSPEED_SPEED, 3);
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_SAMPLE_COUNT_SAMPLE_COUNT, 5);
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_SAMPLE_POINT_SAMPLE_POINT, 2);
+
+ /* UART_PTA_BASE + 0x3C = 0x12, this step is no-need now
+ * GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_GUARD_GUARD_CNT, 2);
+ * GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_GUARD_GUARD_EN, 1);
+ */
+
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_VFIFO_EN_RX_TIME_EN, 1); /* bit7 */
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_VFIFO_EN_PTA_RX_FE_EN, 1); /* bit3 */
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_VFIFO_EN_PTA_RX_MODE, 1); /* bit2 */
+
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_FRACDIV_L_FRACDIV_L, 0x55);
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_FRACDIV_M_FRACDIV_M, 2);
+
+ /* UART_PTA_BASE + 0x3C[4] = 0, this step is no-need now
+ * GDL_HW_SET_CONN_INFRA_ENTRY(CONN_UART_PTA_GUARD_GUARD_EN, 0);
+ */
+
+ GDL_HW_WR_CONN_INFRA_REG(CONN_UART_PTA_LCR_ADDR, 0xBF);
+ GDL_HW_WR_CONN_INFRA_REG(CONN_UART_PTA_DLL_ADDR, 1);
+ GDL_HW_WR_CONN_INFRA_REG(CONN_UART_PTA_DLM_ADDR, 0);
+ GDL_HW_WR_CONN_INFRA_REG(CONN_UART_PTA_LCR_ADDR, 3);
+
+ /* 20191008 after DE checking, add CONN_UART_PTA_FCR_ADDR read-back checking */
+
+ /* dump value before setting */
+ GDL_HW_RD_CONN_INFRA_REG(CONN_UART_PTA_FCR_ADDR);
+ GDL_HW_WR_CONN_INFRA_REG(CONN_UART_PTA_FCR_ADDR, 0x37);
+ /* dump value after setting and poll until bit7 become 1 or timeout */
+ GDL_HW_POLL_CONN_INFRA_ENTRY(CONN_UART_PTA_FCR_RFTL_HIGH_BIT, 1, POLL_DEFAULT, &poll_okay);
+ if (!poll_okay) {
+ if (reg_rw_log)
+ gps_dl_set_show_reg_rw_log(show_log);
+ GDL_LOGE("CONN_UART_PTA_FCR bit7 not become 1, fail");
+ return false;
+ }
+
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_WFSET_PTA_CTRL_r_wfset_uart_apb_hw_en, 1);
+
+ /* 20191008 after DE checking, add this step */
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_BTSET_PTA_CTRL_r_btset_uart_apb_hw_en, 1);
+
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_WFSET_PTA_CTRL_r_wfset_lte_pta_en, 1);
+
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_TMR_CTRL_1_r_idc_2nd_byte_tmout, 4); /* us */
+
+ if (reg_rw_log)
+ gps_dl_set_show_reg_rw_log(show_log);
+
+ return true;
+}
+
+void gps_dl_hw_deinit_pta_uart(void)
+{
+ /* Currently no need to do pta uart deinit */
+}
+
+
+#define PTA_1M_CNT_VALUE 26 /* mobile platform uses 26M */
+
+bool gps_dl_hw_is_pta_init_done(void)
+{
+ bool done;
+ unsigned int pta_en;
+ unsigned int pta_arb_en;
+ unsigned int pta_1m_cnt;
+
+ pta_en = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_PTA6_RO_PTA_CTRL_ro_pta_en);
+ pta_arb_en = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_PTA6_RO_PTA_CTRL_ro_en_pta_arb);
+ pta_1m_cnt = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_PTA6_PTA_CLK_CFG_r_pta_1m_cnt);
+
+ done = ((pta_en == 1) && (pta_arb_en == 1) && (pta_1m_cnt == PTA_1M_CNT_VALUE));
+ GDL_LOGD("done = %d, pta_en = %d, pta_arb_en = %d, pta_1m_cnt = 0x%x",
+ done, pta_en, pta_arb_en, pta_1m_cnt);
+
+ return done;
+}
+
+void gps_dl_hw_init_pta(void)
+{
+ unsigned int pta_en;
+ unsigned int pta_arb_en;
+
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_PTA_CLK_CFG_r_pta_1m_cnt, PTA_1M_CNT_VALUE);
+
+ /* Note: GPS use WFSET */
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_WFSET_PTA_CTRL_r_wfset_en_pta_arb, 1);
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_WFSET_PTA_CTRL_r_wfset_pta_en, 1);
+
+ /* just confirm status change properly */
+ pta_en = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_PTA6_RO_PTA_CTRL_ro_pta_en);
+ pta_arb_en = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_PTA6_RO_PTA_CTRL_ro_en_pta_arb);
+
+ if (!((pta_en == 1) && (pta_arb_en == 1))) {
+ /* should not happen, do nothing but just show log */
+ GDL_LOGE("pta_en = %d, pta_arb_en = %d, fail", pta_en, pta_arb_en);
+ } else
+ GDL_LOGI("pta_en = %d, pta_arb_en = %d, okay", pta_en, pta_arb_en);
+}
+
+void gps_dl_hw_deinit_pta(void)
+{
+ /* Currently no need to do pta deinit */
+}
+
+
+void gps_dl_hw_claim_pta_used_by_gps(void)
+{
+ /* Currently it's empty */
+}
+
+void gps_dl_hw_disclaim_pta_used_by_gps(void)
+{
+ /* Currently it's empty */
+}
+
+void gps_dl_hw_set_pta_blanking_parameter(void)
+{
+ /* Set timeout threashold: ms */
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_TMR_CTRL_3_r_gps_l5_blank_tmr_thld, 3);
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_TMR_CTRL_3_r_gps_l1_blank_tmr_thld, 3);
+
+ /* Set blanking source: both LTE and NR */
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_GPS_BLANK_CFG_r_idc_gps_l1_blank_src, 2);
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_GPS_BLANK_CFG_r_idc_gps_l5_blank_src, 2);
+
+ /* Use IDC mode */
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_PTA6_GPS_BLANK_CFG_r_gps_blank_src, 0);
+}
+
+/*
+ * COS_SEMA_COEX_INDEX = 5(see conninfra/platform/include/consys_hw.h)
+ * GPS use M3
+ */
+#define COS_SEMA_COEX_STA_ENTRY_FOR_GPS \
+ CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_STA_CONN_SEMA05_M3_OWN_STA
+
+#define COS_SEMA_COEX_REL_ENTRY_FOR_GPS \
+ CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_REL_CONN_SEMA05_M3_OWN_REL
+
+bool gps_dl_hw_take_conn_coex_hw_sema(unsigned int try_timeout_ms)
+{
+ bool okay;
+ bool show_log;
+ unsigned int poll_us, poll_max_us;
+ unsigned int val;
+
+ show_log = gps_dl_set_show_reg_rw_log(true);
+ /* poll until value is expected or timeout */
+ poll_us = 0;
+ poll_max_us = POLL_US * 1000 * try_timeout_ms;
+ okay = false;
+ while (!okay) {
+ val = GDL_HW_GET_CONN_INFRA_ENTRY(COS_SEMA_COEX_STA_ENTRY_FOR_GPS);
+ /* 2bit value:
+ * 0 -> need waiting
+ * 1,3 -> okay; 2 -> already taken
+ */
+ if (val != 0) {
+ okay = true;
+ break;
+ }
+ if (poll_us >= poll_max_us) {
+ okay = false;
+ break;
+ }
+ gps_dl_wait_us(POLL_INTERVAL_US);
+ poll_us += POLL_INTERVAL_US;
+ }
+ gps_dl_set_show_reg_rw_log(show_log);
+
+ if (!okay)
+ GDL_LOGW("okay = %d", okay);
+ else
+ GDL_LOGD("okay = %d", okay);
+ return okay;
+}
+
+void gps_dl_hw_give_conn_coex_hw_sema(void)
+{
+ bool show_log;
+
+ show_log = gps_dl_set_show_reg_rw_log(true);
+ GDL_HW_SET_CONN_INFRA_ENTRY(COS_SEMA_COEX_REL_ENTRY_FOR_GPS, 1);
+ gps_dl_set_show_reg_rw_log(show_log);
+
+ GDL_LOGD("");
+}
+#endif /* GPS_DL_HAS_PTA */
+
+/*
+ * COS_SEMA_RFSPI_INDEX = 11(see conninfra/platform/include/consys_hw.h)
+ * GPS use M3
+ */
+#define COS_SEMA_RFSPI_STA_ENTRY_FOR_GPS \
+ CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_STA_CONN_SEMA11_M3_OWN_STA
+
+#define COS_SEMA_RFSPI_REL_ENTRY_FOR_GPS \
+ CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_REL_CONN_SEMA11_M3_OWN_REL
+
+bool gps_dl_hw_take_conn_rfspi_hw_sema(unsigned int try_timeout_ms)
+{
+ bool okay;
+ bool show_log;
+ unsigned int poll_us, poll_max_us;
+ unsigned int val;
+
+ show_log = gps_dl_set_show_reg_rw_log(true);
+ /* poll until value is expected or timeout */
+ poll_us = 0;
+ poll_max_us = POLL_US * 1000 * try_timeout_ms;
+ okay = false;
+ while (!okay) {
+ val = GDL_HW_GET_CONN_INFRA_ENTRY(COS_SEMA_RFSPI_STA_ENTRY_FOR_GPS);
+ /* 2bit value:
+ * 0 -> need waiting
+ * 1,3 -> okay; 2 -> already taken
+ */
+ if (val != 0) {
+ okay = true;
+ break;
+ }
+ if (poll_us >= poll_max_us) {
+ okay = false;
+ break;
+ }
+ gps_dl_wait_us(POLL_INTERVAL_US);
+ poll_us += POLL_INTERVAL_US;
+ }
+ gps_dl_set_show_reg_rw_log(show_log);
+
+ GDL_LOGI("okay = %d", okay);
+
+ return okay;
+}
+
+void gps_dl_hw_give_conn_rfspi_hw_sema(void)
+{
+ bool show_log;
+
+ show_log = gps_dl_set_show_reg_rw_log(true);
+ GDL_HW_SET_CONN_INFRA_ENTRY(COS_SEMA_RFSPI_REL_ENTRY_FOR_GPS, 1);
+ gps_dl_set_show_reg_rw_log(show_log);
+
+ GDL_LOGI("");
+}
+
+
+#define GPS_DL_RFSPI_BUSY_POLL_MAX (10*1000*POLL_US) /* 10ms */
+
+/* note: must be protect by gps_dl_hw_take_conn_rfspi_hw_sema */
+static bool gps_dl_hw_gps_fmspi_state_backup(unsigned int *p_rd_ext_en_bk, unsigned int *p_rd_ext_cnt_bk)
+{
+ bool okay = true;
+ bool poll_okay;
+
+ if (p_rd_ext_en_bk == NULL || p_rd_ext_cnt_bk == NULL)
+ return false;
+
+ GDL_HW_POLL_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_SPI_STA_FM_BUSY, 0,
+ GPS_DL_RFSPI_BUSY_POLL_MAX, &poll_okay);
+ if (!poll_okay)
+ return false;
+
+ *p_rd_ext_en_bk = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_EN);
+ *p_rd_ext_cnt_bk = GDL_HW_GET_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_CNT);
+ return okay;
+}
+
+/* note: must be protect by gps_dl_hw_take_conn_rfspi_hw_sema */
+static void gps_dl_hw_gps_fmspi_state_restore(unsigned int rd_ext_en_bk, unsigned int rd_ext_cnt_bk)
+{
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_EN, rd_ext_en_bk);
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_CNT, rd_ext_cnt_bk);
+}
+
+/* note: must be protect by gps_dl_hw_take_conn_rfspi_hw_sema */
+static bool gps_dl_hw_gps_fmspi_read_rfcr(unsigned int addr, unsigned int *p_val)
+{
+ unsigned int val;
+ bool okay;
+ bool poll_okay;
+ unsigned int tmp;
+
+ if (p_val == NULL)
+ return false;
+
+ GDL_HW_POLL_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_SPI_STA_FM_BUSY, 0,
+ GPS_DL_RFSPI_BUSY_POLL_MAX, &poll_okay);
+ if (!poll_okay)
+ return false;
+
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_EN, 0);
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_CNT, 0);
+
+ tmp = ((addr & 0xFFF) | (1 << 12UL) | (4 << 13UL) | (0 << 16UL));
+ GDL_HW_WR_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_FM_ADDR_ADDR, tmp);
+ GDL_HW_WR_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_FM_WDAT_ADDR, 0);
+
+ GDL_HW_POLL_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_SPI_STA_FM_BUSY, 0,
+ GPS_DL_RFSPI_BUSY_POLL_MAX, &poll_okay);
+ if (!poll_okay) {
+ GDL_HW_RD_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_FM_RDAT_ADDR);
+ return false;
+ }
+
+ val = GDL_HW_RD_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_FM_RDAT_ADDR);
+ *p_val = val;
+ okay = true;
+ return okay;
+}
+
+static bool gps_dl_hw_gps_fmspi_write_rfcr(unsigned int addr, unsigned int val)
+{
+ bool okay;
+ bool poll_okay;
+ unsigned int tmp;
+
+ GDL_HW_POLL_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_SPI_STA_FM_BUSY, 0,
+ GPS_DL_RFSPI_BUSY_POLL_MAX, &poll_okay);
+ if (!poll_okay)
+ return false;
+
+ tmp = ((addr & 0xFFF) | (0 << 12UL) | (4 << 13UL) | (0 << 16UL));
+ GDL_HW_WR_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_FM_ADDR_ADDR, tmp);
+ GDL_HW_WR_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_FM_WDAT_ADDR, val);
+
+ GDL_HW_POLL_CONN_INFRA_ENTRY(CONN_RF_SPI_MST_REG_SPI_STA_FM_BUSY, 0,
+ GPS_DL_RFSPI_BUSY_POLL_MAX, &poll_okay);
+ if (!poll_okay) {
+ GDL_HW_RD_CONN_INFRA_REG(CONN_RF_SPI_MST_ADDR_SPI_FM_RDAT_ADDR);
+ return false;
+ }
+
+ okay = true;
+ return okay;
+}
+
+void gps_dl_hw_gps_dump_gps_rf_cr(void)
+{
+ bool show_log, backup_okay;
+ unsigned int addr, val;
+ unsigned int rd_ext_en_bk, rd_ext_cnt_bk;
+
+ gps_dl_hw_take_conn_rfspi_hw_sema(100);
+ show_log = gps_dl_set_show_reg_rw_log(true);
+ backup_okay = gps_dl_hw_gps_fmspi_state_backup(&rd_ext_en_bk, &rd_ext_cnt_bk);
+
+ /* read: 0x500 ~ 0x51b */
+ for (addr = 0x500; addr <= 0x51B; addr++) {
+ if (gps_dl_hw_gps_fmspi_read_rfcr(addr, &val))
+ GDL_LOGW("rd: addr = 0x%x, val = 0x%x", addr, val);
+ else
+ GDL_LOGW("rd: addr = 0x%x, fail", addr);
+ }
+
+ /* write: 0x51a = 1 */
+ addr = 0x51A;
+ val = 1;
+ if (gps_dl_hw_gps_fmspi_write_rfcr(addr, val))
+ GDL_LOGW("wr: addr = 0x%x, val = 0x%x, okay", addr, val);
+ else
+ GDL_LOGW("wr: addr = 0x%x, val = 0x%x, fail", addr, val);
+
+ /* read: 0x51a & 0x51b */
+ for (addr = 0x51A; addr <= 0x51B; addr++) {
+ if (gps_dl_hw_gps_fmspi_read_rfcr(addr, &val))
+ GDL_LOGW("rd: addr = 0x%x, val = 0x%x", addr, val);
+ else
+ GDL_LOGW("rd: addr = 0x%x, fail", addr);
+ }
+
+ if (backup_okay)
+ gps_dl_hw_gps_fmspi_state_restore(rd_ext_en_bk, rd_ext_cnt_bk);
+ else
+ GDL_LOGW("not do gps_dl_hw_gps_fmspi_state_restore due to backup failed!");
+ gps_dl_set_show_reg_rw_log(show_log);
+ gps_dl_hw_give_conn_rfspi_hw_sema();
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_gps.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_gps.c
new file mode 100644
index 0000000..a6f3236
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_gps.c
@@ -0,0 +1,500 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+
+#include "gps_dl_context.h"
+#include "gps_dl_time_tick.h"
+#include "gps_dsp_fsm.h"
+#include "gps_dl_hw_api.h"
+#include "gps_dl_hw_priv_util.h"
+#include "gps/bgf_gps_dma.h"
+#include "gps/gps_aon_top.h"
+#include "gps/gps_usrt_apb.h"
+#include "gps/gps_l5_usrt_apb.h"
+
+#define GPS_ADDR_ENTRY_NUM (1)
+static const struct gps_dl_addr_map_entry g_gps_addr_table[GPS_ADDR_ENTRY_NUM] = {
+ /* Put base list here: */
+ /* BGF_GPS_CFG_BASE */
+ {0x18C00000, 0x80000000, 0x90000},
+};
+
+unsigned int gps_bus_to_host(unsigned int gps_addr)
+{
+ unsigned int i;
+ const struct gps_dl_addr_map_entry *p;
+
+ for (i = 0; i < GPS_ADDR_ENTRY_NUM; i++) {
+ p = &g_gps_addr_table[i];
+ if (gps_addr >= p->bus_addr &&
+ gps_addr < (p->bus_addr + p->length))
+ return ((gps_addr - p->bus_addr) + p->host_addr);
+ }
+
+ return 0;
+}
+
+
+void gps_dl_hw_set_dma_start(enum gps_dl_hal_dma_ch_index channel,
+ struct gdl_hw_dma_transfer *p_transfer)
+{
+ unsigned int bus_addr_of_data_start;
+ unsigned int bus_addr_of_buf_start;
+ unsigned int gdl_ret;
+
+ gdl_ret = gps_dl_emi_remap_phy_to_bus_addr(p_transfer->transfer_start_addr, &bus_addr_of_data_start);
+ gdl_ret = gps_dl_emi_remap_phy_to_bus_addr(p_transfer->buf_start_addr, &bus_addr_of_buf_start);
+
+ switch (channel) {
+ case GPS_DL_DMA_LINK0_A2D:
+ if (gps_dl_is_1byte_mode())
+ GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA1_CON_ADDR, 0x00128014);
+ else
+ GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA1_CON_ADDR, 0x00128016);
+
+ GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA1_PGMADDR_PGMADDR_ADDR,
+ bus_addr_of_data_start);
+ GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA1_WPTO_WPTO_ADDR,
+ bus_addr_of_buf_start);
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA1_WPPT_WPPT, p_transfer->len_to_wrap);
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA1_COUNT_LEN, p_transfer->transfer_max_len);
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA1_START_STR, 1);
+ break;
+ case GPS_DL_DMA_LINK0_D2A:
+ if (gps_dl_is_1byte_mode())
+ GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA2_CON_ADDR, 0x00078018);
+ else
+ GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA2_CON_ADDR, 0x0007801A);
+
+ GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA2_PGMADDR_PGMADDR_ADDR,
+ bus_addr_of_data_start);
+ GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA2_WPTO_WPTO_ADDR,
+ bus_addr_of_buf_start);
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA2_WPPT_WPPT, p_transfer->len_to_wrap);
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA2_COUNT_LEN, p_transfer->transfer_max_len);
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA2_START_STR, 1);
+ break;
+ case GPS_DL_DMA_LINK1_A2D:
+ if (gps_dl_is_1byte_mode())
+ GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA3_CON_ADDR, 0x00328014);
+ else
+ GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA3_CON_ADDR, 0x00328016);
+
+ GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA3_PGMADDR_PGMADDR_ADDR,
+ bus_addr_of_data_start);
+ GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA3_WPTO_WPTO_ADDR,
+ bus_addr_of_buf_start);
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA3_WPPT_WPPT, p_transfer->len_to_wrap);
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA3_COUNT_LEN, p_transfer->transfer_max_len);
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA3_START_STR, 1);
+ break;
+ case GPS_DL_DMA_LINK1_D2A:
+ if (gps_dl_is_1byte_mode())
+ GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA4_CON_ADDR, 0x00278018);
+ else
+ GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA4_CON_ADDR, 0x0027801A);
+
+ GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA4_PGMADDR_PGMADDR_ADDR,
+ bus_addr_of_data_start);
+ GDL_HW_WR_GPS_REG(BGF_GPS_DMA_DMA4_WPTO_WPTO_ADDR,
+ bus_addr_of_buf_start);
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA4_WPPT_WPPT, p_transfer->len_to_wrap);
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA4_COUNT_LEN, p_transfer->transfer_max_len);
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA4_START_STR, 1);
+ break;
+ default:
+ return;
+ }
+}
+
+void gps_dl_hw_set_dma_stop(enum gps_dl_hal_dma_ch_index channel)
+{
+ /* Poll until DMA IDLE */
+ switch (channel) {
+ case GPS_DL_DMA_LINK0_A2D:
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA1_START_STR, 0);
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA1_ACKINT_ACK, 1);
+ break;
+ case GPS_DL_DMA_LINK0_D2A:
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA2_START_STR, 0);
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA2_ACKINT_ACK, 1);
+ break;
+ case GPS_DL_DMA_LINK1_A2D:
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA3_START_STR, 0);
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA3_ACKINT_ACK, 1);
+ break;
+ case GPS_DL_DMA_LINK1_D2A:
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA4_START_STR, 0);
+ GDL_HW_SET_GPS_ENTRY(BGF_GPS_DMA_DMA4_ACKINT_ACK, 1);
+ break;
+ default:
+ return;
+ }
+}
+
+bool gps_dl_hw_get_dma_int_status(enum gps_dl_hal_dma_ch_index channel)
+{
+ /* ASSERT(channel >= 0 && channel <= GPS_DL_DMA_CH_NUM); */
+ switch (channel) {
+ case GPS_DL_DMA_LINK0_A2D:
+ return (bool)GDL_HW_GET_GPS_ENTRY(BGF_GPS_DMA_DMA1_INTSTA_INT);
+ case GPS_DL_DMA_LINK0_D2A:
+ return (bool)GDL_HW_GET_GPS_ENTRY(BGF_GPS_DMA_DMA2_INTSTA_INT);
+ case GPS_DL_DMA_LINK1_A2D:
+ return (bool)GDL_HW_GET_GPS_ENTRY(BGF_GPS_DMA_DMA3_INTSTA_INT);
+ case GPS_DL_DMA_LINK1_D2A:
+ return (bool)GDL_HW_GET_GPS_ENTRY(BGF_GPS_DMA_DMA4_INTSTA_INT);
+ default:
+ return false;
+ }
+}
+
+void gps_dl_hw_save_dma_status_struct(
+ enum gps_dl_hal_dma_ch_index ch, struct gps_dl_hw_dma_status_struct *p)
+{
+ unsigned int offset =
+ (BGF_GPS_DMA_DMA2_WPPT_ADDR - BGF_GPS_DMA_DMA1_WPPT_ADDR) * ch;
+
+ p->wrap_count = GDL_HW_RD_GPS_REG(BGF_GPS_DMA_DMA1_WPPT_ADDR + offset);
+ p->wrap_to_addr = GDL_HW_RD_GPS_REG(BGF_GPS_DMA_DMA1_WPTO_ADDR + offset);
+ p->total_count = GDL_HW_RD_GPS_REG(BGF_GPS_DMA_DMA1_COUNT_ADDR + offset);
+ p->config = GDL_HW_RD_GPS_REG(BGF_GPS_DMA_DMA1_CON_ADDR + offset);
+ p->start_flag = GDL_HW_RD_GPS_REG(BGF_GPS_DMA_DMA1_START_ADDR + offset);
+ p->intr_flag = GDL_HW_RD_GPS_REG(BGF_GPS_DMA_DMA1_INTSTA_ADDR + offset);
+ p->left_count = GDL_HW_RD_GPS_REG(BGF_GPS_DMA_DMA1_RLCT_ADDR + offset);
+ p->curr_addr = GDL_HW_RD_GPS_REG(BGF_GPS_DMA_DMA1_PGMADDR_ADDR + offset);
+ p->state = GDL_HW_RD_GPS_REG(BGF_GPS_DMA_DMA1_STATE_ADDR + offset);
+}
+
+void gps_dl_hw_print_dma_status_struct(
+ enum gps_dl_hal_dma_ch_index ch, struct gps_dl_hw_dma_status_struct *p)
+{
+ if (!gps_dl_show_reg_wait_log())
+ return;
+
+ GDL_LOGW("dma ch %d, wrap = 0x%08x; tra = 0x%08x, count l/w/t = %d/%d/%d, str/int/sta = %d/%d/%d",
+ ch, p->wrap_to_addr,
+ p->curr_addr, p->left_count, p->wrap_count, p->total_count,
+ GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_START_STR, p->start_flag),
+ GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_INTSTA_INT, p->intr_flag),
+ GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_STATE_STATE, p->state));
+
+ GDL_LOGW("dma ch %d, conf = 0x%08x, master = %d, b2w = %d, w2b = %d, size = %d",
+ ch, p->config,
+ GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_CON_MAS, p->config),
+ GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_CON_B2W, p->config),
+ GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_CON_W2B, p->config),
+ GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_CON_SIZE, p->config));
+}
+
+enum GDL_RET_STATUS gps_dl_hw_wait_until_dma_complete_and_stop_it(
+ enum gps_dl_hal_dma_ch_index ch, int timeout_usec, bool return_if_not_start)
+{
+ struct gps_dl_hw_dma_status_struct dma_status;
+ struct gps_dl_hw_usrt_status_struct usrt_status;
+ enum gps_dl_link_id_enum link_id = DMA_CH_TO_LINK_ID(ch);
+ bool last_rw_log_on;
+ unsigned long tick0, tick1;
+ bool conninfra_okay;
+ bool do_stop = true;
+ enum GDL_RET_STATUS ret = GDL_OKAY;
+ int loop_cnt;
+
+ tick0 = gps_dl_tick_get();
+ loop_cnt = 0;
+ while (1) {
+ gps_dl_hw_save_dma_status_struct(ch, &dma_status);
+ if (gps_dl_only_show_wait_done_log())
+ last_rw_log_on = gps_dl_set_show_reg_rw_log(false);
+ else
+ gps_dl_hw_print_dma_status_struct(ch, &dma_status);
+
+ if (GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_START_STR, dma_status.start_flag)) {
+ if (gps_dl_only_show_wait_done_log()) {
+ gps_dl_set_show_reg_rw_log(last_rw_log_on);
+ gps_dl_hw_print_dma_status_struct(ch, &dma_status);
+ gps_dl_hw_save_dma_status_struct(ch, &dma_status);
+ }
+ break; /* to next while-loop */
+ } else if (return_if_not_start) {
+ ret = GDL_OKAY;
+ do_stop = false;
+ goto _end;
+ }
+
+ tick1 = gps_dl_tick_get();
+ if (timeout_usec > GPS_DL_RW_NO_TIMEOUT && (
+ gps_dl_tick_delta_to_usec(tick0, tick1) >= timeout_usec ||
+ loop_cnt * GDL_HW_STATUS_POLL_INTERVAL_USEC >= timeout_usec)) {
+ ret = GDL_FAIL_TIMEOUT;
+ do_stop = false;
+ goto _end;
+ }
+
+ gps_dl_wait_us(GDL_HW_STATUS_POLL_INTERVAL_USEC);
+ loop_cnt++;
+ }
+
+ while (1) {
+ conninfra_okay = gps_dl_conninfra_is_okay_or_handle_it(NULL, true);
+ if (!conninfra_okay) {
+ ret = GDL_FAIL_CONN_NOT_OKAY;
+ do_stop = false;
+ break;
+ }
+
+ gps_dl_hw_save_dma_status_struct(ch, &dma_status);
+ gps_dl_hw_save_usrt_status_struct(link_id, &usrt_status);
+ if (gps_dl_only_show_wait_done_log())
+ last_rw_log_on = gps_dl_set_show_reg_rw_log(false);
+ else {
+ gps_dl_hw_print_dma_status_struct(ch, &dma_status);
+ gps_dl_hw_print_usrt_status_struct(link_id, &usrt_status);
+ }
+
+ if (GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_INTSTA_INT, dma_status.intr_flag) &&
+ GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_STATE_STATE, dma_status.state) == 0x01) {
+ if (gps_dl_only_show_wait_done_log()) {
+ gps_dl_set_show_reg_rw_log(last_rw_log_on);
+ gps_dl_hw_print_dma_status_struct(ch, &dma_status);
+ gps_dl_hw_save_dma_status_struct(ch, &dma_status);
+ }
+
+ /* DMA ready to stop */
+ gps_dl_hw_set_dma_stop(ch);
+ gps_dl_hw_save_dma_status_struct(ch, &dma_status);
+ gps_dl_hw_print_dma_status_struct(ch, &dma_status);
+ ret = GDL_OKAY;
+ do_stop = true;
+ break;
+ }
+
+ tick1 = gps_dl_tick_get();
+ if (timeout_usec > GPS_DL_RW_NO_TIMEOUT && (
+ gps_dl_tick_delta_to_usec(tick0, tick1) >= timeout_usec ||
+ loop_cnt * GDL_HW_STATUS_POLL_INTERVAL_USEC >= timeout_usec)) {
+ ret = GDL_FAIL_TIMEOUT;
+ do_stop = false;
+ break;
+ }
+
+ gps_dl_wait_us(GDL_HW_STATUS_POLL_INTERVAL_USEC);
+ loop_cnt++;
+ }
+
+_end:
+ tick1 = gps_dl_tick_get();
+ GDL_LOGW("ch = %d, d_us = %d, do_stop = %d, ret = %s",
+ ch, gps_dl_tick_delta_to_usec(tick0, tick1), do_stop, gdl_ret_to_name(ret));
+ return ret;
+}
+
+unsigned int gps_dl_hw_get_dma_left_len(enum gps_dl_hal_dma_ch_index channel)
+{
+ /* ASSERT(channel >= 0 && channel <= GPS_DL_DMA_CH_NUM); */
+ switch (channel) {
+ case GPS_DL_DMA_LINK0_A2D:
+ return GDL_HW_GET_GPS_ENTRY(BGF_GPS_DMA_DMA1_RLCT_RLCT);
+ case GPS_DL_DMA_LINK0_D2A:
+ return GDL_HW_GET_GPS_ENTRY(BGF_GPS_DMA_DMA2_RLCT_RLCT);
+ case GPS_DL_DMA_LINK1_A2D:
+ return GDL_HW_GET_GPS_ENTRY(BGF_GPS_DMA_DMA3_RLCT_RLCT);
+ case GPS_DL_DMA_LINK1_D2A:
+ return GDL_HW_GET_GPS_ENTRY(BGF_GPS_DMA_DMA4_RLCT_RLCT);
+ default:
+ return 0;
+ }
+}
+
+void gps_dl_hw_get_link_status(
+ enum gps_dl_link_id_enum link_id, struct gps_dl_hw_link_status_struct *p)
+{
+ unsigned int reg_val;
+ unsigned int offset =
+ (GPS_L5_USRT_APB_APB_CTRL_ADDR - GPS_USRT_APB_APB_CTRL_ADDR) * link_id;
+
+ /* todo: link_id error handling */
+
+ if (link_id == GPS_DATA_LINK_ID0) {
+ p->tx_dma_done = gps_dl_hw_get_dma_int_status(GPS_DL_DMA_LINK0_A2D);
+ p->rx_dma_done = gps_dl_hw_get_dma_int_status(GPS_DL_DMA_LINK0_D2A);
+ } else if (link_id == GPS_DATA_LINK_ID1) {
+ p->tx_dma_done = gps_dl_hw_get_dma_int_status(GPS_DL_DMA_LINK1_A2D);
+ p->rx_dma_done = gps_dl_hw_get_dma_int_status(GPS_DL_DMA_LINK1_D2A);
+ } else {
+ p->tx_dma_done = false;
+ p->rx_dma_done = false;
+ }
+
+ reg_val = GDL_HW_RD_GPS_REG(GPS_USRT_APB_APB_STA_ADDR + offset);
+ p->usrt_has_data = GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_TX_IND, reg_val);
+ p->usrt_has_nodata = GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_NODAINTB, reg_val);
+}
+
+void gps_dl_hw_save_usrt_status_struct(
+ enum gps_dl_link_id_enum link_id, struct gps_dl_hw_usrt_status_struct *p)
+{
+ unsigned int offset =
+ (GPS_L5_USRT_APB_APB_CTRL_ADDR - GPS_USRT_APB_APB_CTRL_ADDR) * link_id;
+
+ p->ctrl_setting = GDL_HW_RD_GPS_REG(GPS_USRT_APB_APB_CTRL_ADDR + offset);
+ p->intr_enable = GDL_HW_RD_GPS_REG(GPS_USRT_APB_APB_INTEN_ADDR + offset);
+ p->state = GDL_HW_RD_GPS_REG(GPS_USRT_APB_APB_STA_ADDR + offset);
+
+ p->mcub_a2d_flag = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCUB_A2DF_ADDR + offset);
+ p->mcub_d2a_flag = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCUB_D2AF_ADDR + offset);
+
+ p->mcub_a2d_d0 = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCU_A2D0_ADDR + offset);
+ p->mcub_a2d_d1 = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCU_A2D1_ADDR + offset);
+ p->mcub_d2a_d0 = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCU_D2A0_ADDR + offset);
+ p->mcub_d2a_d1 = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCU_D2A1_ADDR + offset);
+}
+
+void gps_dl_hw_print_usrt_status_struct(
+ enum gps_dl_link_id_enum link_id, struct gps_dl_hw_usrt_status_struct *p)
+{
+ if (!gps_dl_show_reg_wait_log())
+ return;
+
+ GDL_LOGXW(link_id, "usrt ctrl = 0x%08x[DMA_EN RX=%d,TX=%d; 1BYTE=%d], intr_en = 0x%08x",
+ p->ctrl_setting,
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_CTRL_RX_EN, p->ctrl_setting),
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_CTRL_TX_EN, p->ctrl_setting),
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_CTRL_BYTEN, p->ctrl_setting),
+ p->intr_enable);
+
+ GDL_LOGXW(link_id, "usrt state = 0x%08x, [UOEFS]RX=%d%d%d%d(%d),TX=%d%d%d%d(%d)",
+ p->state,
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_RX_UNDR, p->state),
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_RX_OVF, p->state),
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_RX_EMP, p->state),
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_RX_FULL, p->state),
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_RX_ST, p->state),
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_TX_UNDR, p->state),
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_TX_OVF, p->state),
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_TX_EMP, p->state),
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_TX_FULL, p->state),
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_TX_ST, p->state));
+
+ GDL_LOGXW(link_id, "usrt TxReg_em=%d, TX_IND=%d, TX_IND=%d, U_em=%d, NOD_INT=%d",
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_REGE, p->state),
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_TX_IND, p->state),
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_TXINTB, p->state),
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_URAME, p->state),
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_NODAINTB, p->state));
+
+ GDL_LOGXW(link_id, "mcub d2a flag=0x%08x, d0=0x%08x, d1=0x%08x",
+ p->mcub_d2a_flag, p->mcub_d2a_d0, p->mcub_d2a_d1);
+
+ GDL_LOGXW(link_id, "mcub a2d flag=0x%08x, d0=0x%08x, d1=0x%08x",
+ p->mcub_a2d_flag, p->mcub_a2d_d0, p->mcub_a2d_d1);
+}
+
+void gps_dl_hw_switch_dsp_jtag(void)
+{
+ unsigned int value, value_new;
+
+ value = GDL_HW_RD_GPS_REG(0x80073160);
+ value_new = value & 0xFFFFFFFE;
+ value_new = value_new | ((~(value & 0x00000001)) & 0x00000001);
+ GDL_HW_WR_GPS_REG(0x80073160, value_new);
+}
+
+enum GDL_HW_RET gps_dl_hw_get_mcub_info(enum gps_dl_link_id_enum link_id, struct gps_dl_hal_mcub_info *p)
+{
+ if (p == NULL)
+ return E_INV_PARAMS;
+
+ if (link_id == GPS_DATA_LINK_ID0) {
+ p->flag = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCUB_D2AF_ADDR);
+ p->dat0 = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCU_D2A0_ADDR);
+ p->dat1 = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCU_D2A1_ADDR);
+ return HW_OKAY;
+ } else if (link_id == GPS_DATA_LINK_ID1) {
+ p->flag = GDL_HW_RD_GPS_REG(GPS_L5_USRT_APB_MCUB_D2AF_ADDR);
+ p->dat0 = GDL_HW_RD_GPS_REG(GPS_L5_USRT_APB_MCU_D2A0_ADDR);
+ p->dat1 = GDL_HW_RD_GPS_REG(GPS_L5_USRT_APB_MCU_D2A1_ADDR);
+ return HW_OKAY;
+ } else
+ return E_INV_PARAMS;
+}
+
+void gps_dl_hw_clear_mcub_d2a_flag(enum gps_dl_link_id_enum link_id, unsigned int d2a_flag)
+{
+ if (link_id == GPS_DATA_LINK_ID0)
+ GDL_HW_WR_GPS_REG(GPS_USRT_APB_MCUB_D2AF_ADDR, d2a_flag);
+ else if (link_id == GPS_DATA_LINK_ID1)
+ GDL_HW_WR_GPS_REG(GPS_L5_USRT_APB_MCUB_D2AF_ADDR, d2a_flag);
+}
+
+unsigned int gps_dl_hw_get_mcub_a2d_flag(enum gps_dl_link_id_enum link_id)
+{
+ unsigned int val = 0;
+
+ if (link_id == GPS_DATA_LINK_ID0)
+ val = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCUB_A2DF_ADDR);
+ else if (link_id == GPS_DATA_LINK_ID1)
+ val = GDL_HW_RD_GPS_REG(GPS_L5_USRT_APB_MCUB_A2DF_ADDR);
+
+ return val;
+}
+
+enum GDL_RET_STATUS gps_dl_hw_mcub_dsp_read_request(enum gps_dl_link_id_enum link_id, u16 dsp_addr)
+{
+ unsigned int a2d_flag = 0;
+
+ /* Fill addr to A2D0 and trigger A2DF bit2
+ * (0x04, GPS_MCUB_A2DF_MASK_DSP_REG_READ_REQ),
+ * the result will be put into D2A0 after D2AF bit1
+ * (0x02, GPS_MCUB_D2AF_MASK_DSP_REG_READ_READY) set.
+ */
+
+ if (link_id == GPS_DATA_LINK_ID0)
+ a2d_flag = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MCUB_A2DF_ADDR);
+ else if (link_id == GPS_DATA_LINK_ID1)
+ a2d_flag = GDL_HW_RD_GPS_REG(GPS_L5_USRT_APB_MCUB_A2DF_ADDR);
+ else
+ return GDL_FAIL_INVAL;
+
+ /* A2DF bit2 must be cleared, otherwise dsp is busy */
+ if ((a2d_flag & GPS_MCUB_A2DF_MASK_DSP_REG_READ_REQ) != 0) {
+ GDL_LOGXD(link_id, "a2d_flag = 0x%x, mask = 0x%x, busy",
+ a2d_flag, GPS_MCUB_A2DF_MASK_DSP_REG_READ_REQ);
+ return GDL_FAIL_BUSY;
+ }
+
+ if (link_id == GPS_DATA_LINK_ID0) {
+ GDL_HW_WR_GPS_REG(GPS_USRT_APB_MCU_A2D0_ADDR, (dsp_addr & 0xFFFF));
+ GDL_HW_WR_GPS_REG(GPS_USRT_APB_MCUB_A2DF_ADDR,
+ GPS_MCUB_A2DF_MASK_DSP_REG_READ_REQ);
+ } else if (link_id == GPS_DATA_LINK_ID1) {
+ GDL_HW_WR_GPS_REG(GPS_L5_USRT_APB_MCU_A2D0_ADDR, (dsp_addr & 0xFFFF));
+ GDL_HW_WR_GPS_REG(GPS_L5_USRT_APB_MCUB_A2DF_ADDR,
+ GPS_MCUB_A2DF_MASK_DSP_REG_READ_REQ);
+ }
+
+ return GDL_OKAY;
+}
+
+void gps_dl_hw_print_ms_counter_status(void)
+{
+ bool show_log;
+
+ show_log = gps_dl_set_show_reg_rw_log(true);
+ gps_dl_bus_rd_opt(GPS_DL_GPS_BUS, GPS_AON_TOP_DSLEEP_CTL_ADDR, BMASK_RW_FORCE_PRINT);
+ gps_dl_bus_rd_opt(GPS_DL_GPS_BUS, GPS_AON_TOP_WAKEUP_CTL_ADDR, BMASK_RW_FORCE_PRINT);
+ gps_dl_bus_rd_opt(GPS_DL_GPS_BUS, GPS_AON_TOP_TCXO_MS_H_ADDR, BMASK_RW_FORCE_PRINT);
+ gps_dl_bus_rd_opt(GPS_DL_GPS_BUS, GPS_AON_TOP_TCXO_MS_L_ADDR, BMASK_RW_FORCE_PRINT);
+ gps_dl_set_show_reg_rw_log(show_log);
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_power_ctrl.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_power_ctrl.c
new file mode 100644
index 0000000..49fe79f
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_power_ctrl.c
@@ -0,0 +1,702 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+#include "gps_dl_context.h"
+
+#include "gps_dl_hal.h"
+#if GPS_DL_MOCK_HAL
+#include "gps_mock_hal.h"
+#endif
+#if GPS_DL_HAS_CONNINFRA_DRV
+#if GPS_DL_ON_LINUX
+#include "conninfra.h"
+#elif GPS_DL_ON_CTP
+#include "conninfra_ext.h"
+#endif
+#endif
+
+#include "gps_dl_hw_api.h"
+#include "gps_dl_hw_dep_api.h"
+#include "gps_dl_hw_priv_util.h"
+#include "gps_dl_hal_util.h"
+#include "gps_dsp_fsm.h"
+#include "gps_dl_subsys_reset.h"
+
+#include "conn_infra/conn_infra_rgu.h"
+#include "conn_infra/conn_infra_cfg.h"
+#include "conn_infra/conn_host_csr_top.h"
+
+#include "gps/gps_rgu_on.h"
+#include "gps/gps_cfg_on.h"
+#include "gps/gps_aon_top.h"
+#include "gps/bgf_gps_cfg.h"
+
+static int gps_dl_hw_gps_sleep_prot_ctrl(int op)
+{
+ bool poll_okay;
+
+ if (1 == op) {
+ /* disable when on */
+ GDL_HW_SET_CONN2GPS_SLP_PROT_RX_VAL(0);
+ GDL_HW_POLL_CONN2GPS_SLP_PROT_RX_UNTIL_VAL(0, POLL_DEFAULT, &poll_okay);
+ if (!poll_okay) {
+ GDL_LOGE("_fail_disable_gps_slp_prot - conn2gps rx");
+ goto _fail_disable_gps_slp_prot;
+ }
+
+ GDL_HW_SET_CONN2GPS_SLP_PROT_TX_VAL(0);
+ GDL_HW_POLL_CONN2GPS_SLP_PROT_TX_UNTIL_VAL(0, POLL_DEFAULT, &poll_okay);
+ if (!poll_okay) {
+ GDL_LOGE("_fail_disable_gps_slp_prot - conn2gps tx");
+ goto _fail_disable_gps_slp_prot;
+ }
+
+ GDL_HW_SET_GPS2CONN_SLP_PROT_RX_VAL(0);
+ GDL_HW_POLL_GPS2CONN_SLP_PROT_RX_UNTIL_VAL(0, POLL_DEFAULT, &poll_okay);
+ if (!poll_okay) {
+ GDL_LOGE("_fail_disable_gps_slp_prot - gps2conn rx");
+ goto _fail_disable_gps_slp_prot;
+ }
+
+ GDL_HW_SET_GPS2CONN_SLP_PROT_TX_VAL(0);
+ GDL_HW_POLL_GPS2CONN_SLP_PROT_TX_UNTIL_VAL(0, POLL_DEFAULT, &poll_okay);
+ if (!poll_okay) {
+ GDL_LOGE("_fail_disable_gps_slp_prot - gps2conn tx");
+ goto _fail_disable_gps_slp_prot;
+ }
+ return 0;
+
+_fail_disable_gps_slp_prot:
+#if 0
+ GDL_HW_WR_CONN_INFRA_REG(CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_ADDR,
+ CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_RX_EN_MASK |
+ CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL_R_CONN2GPS_SLP_PROT_TX_EN_MASK |
+ CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_RX_EN_MASK |
+ CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL_R_GPS2CONN_SLP_PROT_TX_EN_MASK);
+#endif
+ return -1;
+ } else if (0 == op) {
+ /* enable when off */
+ GDL_HW_SET_CONN2GPS_SLP_PROT_TX_VAL(1);
+ GDL_HW_POLL_CONN2GPS_SLP_PROT_TX_UNTIL_VAL(1, POLL_DEFAULT, &poll_okay);
+ if (!poll_okay) {
+ /* From DE: need to trigger connsys reset */
+ GDL_LOGE("_fail_enable_gps_slp_prot - conn2gps tx");
+ goto _fail_enable_gps_slp_prot;
+ }
+
+ GDL_HW_SET_CONN2GPS_SLP_PROT_RX_VAL(1);
+ GDL_HW_POLL_CONN2GPS_SLP_PROT_RX_UNTIL_VAL(1, POLL_DEFAULT, &poll_okay);
+ if (!poll_okay) {
+ /* not handle it, just show warning */
+ GDL_LOGE("_fail_enable_gps_slp_prot - conn2gps rx");
+ }
+
+ GDL_HW_SET_GPS2CONN_SLP_PROT_TX_VAL(1);
+ GDL_HW_POLL_GPS2CONN_SLP_PROT_TX_UNTIL_VAL(1, POLL_DEFAULT, &poll_okay);
+ if (!poll_okay) {
+ /* not handle it, just show warning */
+ GDL_LOGE("_fail_enable_gps_slp_prot - gps2conn tx");
+ }
+
+ GDL_HW_SET_GPS2CONN_SLP_PROT_RX_VAL(1);
+ GDL_HW_POLL_GPS2CONN_SLP_PROT_RX_UNTIL_VAL(1, POLL_DEFAULT, &poll_okay);
+ if (!poll_okay) {
+ /* From DE: need to trigger connsys reset */
+ GDL_LOGE("_fail_enable_gps_slp_prot - gps2conn rx");
+ goto _fail_enable_gps_slp_prot;
+ }
+
+ return 0;
+
+_fail_enable_gps_slp_prot:
+ /* trigger reset on outer function */
+#if 0
+ gps_dl_trigger_connsys_reset();
+#endif
+ return -1;
+ }
+
+ return 0;
+}
+
+bool gps_dl_hw_gps_force_wakeup_conninfra_top_off(bool enable)
+{
+ bool poll_okay;
+
+ if (enable) {
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_GPS_CONN_INFRA_WAKEPU_GPS, 1);
+ GDL_HW_MAY_WAIT_CONN_INFRA_SLP_PROT_DISABLE_ACK(&poll_okay);
+ if (!poll_okay) {
+ GDL_LOGE("_fail_conn_slp_prot_not_okay");
+ return false; /* not okay */
+ }
+ } else
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_GPS_CONN_INFRA_WAKEPU_GPS, 0);
+
+ return true;
+}
+
+void gps_dl_hw_gps_sw_request_emi_usage(bool request)
+{
+ bool show_log;
+ bool reg_rw_log = gps_dl_log_reg_rw_is_on(GPS_DL_REG_RW_EMI_SW_REQ_CTRL);
+
+ if (reg_rw_log) {
+ show_log = gps_dl_set_show_reg_rw_log(true);
+ GDL_HW_RD_CONN_INFRA_REG(CONN_INFRA_CFG_EMI_CTL_TOP_ADDR);
+ GDL_HW_RD_CONN_INFRA_REG(CONN_INFRA_CFG_EMI_CTL_WF_ADDR);
+ GDL_HW_RD_CONN_INFRA_REG(CONN_INFRA_CFG_EMI_CTL_BT_ADDR);
+ GDL_HW_RD_CONN_INFRA_REG(CONN_INFRA_CFG_EMI_CTL_GPS_ADDR);
+ }
+#if (GPS_DL_USE_TIA)
+ /* If use TIA, CONN_INFRA_CFG_EMI_CTL_GPS used by DSP, driver use TOP's. */
+ if (request)
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_INFRA_CFG_EMI_CTL_TOP_EMI_REQ_TOP, 1);
+ else
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_INFRA_CFG_EMI_CTL_TOP_EMI_REQ_TOP, 0);
+#else
+ if (request)
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_INFRA_CFG_EMI_CTL_GPS_EMI_REQ_GPS, 1);
+ else
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_INFRA_CFG_EMI_CTL_GPS_EMI_REQ_GPS, 0);
+#endif
+ if (reg_rw_log)
+ gps_dl_set_show_reg_rw_log(show_log);
+}
+
+int gps_dl_hw_gps_common_on(void)
+{
+ bool poll_okay;
+ unsigned int poll_ver;
+ int i;
+
+ /* Enable Conninfra BGF */
+ GDL_HW_SET_CONN_INFRA_BGF_EN(1);
+
+ /* Poll conninfra hw version */
+ GDL_HW_CHECK_CONN_INFRA_VER(&poll_okay, &poll_ver);
+ if (!poll_okay) {
+ GDL_LOGE("_fail_conn_hw_ver_not_okay, poll_ver = 0x%08x", poll_ver);
+ goto _fail_conn_hw_ver_not_okay;
+ }
+
+ /* GDL_HW_CHECK_CONN_INFRA_VER may check a list and return ok if poll_ver is in the list,
+ * record the poll_ver here and we can know which one it is,
+ * and it may help for debug purpose.
+ */
+ gps_dl_hw_gps_set_conn_infra_ver(poll_ver);
+ GDL_LOGW("%s: poll_ver = 0x%08x is ok", GDL_HW_SUPPORT_LIST, poll_ver);
+
+ /* GPS SW EMI request
+ * gps_dl_hw_gps_sw_request_emi_usage(true);
+ */
+ gps_dl_hal_emi_usage_init();
+
+ /* Enable GPS function */
+ GDL_HW_SET_GPS_FUNC_EN(1);
+
+ /* bit24: BGFSYS_ON_TOP primary power ack */
+ GDL_HW_POLL_CONN_INFRA_ENTRY(CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_BGFSYS_ON_TOP_PWR_ACK, 1,
+ POLL_DEFAULT, &poll_okay);
+ if (!poll_okay) {
+ GDL_LOGE("_fail_bgf_top_1st_pwr_ack_not_okay");
+ goto _fail_bgf_top_1st_pwr_ack_not_okay;
+ }
+
+ /* bit25: BGFSYS_ON_TOP secondary power ack */
+ GDL_HW_POLL_CONN_INFRA_ENTRY(CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_AN_BGFSYS_ON_TOP_PWR_ACK_S, 1,
+ POLL_DEFAULT, &poll_okay);
+ if (!poll_okay) {
+ GDL_LOGE("_fail_bgf_top_2nd_pwr_ack_not_okay");
+ goto _fail_bgf_top_2nd_pwr_ack_not_okay;
+ }
+
+ GDL_WAIT_US(200);
+
+ /* sleep prot */
+ if (gps_dl_hw_gps_sleep_prot_ctrl(1) != 0) {
+ GDL_LOGE("_fail_disable_gps_slp_prot_not_okay");
+ goto _fail_disable_gps_slp_prot_not_okay;
+ }
+
+ /* polling status and version */
+ /* Todo: set GPS host csr flag selection */
+ /* 0x18060240[3:0] == 4h'2 gps_top_off is GPS_ACTIVE state */
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_HOST2GPS_DEGUG_SEL, 0x80);
+ for (i = 0; i < 3; i++) {
+ GDL_HW_POLL_CONN_INFRA_ENTRY(CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_GPS_CFG2HOST_DEBUG, 2,
+ POLL_DEFAULT, &poll_okay);
+ if (poll_okay)
+ break;
+ /*
+ * TODO:
+ * if (!gps_dl_reset_level_is_none()) break;
+ */
+ if (i > 0)
+ GDL_LOGW("_poll_gps_top_off_active, cnt = %d", i + 1);
+ }
+ if (!poll_okay) {
+ GDL_LOGE("_fail_gps_top_off_active_not_okay");
+ goto _fail_gps_top_off_active_not_okay;
+ }
+
+ /* 0x18c21010[31:0] bgf ip version */
+ GDL_HW_POLL_GPS_ENTRY(BGF_GPS_CFG_BGF_IP_VERSION_BGFSYS_VERSION,
+ GDL_HW_BGF_VER, POLL_DEFAULT, &poll_okay);
+ if (!poll_okay) {
+ GDL_LOGE("_fail_bgf_ip_ver_not_okay");
+ goto _fail_bgf_ip_ver_not_okay;
+ }
+
+ /* 0x18c21014[7:0] bgf ip cfg */
+ GDL_HW_POLL_GPS_ENTRY(BGF_GPS_CFG_BGF_IP_CONFIG_BGFSYS_CONFIG, 0,
+ POLL_DEFAULT, &poll_okay);
+ if (!poll_okay) {
+ GDL_LOGE("_fail_bgf_ip_cfg_not_okay");
+ goto _fail_bgf_ip_cfg_not_okay;
+ }
+
+#if (GPS_DL_HAS_CONNINFRA_DRV)
+ /* conninfra driver add an API to do bellow step */
+ conninfra_config_setup();
+#else
+ /* Enable conninfra bus hung detection */
+ GDL_HW_WR_CONN_INFRA_REG(0x1800F000, 0xF000001C);
+#endif
+
+ /* host csr gps bus debug mode enable 0x18c60000 = 0x10 */
+ GDL_HW_WR_GPS_REG(0x80060000, 0x10);
+
+ /* Power on A-die top clock */
+ GDL_HW_ADIE_TOP_CLK_EN(1, &poll_okay);
+ if (!poll_okay) {
+ GDL_LOGE("_fail_adie_top_clk_en_not_okay");
+ goto _fail_adie_top_clk_en_not_okay;
+ }
+
+ /* Enable PLL driver */
+ GDL_HW_SET_GPS_ENTRY(GPS_CFG_ON_GPS_CLKGEN1_CTL_CR_GPS_DIGCK_DIV_EN, 1);
+
+ return 0;
+
+_fail_adie_top_clk_en_not_okay:
+_fail_bgf_ip_cfg_not_okay:
+_fail_bgf_ip_ver_not_okay:
+_fail_gps_top_off_active_not_okay:
+_fail_disable_gps_slp_prot_not_okay:
+_fail_bgf_top_2nd_pwr_ack_not_okay:
+_fail_bgf_top_1st_pwr_ack_not_okay:
+ GDL_HW_SET_GPS_FUNC_EN(0);
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_INFRA_CFG_EMI_CTL_GPS_EMI_REQ_GPS, 0);
+
+_fail_conn_hw_ver_not_okay:
+ return -1;
+}
+
+int gps_dl_hw_gps_common_off(void)
+{
+ bool poll_okay;
+
+ /* Power off A-die top clock */
+ GDL_HW_ADIE_TOP_CLK_EN(0, &poll_okay);
+ if (!poll_okay) {
+ /* Just show log */
+ GDL_LOGE("_fail_adie_top_clk_dis_not_okay");
+ }
+
+ if (gps_dl_hw_gps_sleep_prot_ctrl(0) != 0) {
+ GDL_LOGE("enable sleep prot fail, trigger connsys reset");
+ gps_dl_trigger_connsys_reset();
+ return -1;
+ }
+
+ /* GPS SW EMI request
+ * gps_dl_hw_gps_sw_request_emi_usage(false);
+ */
+ gps_dl_hal_emi_usage_deinit();
+
+ if (gps_dl_log_reg_rw_is_on(GPS_DL_REG_RW_HOST_CSR_GPS_OFF))
+ gps_dl_hw_dump_host_csr_conninfra_info(true);
+
+ /* Disable GPS function */
+ GDL_HW_SET_GPS_FUNC_EN(0);
+
+ /* Disable Conninfra BGF */
+ GDL_HW_SET_CONN_INFRA_BGF_EN(0);
+
+ return 0;
+}
+
+/* L1 and L5 share same pwr stat and current we can support the bellow case:
+ * 1. Both L1 and L5 on / off
+ * 2. Both L1 and L5 enter deep stop mode and wakeup
+ * 3. L5 stays off, L1 do on / off
+ * 4. L5 stays off, L1 enter deep stop mode and wakeup
+ */
+unsigned int g_gps_pwr_stat;
+int gps_dl_hw_gps_pwr_stat_ctrl(enum dsp_ctrl_enum ctrl)
+{
+ bool clk_ext = gps_dl_hal_get_need_clk_ext_flag(GPS_DATA_LINK_ID0);
+
+ switch (ctrl) {
+ case GPS_L1_DSP_ON:
+ case GPS_L5_DSP_ON:
+ case GPS_L1_DSP_OFF:
+ case GPS_L5_DSP_OFF:
+ GDL_HW_SET_GPS_ENTRY(GPS_AON_TOP_DSLEEP_CTL_GPS_PWR_STAT, 0);
+ GDL_HW_SET_GPS_ENTRY(GPS_AON_TOP_DSLEEP_CTL_FORCE_OSC_EN_ON, 0);
+ g_gps_pwr_stat = 0;
+ break;
+
+ case GPS_L1_DSP_CLEAR_PWR_STAT:
+ case GPS_L5_DSP_CLEAR_PWR_STAT:
+ gps_dl_hw_print_ms_counter_status();
+ GDL_HW_SET_GPS_ENTRY(GPS_AON_TOP_DSLEEP_CTL_GPS_PWR_STAT, 0);
+ GDL_HW_SET_GPS_ENTRY(GPS_AON_TOP_DSLEEP_CTL_FORCE_OSC_EN_ON, 0);
+ g_gps_pwr_stat = 0;
+ break;
+
+ case GPS_L1_DSP_ENTER_DSTOP:
+ case GPS_L5_DSP_ENTER_DSTOP:
+ GDL_HW_SET_GPS_ENTRY(GPS_AON_TOP_DSLEEP_CTL_GPS_PWR_STAT, 1);
+ GDL_HW_SET_GPS_ENTRY(GPS_AON_TOP_DSLEEP_CTL_FORCE_OSC_EN_ON, clk_ext);
+ gps_dl_hw_print_ms_counter_status();
+ g_gps_pwr_stat = 1;
+ break;
+
+ case GPS_L1_DSP_EXIT_DSTOP:
+ case GPS_L5_DSP_EXIT_DSTOP:
+ /* do nothing */
+ gps_dl_hw_print_ms_counter_status();
+ break;
+
+ case GPS_L1_DSP_ENTER_DSLEEP:
+ case GPS_L5_DSP_ENTER_DSLEEP:
+ GDL_HW_SET_GPS_ENTRY(GPS_AON_TOP_DSLEEP_CTL_GPS_PWR_STAT, 3);
+ GDL_HW_SET_GPS_ENTRY(GPS_AON_TOP_DSLEEP_CTL_FORCE_OSC_EN_ON, clk_ext);
+ g_gps_pwr_stat = 3;
+ break;
+
+ case GPS_L1_DSP_EXIT_DSLEEP:
+ case GPS_L5_DSP_EXIT_DSLEEP:
+ /* do nothong */
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int gps_dl_hw_gps_dsp_ctrl(enum dsp_ctrl_enum ctrl)
+{
+ bool poll_okay;
+ bool dsp_off_done;
+
+ switch (ctrl) {
+ case GPS_L1_DSP_ON:
+ case GPS_L1_DSP_EXIT_DSTOP:
+ case GPS_L1_DSP_EXIT_DSLEEP:
+ gps_dl_hw_gps_pwr_stat_ctrl(ctrl);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_ON, 1);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_SOFT_RST_B, 1);
+ GDL_HW_POLL_GPS_ENTRY(GPS_CFG_ON_GPS_L1_SLP_PWR_CTL_GPS_L1_SLP_PWR_CTL_CS, 3,
+ POLL_DEFAULT, &poll_okay);
+ if (!poll_okay) {
+ GDL_LOGE("ctrl = %d fail", ctrl);
+ return -1;
+ }
+
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_MEM_DLY_CTL_RGU_GPSSYS_L1_MEM_ADJ_DLY_EN, 1);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DLY_CHAIN_CTL_RGU_GPS_L1_MEM_PDN_DELAY_DUMMY_NUM, 5);
+ gps_dl_wait_us(100); /* 3 x 32k clk ~= 100us */
+ gps_dl_hw_usrt_ctrl(GPS_DATA_LINK_ID0,
+ true, gps_dl_is_dma_enabled(), gps_dl_is_1byte_mode());
+ break;
+
+ case GPS_L1_DSP_CLEAR_PWR_STAT:
+ gps_dl_hw_gps_pwr_stat_ctrl(ctrl);
+ return 0;
+
+ case GPS_L1_DSP_OFF:
+ case GPS_L1_DSP_ENTER_DSTOP:
+ case GPS_L1_DSP_ENTER_DSLEEP:
+ gps_dl_hw_usrt_ctrl(GPS_DATA_LINK_ID0,
+ false, gps_dl_is_dma_enabled(), gps_dl_is_1byte_mode());
+
+ /* poll */
+ dsp_off_done = gps_dl_hw_gps_dsp_is_off_done(GPS_DATA_LINK_ID0);
+
+ gps_dl_hw_gps_pwr_stat_ctrl(ctrl);
+ if (ctrl == GPS_L1_DSP_ENTER_DSLEEP) {
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPPRAM_PDN_EN_RGU_GPS_L1_PRAM_HWCTL_PDN, 0);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPPRAM_SLP_EN_RGU_GPS_L1_PRAM_HWCTL_SLP, 0x1FF);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPXRAM_PDN_EN_RGU_GPS_L1_XRAM_HWCTL_PDN, 0);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPXRAM_SLP_EN_RGU_GPS_L1_XRAM_HWCTL_SLP, 0xF);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPYRAM_PDN_EN_RGU_GPS_L1_YRAM_HWCTL_PDN, 0);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPYRAM_SLP_EN_RGU_GPS_L1_YRAM_HWCTL_SLP, 0x1FF);
+ } else if (ctrl == GPS_L1_DSP_ENTER_DSTOP) {
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPPRAM_PDN_EN_RGU_GPS_L1_PRAM_HWCTL_PDN, 0);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPPRAM_SLP_EN_RGU_GPS_L1_PRAM_HWCTL_SLP, 0x1FF);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPXRAM_PDN_EN_RGU_GPS_L1_XRAM_HWCTL_PDN, 0);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPXRAM_SLP_EN_RGU_GPS_L1_XRAM_HWCTL_SLP, 0xF);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPYRAM_PDN_EN_RGU_GPS_L1_YRAM_HWCTL_PDN, 0x1FF);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPYRAM_SLP_EN_RGU_GPS_L1_YRAM_HWCTL_SLP, 0);
+ } else {
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPPRAM_PDN_EN_RGU_GPS_L1_PRAM_HWCTL_PDN, 0x1FF);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPPRAM_SLP_EN_RGU_GPS_L1_PRAM_HWCTL_SLP, 0);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPXRAM_PDN_EN_RGU_GPS_L1_XRAM_HWCTL_PDN, 0xF);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPXRAM_SLP_EN_RGU_GPS_L1_XRAM_HWCTL_SLP, 0);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPYRAM_PDN_EN_RGU_GPS_L1_YRAM_HWCTL_PDN, 0x1FF);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_DSPYRAM_SLP_EN_RGU_GPS_L1_YRAM_HWCTL_SLP, 0);
+ }
+
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_SOFT_RST_B, 0);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_ON, 0);
+
+ if (dsp_off_done)
+ return 0;
+ else
+ return -1;
+
+ case GPS_L5_DSP_ON:
+ case GPS_L5_DSP_EXIT_DSTOP:
+ case GPS_L5_DSP_EXIT_DSLEEP:
+ gps_dl_hw_gps_pwr_stat_ctrl(ctrl);
+
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_ON, 1);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_SOFT_RST_B, 1);
+ GDL_HW_POLL_GPS_ENTRY(GPS_CFG_ON_GPS_L5_SLP_PWR_CTL_GPS_L5_SLP_PWR_CTL_CS, 3,
+ POLL_DEFAULT, &poll_okay);
+ if (!poll_okay) {
+ GDL_LOGE("ctrl = %d fail", ctrl);
+ return -1;
+ }
+
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_MEM_DLY_CTL_RGU_GPSSYS_L5_MEM_ADJ_DLY_EN, 1);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DLY_CHAIN_CTL_RGU_GPS_L5_MEM_PDN_DELAY_DUMMY_NUM, 9);
+ gps_dl_wait_us(100); /* 3 x 32k clk ~= 1ms */
+ gps_dl_hw_usrt_ctrl(GPS_DATA_LINK_ID1,
+ true, gps_dl_is_dma_enabled(), gps_dl_is_1byte_mode());
+ break;
+
+ case GPS_L5_DSP_CLEAR_PWR_STAT:
+ gps_dl_hw_gps_pwr_stat_ctrl(ctrl);
+ return 0;
+
+ case GPS_L5_DSP_OFF:
+ case GPS_L5_DSP_ENTER_DSTOP:
+ case GPS_L5_DSP_ENTER_DSLEEP:
+ gps_dl_hw_usrt_ctrl(GPS_DATA_LINK_ID1,
+ false, gps_dl_is_dma_enabled(), gps_dl_is_1byte_mode());
+
+ /* poll */
+ dsp_off_done = gps_dl_hw_gps_dsp_is_off_done(GPS_DATA_LINK_ID1);
+
+ gps_dl_hw_gps_pwr_stat_ctrl(ctrl);
+ if (ctrl == GPS_L5_DSP_ENTER_DSLEEP) {
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPPRAM_PDN_EN_RGU_GPS_L5_PRAM_HWCTL_PDN, 0);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPPRAM_SLP_EN_RGU_GPS_L5_PRAM_HWCTL_SLP, 0x3FF);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPXRAM_PDN_EN_RGU_GPS_L5_XRAM_HWCTL_PDN, 0);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPXRAM_SLP_EN_RGU_GPS_L5_XRAM_HWCTL_SLP, 0xF);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPYRAM_PDN_EN_RGU_GPS_L5_YRAM_HWCTL_PDN, 0);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPYRAM_SLP_EN_RGU_GPS_L5_YRAM_HWCTL_SLP, 0x3FF);
+ } else if (ctrl == GPS_L5_DSP_ENTER_DSTOP) {
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPPRAM_PDN_EN_RGU_GPS_L5_PRAM_HWCTL_PDN, 0);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPPRAM_SLP_EN_RGU_GPS_L5_PRAM_HWCTL_SLP, 0x3FF);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPXRAM_PDN_EN_RGU_GPS_L5_XRAM_HWCTL_PDN, 0);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPXRAM_SLP_EN_RGU_GPS_L5_XRAM_HWCTL_SLP, 0xF);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPYRAM_PDN_EN_RGU_GPS_L5_YRAM_HWCTL_PDN, 0x3FF);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPYRAM_SLP_EN_RGU_GPS_L5_YRAM_HWCTL_SLP, 0);
+ } else {
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPPRAM_PDN_EN_RGU_GPS_L5_PRAM_HWCTL_PDN, 0x3FF);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPPRAM_SLP_EN_RGU_GPS_L5_PRAM_HWCTL_SLP, 0);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPXRAM_PDN_EN_RGU_GPS_L5_XRAM_HWCTL_PDN, 0xF);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPXRAM_SLP_EN_RGU_GPS_L5_XRAM_HWCTL_SLP, 0);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPYRAM_PDN_EN_RGU_GPS_L5_YRAM_HWCTL_PDN, 0x3FF);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_DSPYRAM_SLP_EN_RGU_GPS_L5_YRAM_HWCTL_SLP, 0);
+ }
+
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_SOFT_RST_B, 0);
+ GDL_HW_SET_GPS_ENTRY(GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_ON, 0);
+
+ if (dsp_off_done)
+ return 0;
+ else
+ return -1;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+bool gps_dl_hw_gps_dsp_is_off_done(enum gps_dl_link_id_enum link_id)
+{
+ int i;
+ bool done;
+ bool show_log;
+
+ /* TODO: move it to proper place */
+ if (GPS_DSP_ST_HW_STOP_MODE == gps_dsp_state_get(link_id)) {
+ /* expect it change to RESET_DONE after this call */
+ if (!gps_dl_hal_mcub_flag_handler(link_id)) {
+ GDL_LOGXW(link_id, "pre-check fail");
+ return false;
+ }
+ }
+
+ if (GPS_DSP_ST_RESET_DONE == gps_dsp_state_get(link_id)) {
+ GDL_LOGXD(link_id, "1st return, done = 1");
+ return true;
+ }
+
+ i = 0;
+
+ show_log = gps_dl_set_show_reg_rw_log(true);
+ do {
+ /* MCUB IRQ already mask at this time */
+ if (!gps_dl_hal_mcub_flag_handler(link_id)) {
+ done = false;
+ break;
+ }
+
+ done = true;
+ while (GPS_DSP_ST_RESET_DONE != gps_dsp_state_get(link_id)) {
+ /* poll 10ms */
+ if (i > 10) {
+ done = false;
+ break;
+ }
+ gps_dl_wait_us(1000);
+
+ /* read dummy cr confirm dsp state for debug */
+ if (GPS_DATA_LINK_ID0 == link_id)
+ GDL_HW_RD_GPS_REG(0x80073160);
+ else if (GPS_DATA_LINK_ID1 == link_id)
+ GDL_HW_RD_GPS_REG(0x80073134);
+
+ if (!gps_dl_hal_mcub_flag_handler(link_id)) {
+ done = false;
+ break;
+ }
+ i++;
+ }
+ } while (0);
+ gps_dl_set_show_reg_rw_log(show_log);
+ GDL_LOGXW(link_id, "2nd return, done = %d, i = %d", done, i);
+ return done;
+}
+
+void gps_dl_hw_gps_adie_force_off(void)
+{
+#if GPS_DL_HAS_CONNINFRA_DRV
+ unsigned int spi_data;
+ int rd_status;
+ int wr_status;
+
+ /* TOP: 0xFC[1:0] = 2'b11 */
+ spi_data = 0;
+ rd_status = conninfra_spi_read(SYS_SPI_TOP, 0xFC, &spi_data);
+ ASSERT_ZERO(rd_status, GDL_VOIDF());
+ GDL_LOGW("spi_data = 0x%x", spi_data);
+ wr_status = conninfra_spi_write(SYS_SPI_TOP, 0xFC, spi_data | 3UL);
+ ASSERT_ZERO(wr_status, GDL_VOIDF());
+
+ /* TOP: 0xA0C[31:0] = 0xFFFFFFFF; 0xAFC[31:0] = 0xFFFFFFFF */
+ wr_status = conninfra_spi_write(SYS_SPI_TOP, 0xA0C, 0xFFFFFFFF);
+ ASSERT_ZERO(wr_status, GDL_VOIDF());
+ wr_status = conninfra_spi_write(SYS_SPI_TOP, 0xAFC, 0xFFFFFFFF);
+ ASSERT_ZERO(wr_status, GDL_VOIDF());
+
+ /* TOP: 0xF8[0] = 1'b0 */
+ spi_data = 0;
+ rd_status = conninfra_spi_read(SYS_SPI_TOP, 0xF8, &spi_data);
+ ASSERT_ZERO(rd_status, GDL_VOIDF());
+ GDL_LOGW("spi_data = 0x%x", spi_data);
+ wr_status = conninfra_spi_write(SYS_SPI_TOP, 0xF8, spi_data & (~1UL));
+ ASSERT_ZERO(wr_status, GDL_VOIDF());
+
+ /* GPS: 0x0[15] = 1'b1 */
+ spi_data = 0;
+ rd_status = conninfra_spi_read(SYS_SPI_GPS, 0x0, &spi_data);
+ ASSERT_ZERO(rd_status, GDL_VOIDF());
+ GDL_LOGW("spi_data = 0x%x", spi_data);
+ wr_status = conninfra_spi_write(SYS_SPI_GPS, 0x0, spi_data & (1UL << 15));
+ ASSERT_ZERO(wr_status, GDL_VOIDF());
+
+ /* TOP: 0xF8[0] = 1'b1 */
+ spi_data = 0;
+ rd_status = conninfra_spi_read(SYS_SPI_TOP, 0xF8, &spi_data);
+ ASSERT_ZERO(rd_status, GDL_VOIDF());
+ GDL_LOGW("spi_data = 0x%x", spi_data);
+ wr_status = conninfra_spi_write(SYS_SPI_TOP, 0xF8, spi_data | 1UL);
+ ASSERT_ZERO(wr_status, GDL_VOIDF());
+
+ /* GPS: 0x0[15] = 1'b1 */
+ spi_data = 0;
+ rd_status = conninfra_spi_read(SYS_SPI_GPS, 0x0, &spi_data);
+ ASSERT_ZERO(rd_status, GDL_VOIDF());
+ GDL_LOGW("spi_data = 0x%x", spi_data);
+ wr_status = conninfra_spi_write(SYS_SPI_GPS, 0x0, spi_data & (1UL << 15));
+ ASSERT_ZERO(wr_status, GDL_VOIDF());
+
+ /* TOP: 0xF8[0] = 1'b0 */
+ spi_data = 0;
+ rd_status = conninfra_spi_read(SYS_SPI_TOP, 0xF8, &spi_data);
+ ASSERT_ZERO(rd_status, GDL_VOIDF());
+ GDL_LOGW("spi_data = 0x%x", spi_data);
+ wr_status = conninfra_spi_write(SYS_SPI_TOP, 0xF8, spi_data & (~1UL));
+ ASSERT_ZERO(wr_status, GDL_VOIDF());
+
+ /* TOP: 0xA0C[31:0] = 0; 0xAFC[31:0] = 0 */
+ wr_status = conninfra_spi_write(SYS_SPI_TOP, 0xA0C, 0);
+ ASSERT_ZERO(wr_status, GDL_VOIDF());
+ wr_status = conninfra_spi_write(SYS_SPI_TOP, 0xAFC, 0);
+ ASSERT_ZERO(wr_status, GDL_VOIDF());
+
+ /* TOP: 0xFC[1:0] = 2'b00 */
+ rd_status = conninfra_spi_read(SYS_SPI_TOP, 0xFC, &spi_data);
+ ASSERT_ZERO(rd_status, GDL_VOIDF());
+ GDL_LOGW("spi_data = 0x%x", spi_data);
+ wr_status = conninfra_spi_write(SYS_SPI_TOP, 0xFC, spi_data & (~3UL));
+ ASSERT_ZERO(wr_status, GDL_VOIDF());
+#else
+ GDL_LOGE("no conninfra driver");
+#endif
+}
+
+void gps_dl_hw_gps_dump_top_rf_cr(void)
+{
+#if GPS_DL_HAS_CONNINFRA_DRV
+ unsigned int spi_data;
+ int rd_status;
+ int i;
+ const int rd_addr_list[] = {0x03C, 0xA18, 0xA1C, 0x0C8, 0xA00, 0x0B4, 0x34C};
+ int rd_addr;
+
+ for (i = 0; i < ARRAY_SIZE(rd_addr_list); i++) {
+ rd_addr = rd_addr_list[i];
+ spi_data = 0;
+ rd_status = conninfra_spi_read(SYS_SPI_TOP, rd_addr, &spi_data);
+ GDL_LOGW("rd: addr = 0x%x, val = 0x%x, rd_status = %d",
+ rd_addr, spi_data, rd_status);
+ }
+#else
+ GDL_LOGE("no conninfra driver");
+#endif
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_priv_util.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_priv_util.h
new file mode 100644
index 0000000..46c9276
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_priv_util.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_HW_UTIL_H
+#define _GPS_DL_HW_UTIL_H
+
+#include "gps_dl_config.h"
+#include "gps_dl_hw_type.h"
+#include "gps_dl_time_tick.h"
+
+enum GPS_DL_BUS_ENUM {
+ GPS_DL_GPS_BUS,
+ GPS_DL_BGF_BUS,
+ GPS_DL_CONN_INFRA_BUS,
+ GPS_DL_BUS_NUM
+};
+
+enum gps_dl_bus_rw_opt_enum {
+ WR_NO_READ_BACK,
+ RW_DO_CHECK,
+ RW_FORCE_PRINT,
+ RW_FULL_PRINT,
+ RW_OPT_MAX = 32
+};
+#define BMASK_WR_NO_READ_BACK (1UL << WR_NO_READ_BACK)
+#define BMASK_RW_DO_CHECK (1UL << RW_DO_CHECK)
+#define BMASK_RW_FORCE_PRINT (1UL << RW_FORCE_PRINT)
+#define BMASK_RW_FULL_PRINT (1UL << RW_FULL_PRINT)
+
+void gps_dl_bus_wr_opt(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr, unsigned int val,
+ unsigned int opt_bitmask);
+unsigned int gps_dl_bus_rd_opt(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr,
+ unsigned int opt_bitmask);
+
+
+/* the function will convert bus addr to host-view addr by remaping */
+#if 0
+void gps_dl_bus_wr32(u32 bus_addr, u32 val);
+u32 gps_dl_bus_rd32(u32 bus_addr);
+#endif
+void gps_dl_bus_write(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr, unsigned int val);
+void gps_dl_bus_write_no_rb(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr, unsigned int val);
+unsigned int gps_dl_bus_read(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr);
+void gps_dl_bus_check_and_print(unsigned int host_addr);
+
+
+/* provide function/macro declaration for c files under hal folder */
+
+/* todo: writel, mb */
+#define ADDR(Field) (Field##_ADDR)
+#define MASK(Field) (Field##_MASK)
+#define SHFT(Field) (Field##_SHFT)
+
+/* TODO: using volatile in kernel is almost an error */
+#if 0
+#define DL_SET_ENTRY(Field, Value) \
+ { conn_reg * addr = ADDR(Field); \
+ *addr = ((((conn_reg)(Value) << SHFT(Field)) \
+ & MASK(Field)) | (*addr & ~MASK(Field))) ; }
+
+#define DL_GET_ENTRY(Field) \
+ ((*ADDR(Field) & (MASK(Field))) >> SHFT(Field))
+#endif
+
+/* todo
+ * 1. iomap the region to access or just writel can work?
+ * 2. using volatile in kernel is almost an error. Replace it with accessor functions
+ */
+#if GPS_DL_ON_CTP
+#define GPS_DL_HOST_REG_WR(host_addr, val) ((*(conn_reg *)host_addr) = (val))
+#define GPS_DL_HOST_REG_RD(host_addr) (*(conn_reg *)host_addr)
+#else
+#define GPS_DL_HOST_REG_WR(host_addr, val) do {} while (0)
+#define GPS_DL_HOST_REG_RD(host_addr) (0)
+#endif
+
+#define GDL_HW_WR_CONN_INFRA_REG(Addr, Value) gps_dl_bus_write(GPS_DL_CONN_INFRA_BUS, Addr, Value)
+#define GDL_HW_RD_CONN_INFRA_REG(Addr) gps_dl_bus_read(GPS_DL_CONN_INFRA_BUS, Addr)
+
+#define GDL_HW_WR_BGF_REG(Addr, Value) gps_dl_bus_write(GPS_DL_BGF_BUS, Addr, Value)
+#define GDL_HW_RD_BGF_REG(Addr) gps_dl_bus_read(GPS_DL_BGF_BUS, Addr)
+
+#define GDL_HW_WR_GPS_REG(Addr, Value) gps_dl_bus_write(GPS_DL_GPS_BUS, Addr, Value)
+#define GDL_HW_RD_GPS_REG(Addr) gps_dl_bus_read(GPS_DL_GPS_BUS, Addr)
+
+
+#define GDL_HW_SET_ENTRY(Bus_ID, Field, Value) do { \
+ conn_reg val; \
+ val = gps_dl_bus_read(Bus_ID, ADDR(Field)); \
+ val &= (~MASK(Field)); \
+ val |= ((Value << SHFT(Field)) & MASK(Field)); \
+ gps_dl_bus_write(Bus_ID, ADDR(Field), val); \
+ } while (0)
+
+#define GDL_HW_GET_ENTRY(Bus_ID, Field) \
+ ((gps_dl_bus_read(Bus_ID, ADDR(Field)) & (MASK(Field))) >> SHFT(Field))
+
+#define GDL_HW_EXTRACT_ENTRY(Field, Val) \
+ ((Val & (MASK(Field))) >> SHFT(Field))
+
+#define POLL_INTERVAL_US (100)
+#define POLL_US (1)
+#define POLL_1_TIME (0)
+#define POLL_FOREVER (-1)
+#define POLL_DEFAULT (1000 * POLL_US)
+#if (GPS_DL_ON_CTP || GPS_DL_ON_LINUX)
+#define GDL_HW_POLL_ENTRY_VERBOSE(Bus_ID, Field, pIsOkay, pLastValue, TimeoutUsec, condExpected) \
+ do { \
+ if (pIsOkay != NULL) { \
+ *pIsOkay = false; \
+ } \
+ if (POLL_1_TIME == TimeoutUsec) { \
+ if (pLastValue != NULL) { \
+ *pLastValue = GDL_HW_GET_ENTRY(Bus_ID, Field); \
+ } \
+ if ((condExpected)) { \
+ if (pIsOkay != NULL) { \
+ *pIsOkay = true; \
+ } \
+ } \
+ } else if (TimeoutUsec > 0) { \
+ unsigned int poll_wait_cnt = 0; \
+ while (true) { \
+ if (pLastValue != NULL) { \
+ *pLastValue = GDL_HW_GET_ENTRY(Bus_ID, Field); \
+ } \
+ if ((condExpected)) { \
+ if (pIsOkay != NULL) { \
+ *pIsOkay = true; \
+ } \
+ break; \
+ } \
+ if (poll_wait_cnt >= TimeoutUsec) { \
+ break; \
+ } \
+ gps_dl_wait_us(POLL_INTERVAL_US); \
+ poll_wait_cnt += POLL_INTERVAL_US; \
+ } \
+ } else if (TimeoutUsec <= POLL_FOREVER) { \
+ while (true) { \
+ if (pLastValue != NULL) { \
+ *pLastValue = GDL_HW_GET_ENTRY(Bus_ID, Field); \
+ } \
+ if ((condExpected)) { \
+ if (pIsOkay != NULL) { \
+ *pIsOkay = true; \
+ } \
+ break; \
+ } \
+ gps_dl_wait_us(POLL_INTERVAL_US); \
+ } \
+ } \
+ } while (0)
+
+#define GDL_HW_POLL_ENTRY(Bus_ID, Field, ValueExpected, TimeoutUsec, pIsOkay) \
+ do { \
+ unsigned int gdl_hw_poll_value; \
+ GDL_HW_POLL_ENTRY_VERBOSE(Bus_ID, Field, \
+ pIsOkay, &gdl_hw_poll_value, \
+ TimeoutUsec, (gdl_hw_poll_value == ValueExpected)); \
+ } while (0)
+#else
+#define GDL_HW_POLL_ENTRY(Bus_ID, Field, ValueExpected, TimeoutUsec, pIsOkay) \
+ do { \
+ if (ValueExpected == GDL_HW_GET_ENTRY(Bus_ID, Field)) { \
+ ; \
+ } \
+ } while (0)
+#endif
+
+
+
+#define GDL_HW_SET_CONN_INFRA_ENTRY(Field, Value) GDL_HW_SET_ENTRY(GPS_DL_CONN_INFRA_BUS, Field, Value)
+#define GDL_HW_GET_CONN_INFRA_ENTRY(Field) GDL_HW_GET_ENTRY(GPS_DL_CONN_INFRA_BUS, Field)
+#define GDL_HW_POLL_CONN_INFRA_ENTRY(Field, ValueExpected, TimeoutUsec, pIsOkay) \
+ GDL_HW_POLL_ENTRY(GPS_DL_CONN_INFRA_BUS, Field, ValueExpected, TimeoutUsec, pIsOkay)
+
+#define GDL_HW_SET_BGF_ENTRY(Field, Value) GDL_HW_SET_ENTRY(GPS_DL_BGF_BUS, Field, Value)
+#define GDL_HW_GET_BGF_ENTRY(Field) GDL_HW_GET_ENTRY(GPS_DL_BGF_BUS, Field)
+#define GDL_HW_POLL_BGF_ENTRY(Field, ValueExpected, TimeoutUsec, pIsOkay) \
+ GDL_HW_POLL_ENTRY(GPS_DL_BGF_BUS, Field, ValueExpected, TimeoutUsec, pIsOkay)
+
+#define GDL_HW_SET_GPS_ENTRY(Field, Value) GDL_HW_SET_ENTRY(GPS_DL_GPS_BUS, Field, Value)
+#define GDL_HW_SET_GPS_ENTRY2(LinkID, Value, Field1, Field2) do { \
+ if (GPS_DATA_LINK_ID0 == LinkID) \
+ GDL_HW_SET_GPS_ENTRY(Field1, Value); \
+ else if (GPS_DATA_LINK_ID1 == LinkID) \
+ GDL_HW_SET_GPS_ENTRY(Field2, Value); \
+ } while (0)
+
+#define GDL_HW_GET_GPS_ENTRY(Field) GDL_HW_GET_ENTRY(GPS_DL_GPS_BUS, Field)
+#define GDL_HW_GET_GPS_ENTRY2(LinkID, Field1, Field2) ( \
+ (GPS_DATA_LINK_ID0 == LinkID) ? \
+ GDL_HW_GET_GPS_ENTRY(Field1) : \
+ ((GPS_DATA_LINK_ID1 == LinkID) ? \
+ GDL_HW_GET_GPS_ENTRY(Field2) : 0) \
+ )
+
+#define GDL_HW_POLL_GPS_ENTRY(Field, ValueExpected, TimeoutUsec, pIsOkay) \
+ GDL_HW_POLL_ENTRY(GPS_DL_GPS_BUS, Field, ValueExpected, TimeoutUsec, pIsOkay)
+
+struct gps_dl_addr_map_entry {
+ unsigned int host_addr;
+ unsigned int bus_addr;
+ unsigned int length;
+};
+
+unsigned int bgf_bus_to_host(unsigned int bgf_addr);
+unsigned int gps_bus_to_host(unsigned int gps_addr);
+
+
+#endif /* _GPS_DL_HW_UTIL_H */
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_usrt_apb.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_usrt_apb.c
new file mode 100644
index 0000000..1254ac1
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_usrt_apb.c
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+#include "gps_dl_context.h"
+#include "gps_dl_time_tick.h"
+
+#include "gps_dl_hal.h"
+#if GPS_DL_MOCK_HAL
+#include "gps_mock_hal.h"
+#endif
+
+#include "gps_dsp_fsm.h"
+#include "gps_dl_hw_api.h"
+#include "gps_dl_hw_priv_util.h"
+
+#include "gps/gps_usrt_apb.h"
+#include "gps/gps_l5_usrt_apb.h"
+#include "gps/bgf_gps_dma.h"
+#include "conn_infra/conn_host_csr_top.h"
+
+void gps_dl_hw_usrt_rx_irq_enable(enum gps_dl_link_id_enum link_id, bool enable)
+{
+ if (enable)
+ GDL_HW_SET_GPS_ENTRY2(link_id, 1, GPS_USRT_APB_APB_INTEN_TXIEN, GPS_L5_USRT_APB_APB_INTEN_TXIEN);
+ else
+ GDL_HW_SET_GPS_ENTRY2(link_id, 0, GPS_USRT_APB_APB_INTEN_TXIEN, GPS_L5_USRT_APB_APB_INTEN_TXIEN);
+}
+
+
+unsigned int gps_dl_hw_get_mcub_a2d1_boot_cfg(enum gps_dl_link_id_enum link_id, bool is_1byte_mode)
+{
+ unsigned int cfg = 0;
+
+ cfg |= GPS_DSP_CFG_BITMASK_MVCD_SPEED_UP;
+ cfg |= GPS_DSP_CFG_BITMASK_ADIE_IS_MT6635_E2_OR_AFTER;
+ if (!is_1byte_mode)
+ cfg |= GPS_DSP_CFG_BITMASK_USRT_4BYTE_MODE;
+#if GPS_DL_USE_TIA
+ cfg |= GPS_DSP_CFG_BITMASK_COLOCK_USE_TIA;
+#endif
+ if (gps_dl_hal_get_need_clk_ext_flag(link_id))
+ cfg |= GPS_DSP_CFG_BITMASK_CLOCK_EXTENSION_WAKEUP;
+ return cfg;
+}
+
+void gps_dl_hw_set_mcub_a2d1_cfg(enum gps_dl_link_id_enum link_id, unsigned int cfg)
+{
+ GDL_HW_SET_GPS_ENTRY2(link_id, cfg, GPS_USRT_APB_MCU_A2D1_A2D_1, GPS_L5_USRT_APB_MCU_A2D1_A2D_1);
+ GDL_HW_SET_GPS_ENTRY2(link_id, 1, GPS_USRT_APB_MCUB_A2DF_A2DF3, GPS_L5_USRT_APB_MCUB_A2DF_A2DF3);
+}
+
+void gps_dl_hw_usrt_ctrl(enum gps_dl_link_id_enum link_id,
+ bool is_on, bool is_dma_mode, bool is_1byte_mode)
+{
+ bool poll_okay;
+
+ if (is_1byte_mode)
+ GDL_HW_SET_GPS_ENTRY2(link_id, 1, GPS_USRT_APB_APB_CTRL_BYTEN, GPS_L5_USRT_APB_APB_CTRL_BYTEN);
+ else
+ GDL_HW_SET_GPS_ENTRY2(link_id, 0, GPS_USRT_APB_APB_CTRL_BYTEN, GPS_L5_USRT_APB_APB_CTRL_BYTEN);
+
+ if (!is_on) {
+ GDL_HW_SET_GPS_ENTRY2(link_id, 0, GPS_USRT_APB_APB_CTRL_TX_EN, GPS_L5_USRT_APB_APB_CTRL_TX_EN);
+ GDL_HW_SET_GPS_ENTRY2(link_id, 0, GPS_USRT_APB_APB_CTRL_RX_EN, GPS_L5_USRT_APB_APB_CTRL_RX_EN);
+ GDL_HW_SET_GPS_ENTRY2(link_id, 0, GPS_USRT_APB_APB_INTEN_TXIEN, GPS_L5_USRT_APB_APB_INTEN_TXIEN);
+ GDL_HW_SET_GPS_ENTRY2(link_id, 0, GPS_USRT_APB_APB_INTEN_NODAIEN, GPS_L5_USRT_APB_APB_INTEN_NODAIEN);
+ } else if (is_dma_mode) {
+ GDL_HW_SET_GPS_ENTRY2(link_id, 1, GPS_USRT_APB_APB_CTRL_TX_EN, GPS_L5_USRT_APB_APB_CTRL_TX_EN);
+ GDL_HW_SET_GPS_ENTRY2(link_id, 1, GPS_USRT_APB_APB_CTRL_RX_EN, GPS_L5_USRT_APB_APB_CTRL_RX_EN);
+ GDL_HW_SET_GPS_ENTRY2(link_id, 1, GPS_USRT_APB_APB_INTEN_TXIEN, GPS_L5_USRT_APB_APB_INTEN_TXIEN);
+ GDL_HW_SET_GPS_ENTRY2(link_id, 1, GPS_USRT_APB_APB_INTEN_NODAIEN, GPS_L5_USRT_APB_APB_INTEN_NODAIEN);
+ } else {
+ GDL_HW_SET_GPS_ENTRY2(link_id, 0, GPS_USRT_APB_APB_CTRL_TX_EN, GPS_L5_USRT_APB_APB_CTRL_TX_EN);
+ GDL_HW_SET_GPS_ENTRY2(link_id, 0, GPS_USRT_APB_APB_CTRL_RX_EN, GPS_L5_USRT_APB_APB_CTRL_RX_EN);
+ GDL_HW_SET_GPS_ENTRY2(link_id, 1, GPS_USRT_APB_APB_INTEN_TXIEN, GPS_L5_USRT_APB_APB_INTEN_TXIEN);
+ GDL_HW_SET_GPS_ENTRY2(link_id, 0, GPS_USRT_APB_APB_INTEN_NODAIEN, GPS_L5_USRT_APB_APB_INTEN_NODAIEN);
+ }
+
+ gps_dl_hw_set_mcub_a2d1_cfg(link_id, gps_dl_hw_get_mcub_a2d1_boot_cfg(link_id, is_1byte_mode));
+
+ /* wait ROM okay flag */
+ if (link_id == GPS_DATA_LINK_ID0)
+ GDL_HW_POLL_GPS_ENTRY(GPS_USRT_APB_MCUB_D2AF_D2AF3, 1, POLL_DEFAULT, &poll_okay);
+ else
+ GDL_HW_POLL_GPS_ENTRY(GPS_L5_USRT_APB_MCUB_D2AF_D2AF3, 1, POLL_DEFAULT, &poll_okay);
+}
+
+bool gps_dl_hw_usrt_has_set_nodata_flag(enum gps_dl_link_id_enum link_id)
+{
+ return (bool)GDL_HW_GET_GPS_ENTRY2(link_id,
+ GPS_USRT_APB_APB_STA_NODAINTB, GPS_L5_USRT_APB_APB_STA_NODAINTB);
+}
+
+void gps_dl_hw_usrt_clear_nodata_irq(enum gps_dl_link_id_enum link_id)
+{
+ GDL_HW_SET_GPS_ENTRY2(link_id, 1, GPS_USRT_APB_APB_STA_NODAINTB, GPS_L5_USRT_APB_APB_STA_NODAINTB);
+}
+
+void gps_dl_hw_print_usrt_status(enum gps_dl_link_id_enum link_id)
+{
+ bool show_log;
+ unsigned int value;
+
+ show_log = gps_dl_set_show_reg_rw_log(true);
+ if (link_id == GPS_DATA_LINK_ID0) {
+ value = GDL_HW_RD_GPS_REG(GPS_USRT_APB_APB_STA_ADDR);
+ value = GDL_HW_RD_GPS_REG(GPS_USRT_APB_MONF_ADDR);
+ } else if (link_id == GPS_DATA_LINK_ID1) {
+ value = GDL_HW_RD_GPS_REG(GPS_L5_USRT_APB_APB_STA_ADDR);
+ value = GDL_HW_RD_GPS_REG(GPS_L5_USRT_APB_MONF_ADDR);
+ }
+ gps_dl_set_show_reg_rw_log(show_log);
+}
+
+bool gps_dl_hw_poll_usrt_dsp_rx_empty(enum gps_dl_link_id_enum link_id)
+{
+ bool poll_okay = false;
+
+ if (link_id == GPS_DATA_LINK_ID0)
+ GDL_HW_POLL_GPS_ENTRY(GPS_USRT_APB_APB_STA_RX_EMP, 1, 10000 * POLL_US, &poll_okay);
+ else if (link_id == GPS_DATA_LINK_ID1)
+ GDL_HW_POLL_GPS_ENTRY(GPS_L5_USRT_APB_APB_STA_RX_EMP, 1, 10000 * POLL_US, &poll_okay);
+
+ if (!poll_okay)
+ GDL_LOGXE_DRW(link_id, "okay = %d", poll_okay);
+
+ return poll_okay;
+}
+
+enum GDL_RET_STATUS gps_dl_hal_wait_and_handle_until_usrt_has_data(
+ enum gps_dl_link_id_enum link_id, int timeout_usec)
+{
+ struct gps_dl_hw_usrt_status_struct usrt_status;
+ bool last_rw_log_on;
+ unsigned long tick0, tick1;
+
+ tick0 = gps_dl_tick_get();
+
+ if (gps_dl_show_reg_wait_log())
+ GDL_LOGXD(link_id, "timeout = %d", timeout_usec);
+
+ while (1) {
+ gps_dl_hw_save_usrt_status_struct(link_id, &usrt_status);
+
+ if (gps_dl_only_show_wait_done_log())
+ last_rw_log_on = gps_dl_set_show_reg_rw_log(false);
+ else
+ gps_dl_hw_print_usrt_status_struct(link_id, &usrt_status);
+
+ if (GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_TX_IND, usrt_status.state)) {
+ if (gps_dl_only_show_wait_done_log()) {
+ gps_dl_set_show_reg_rw_log(last_rw_log_on);
+ gps_dl_hw_print_usrt_status_struct(link_id, &usrt_status);
+ gps_dl_hw_save_usrt_status_struct(link_id, &usrt_status);
+ }
+
+ gps_dl_hal_event_send(GPS_DL_HAL_EVT_D2A_RX_HAS_DATA, link_id);
+ break;
+ }
+
+ tick1 = gps_dl_tick_get();
+ if (timeout_usec > GPS_DL_RW_NO_TIMEOUT &&
+ gps_dl_tick_delta_to_usec(tick0, tick1) >= timeout_usec)
+ return GDL_FAIL_TIMEOUT;
+
+ gps_dl_wait_us(GDL_HW_STATUS_POLL_INTERVAL_USEC);
+ }
+
+ return GDL_OKAY;
+}
+
+enum GDL_RET_STATUS gps_dl_hal_wait_and_handle_until_usrt_has_nodata_or_rx_dma_done(
+ enum gps_dl_link_id_enum link_id, int timeout_usec, bool to_handle)
+{
+ struct gps_dl_hw_dma_status_struct dma_status;
+ struct gps_dl_hw_usrt_status_struct usrt_status;
+ enum gps_dl_hal_dma_ch_index dma_ch;
+ bool last_rw_log_on;
+ unsigned long tick0, tick1;
+ bool conninfra_okay;
+ bool do_stop = true;
+ enum GDL_RET_STATUS ret = GDL_OKAY;
+ int loop_cnt;
+
+ if (link_id == GPS_DATA_LINK_ID0)
+ dma_ch = GPS_DL_DMA_LINK0_D2A;
+ else if (link_id == GPS_DATA_LINK_ID1)
+ dma_ch = GPS_DL_DMA_LINK1_D2A;
+ else
+ return GDL_FAIL;
+
+ if (gps_dl_show_reg_wait_log())
+ GDL_LOGXD(link_id, "timeout = %d", timeout_usec);
+
+ tick0 = gps_dl_tick_get();
+ loop_cnt = 0;
+ while (1) {
+ conninfra_okay = gps_dl_conninfra_is_okay_or_handle_it(NULL, true);
+ if (!conninfra_okay) {
+ ret = GDL_FAIL_CONN_NOT_OKAY;
+ do_stop = false;
+ break;
+ }
+
+ gps_dl_hw_save_dma_status_struct(dma_ch, &dma_status);
+ if (gps_dl_only_show_wait_done_log())
+ last_rw_log_on = gps_dl_set_show_reg_rw_log(false);
+ else
+ gps_dl_hw_print_dma_status_struct(dma_ch, &dma_status);
+
+ if (GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_START_STR, dma_status.intr_flag) &&
+ GDL_HW_EXTRACT_ENTRY(BGF_GPS_DMA_DMA1_STATE_STATE, dma_status.state) == 0x01) {
+ if (gps_dl_only_show_wait_done_log()) {
+ gps_dl_set_show_reg_rw_log(last_rw_log_on);
+ gps_dl_hw_print_dma_status_struct(dma_ch, &dma_status);
+ gps_dl_hw_save_dma_status_struct(dma_ch, &dma_status);
+ }
+
+ /* DMA has stopped */
+ gps_dl_hw_set_dma_stop(dma_ch);
+ gps_dl_hw_save_dma_status_struct(dma_ch, &dma_status);
+ gps_dl_hw_print_dma_status_struct(dma_ch, &dma_status);
+ if (to_handle)
+ gps_dl_hal_event_send(GPS_DL_HAL_EVT_D2A_RX_DMA_DONE, link_id);
+ ret = GDL_OKAY;
+ do_stop = true;
+ break;
+ }
+
+ gps_dl_hw_save_usrt_status_struct(link_id, &usrt_status);
+ if (gps_dl_only_show_wait_done_log())
+ last_rw_log_on = gps_dl_set_show_reg_rw_log(false);
+ else
+ gps_dl_hw_print_usrt_status_struct(link_id, &usrt_status);
+
+ if (GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_REGE, usrt_status.state) ||
+ GDL_HW_EXTRACT_ENTRY(GPS_USRT_APB_APB_STA_NODAINTB, usrt_status.state)) {
+ if (gps_dl_only_show_wait_done_log()) {
+ gps_dl_set_show_reg_rw_log(last_rw_log_on);
+ gps_dl_hw_print_usrt_status_struct(link_id, &usrt_status);
+ gps_dl_hw_save_usrt_status_struct(link_id, &usrt_status);
+ }
+ if (to_handle)
+ gps_dl_hal_event_send(GPS_DL_HAL_EVT_D2A_RX_HAS_NODATA, link_id);
+ else {
+ gps_dl_hw_set_dma_stop(dma_ch);
+ gps_dl_hw_save_dma_status_struct(dma_ch, &dma_status);
+ gps_dl_hw_print_dma_status_struct(dma_ch, &dma_status);
+ }
+ ret = GDL_OKAY;
+ do_stop = true;
+ break;
+ }
+
+ tick1 = gps_dl_tick_get();
+ if (timeout_usec > GPS_DL_RW_NO_TIMEOUT && (
+ gps_dl_tick_delta_to_usec(tick0, tick1) >= timeout_usec ||
+ loop_cnt * GDL_HW_STATUS_POLL_INTERVAL_USEC >= timeout_usec)) {
+ ret = GDL_FAIL_TIMEOUT;
+ do_stop = false;
+ break;
+ }
+
+ gps_dl_wait_us(GDL_HW_STATUS_POLL_INTERVAL_USEC);
+ loop_cnt++;
+ }
+
+ tick1 = gps_dl_tick_get();
+ GDL_LOGXW(link_id, "d_us = %d, cnt = %d, do_stop = %d, ret = %s",
+ gps_dl_tick_delta_to_usec(tick0, tick1), loop_cnt, do_stop, gdl_ret_to_name(ret));
+ return ret;
+}
+
+void gps_dl_hal_poll_single_link(enum gps_dl_link_id_enum link_id,
+ unsigned int evt_in, unsigned int *p_evt_out)
+{
+ unsigned int evt_out = 0;
+ struct gps_dl_hw_link_status_struct hw_status;
+
+ gps_dl_hw_get_link_status(link_id, &hw_status);
+
+ if (evt_in & (1UL << GPS_DL_POLL_TX_DMA_DONE)) {
+ if (hw_status.tx_dma_done) {
+ evt_out |= (1UL << GPS_DL_POLL_TX_DMA_DONE);
+ gps_dl_isr_a2d_tx_dma_done(link_id);
+ }
+ }
+
+ if (evt_in & (1UL << GPS_DL_POLL_RX_DMA_DONE)) {
+ if (hw_status.rx_dma_done) {
+ evt_out |= (1UL << GPS_DL_POLL_RX_DMA_DONE);
+ gps_dl_isr_d2a_rx_dma_done(link_id);
+ }
+ }
+
+ if (evt_in & (1UL << GPS_DL_POLL_USRT_HAS_DATA)) {
+ if (hw_status.usrt_has_data) {
+ evt_out |= (1UL << GPS_DL_POLL_USRT_HAS_DATA);
+ gps_dl_isr_usrt_has_data(link_id);
+ }
+ }
+
+ if (evt_in & (1UL << GPS_DL_POLL_USRT_HAS_NODATA)) {
+ if (hw_status.usrt_has_nodata) {
+ evt_out |= (1UL << GPS_DL_POLL_USRT_HAS_NODATA);
+ gps_dl_isr_usrt_has_nodata(link_id);
+ }
+ }
+
+ *p_evt_out = evt_out;
+}
+
+enum GDL_RET_STATUS gps_dl_hal_poll_event(
+ unsigned int L1_evt_in, unsigned int L5_evt_in,
+ unsigned int *pL1_evt_out, unsigned int *pL5_evt_out, unsigned int timeout_usec)
+{
+ unsigned int L1_evt_out = 0;
+ unsigned int L5_evt_out = 0;
+ enum GDL_RET_STATUS ret_val = GDL_OKAY;
+ unsigned long tick0, tick1;
+ int take_usec;
+
+ if (L1_evt_in == 0 && L5_evt_in == 0) {
+ *pL1_evt_out = 0;
+ *pL5_evt_out = 0;
+ return GDL_OKAY;
+ }
+
+ tick0 = gps_dl_tick_get();
+ while (1) {
+ if (L1_evt_in)
+ gps_dl_hal_poll_single_link(GPS_DATA_LINK_ID0, L1_evt_in, &L1_evt_out);
+
+ if (L5_evt_in)
+ gps_dl_hal_poll_single_link(GPS_DATA_LINK_ID1, L5_evt_in, &L5_evt_out);
+
+ tick1 = gps_dl_tick_get();
+ take_usec = gps_dl_tick_delta_to_usec(tick0, tick1);
+
+ if (L1_evt_out || L5_evt_out)
+ break;
+
+ GDL_LOGD("tick0 = %ld, tick1 = %ld, usec = %d/%d",
+ tick0, tick1, take_usec, timeout_usec);
+
+ if (take_usec >= timeout_usec) {
+ ret_val = GDL_FAIL_TIMEOUT;
+ break;
+ }
+
+ gps_dl_wait_us(GDL_HW_STATUS_POLL_INTERVAL_USEC);
+ }
+
+ GDL_LOGD("ret = %d, L1 = 0x%x, L5 = 0x%x, usec = %d/%d",
+ ret_val, L1_evt_out, L5_evt_out, take_usec, timeout_usec);
+
+ if (ret_val != GDL_OKAY)
+ return ret_val;
+
+ /* TODO: read one more time? */
+ *pL1_evt_out = L1_evt_out;
+ *pL5_evt_out = L5_evt_out;
+ return GDL_OKAY;
+}
+
+int gps_dl_hal_usrt_direct_write(enum gps_dl_link_id_enum link_id,
+ unsigned char *buf, unsigned int len)
+{
+ unsigned int reg_val;
+ unsigned int reg_addr;
+ int i, j;
+
+ if (link_id == GPS_DATA_LINK_ID0)
+ reg_addr = GPS_USRT_APB_GPS_APB_DATA_ADDR;
+ else if (link_id == GPS_DATA_LINK_ID1)
+ reg_addr = GPS_L5_USRT_APB_GPS_APB_DATA_ADDR;
+ else
+ return -1;
+
+ if (gps_dl_is_1byte_mode()) {
+ for (i = 0; i < len; i++)
+ gps_dl_bus_write_no_rb(GPS_DL_GPS_BUS, reg_addr, buf[i]);
+ } else {
+ for (i = 0; i < len;) {
+ reg_val = (unsigned int) buf[i++];
+
+ for (j = 1; j < 4 && i < len; j++, i++)
+ reg_val |= (((unsigned int) buf[i]) << (j * 8));
+
+ gps_dl_bus_write_no_rb(GPS_DL_GPS_BUS, reg_addr, reg_val);
+ }
+ }
+
+ return 0;
+}
+
+int gps_dl_hal_usrt_direct_read(enum gps_dl_link_id_enum link_id,
+ unsigned char *buf, unsigned int len)
+{
+ unsigned int reg_val;
+ unsigned int reg_addr;
+ struct gps_dl_hw_link_status_struct hw_status;
+ int i;
+
+ if (link_id == GPS_DATA_LINK_ID0)
+ reg_addr = GPS_USRT_APB_GPS_APB_DATA_ADDR;
+ else if (link_id == GPS_DATA_LINK_ID1)
+ reg_addr = GPS_L5_USRT_APB_GPS_APB_DATA_ADDR;
+ else
+ return -1;
+
+ /* GPS_USRT_APB_APB_STA_TXINTB_SHFT */
+ /* APB_STA[7:0]: 0x22000030 -> 0x20000009 -> 0x22000019 -> 0x22000030 */
+ do {
+ gps_dl_hw_get_link_status(link_id, &hw_status);
+ } while (!hw_status.usrt_has_data);
+
+ for (i = 0; i < len; ) {
+ reg_val = GDL_HW_RD_GPS_REG(reg_addr);
+
+ if (gps_dl_is_1byte_mode())
+ buf[i++] = (unsigned char)reg_val;
+ else {
+ buf[i++] = (unsigned char)(reg_val >> 0);
+ buf[i++] = (unsigned char)(reg_val >> 8);
+ buf[i++] = (unsigned char)(reg_val >> 16);
+ buf[i++] = (unsigned char)(reg_val >> 24);
+ }
+
+ gps_dl_hw_get_link_status(link_id, &hw_status);
+ if (!hw_status.usrt_has_data) /* no need: hw_status.usrt_has_nodata */
+ break;
+ }
+
+ GDL_LOGXD(link_id, "read len = %d", i);
+ return i;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_util.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_util.c
new file mode 100644
index 0000000..7c7398e
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/gps_dl_hw_util.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+#include "gps_dl_context.h"
+#include "gps_dl_hw_priv_util.h"
+#include "gps_dl_subsys_reset.h"
+
+#if GPS_DL_ON_LINUX
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <asm/io.h>
+#include "gps_dl_linux.h"
+#if GPS_DL_HAS_PLAT_DRV
+#include "gps_dl_linux_plat_drv.h"
+#endif
+#elif GPS_DL_ON_CTP
+#include "kernel_to_ctp.h"
+#endif
+
+unsigned int gps_dl_bus_to_host_addr(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr)
+{
+ unsigned int host_addr = 0;
+
+ switch (bus_id) {
+ case GPS_DL_GPS_BUS:
+ host_addr = gps_bus_to_host(bus_addr);
+ break;
+ case GPS_DL_BGF_BUS:
+ host_addr = bgf_bus_to_host(bus_addr);
+ break;
+ case GPS_DL_CONN_INFRA_BUS:
+ host_addr = bus_addr;
+ break;
+ default:
+ host_addr = 0;
+ }
+
+ return host_addr;
+}
+
+void gps_dl_bus_wr_opt(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr, unsigned int val,
+ unsigned int opt_bitmask)
+{
+ bool no_read_back = !!(opt_bitmask & BMASK_WR_NO_READ_BACK);
+ bool do_check = !!(opt_bitmask & BMASK_RW_DO_CHECK);
+ bool force_print = !!(opt_bitmask & BMASK_RW_FORCE_PRINT);
+ bool full_print = !!(opt_bitmask & BMASK_RW_FULL_PRINT);
+ bool print_vir_addr = false;
+
+ unsigned int read_back_val = 0;
+ unsigned int host_addr = gps_dl_bus_to_host_addr(bus_id, bus_addr);
+#if GPS_DL_ON_LINUX
+#if GPS_DL_HAS_PLAT_DRV
+ void __iomem *host_vir_addr = gps_dl_host_addr_to_virt(host_addr);
+#else
+ void __iomem *host_vir_addr = phys_to_virt(host_addr);
+#endif
+#else
+ void *host_vir_addr = NULL;
+#endif
+
+ /*
+ * For linux preparation and checking
+ */
+#if GPS_DL_ON_LINUX
+ if (host_vir_addr == NULL) {
+ GDL_LOGW_RRW("bus_id = %d, addr = 0x%p/0x%08x/0x%08x, NULL!",
+ bus_id, host_vir_addr, host_addr, bus_addr);
+ return;
+ }
+ print_vir_addr = true;
+
+ if (do_check) {
+ /* gps_dl_conninfra_not_readable_show_warning(host_addr); */
+ gps_dl_bus_check_and_print(host_addr);
+ }
+#endif /* GPS_DL_ON_LINUX */
+
+ /*
+ * Do writing
+ */
+#if GPS_DL_HW_IS_MOCK
+ /* do nothing if it's mock */
+#elif GPS_DL_ON_LINUX
+ gps_dl_linux_sync_writel(val, host_vir_addr);
+#else
+ GPS_DL_HOST_REG_WR(host_addr, val);
+#endif
+
+ /*
+ * Do reading back
+ */
+ if (!no_read_back) {
+#if GPS_DL_HW_IS_MOCK
+ /* do nothing if it's mock */
+#elif GPS_DL_ON_LINUX
+ read_back_val = __raw_readl(host_vir_addr);
+#else
+ read_back_val = GPS_DL_HOST_REG_RD(host_addr);
+#endif
+ }
+ if (!(gps_dl_show_reg_rw_log() || force_print))
+ return;
+
+ /*
+ * Do printing if need
+ */
+ if (no_read_back && (!full_print)) {
+ GDL_LOGI_RRW("bus_id = %d, addr = 0x%08x, w_val = 0x%08x",
+ bus_id, host_addr, val);
+ } else if (no_read_back && (full_print && !print_vir_addr)) {
+ GDL_LOGI_RRW("bus_id = %d, addr = 0x%08x/0x%08x, w_val = 0x%08x",
+ bus_id, host_addr, bus_addr, val);
+ } else if (no_read_back && (full_print && print_vir_addr)) {
+ GDL_LOGI_RRW("bus_id = %d, addr = 0x%p/0x%08x/0x%08x, w_val = 0x%08x",
+ bus_id, host_vir_addr, host_addr, bus_addr, val);
+ } else if (!no_read_back && (!full_print)) {
+ GDL_LOGI_RRW("bus_id = %d, addr = 0x%08x, w_val = 0x%08x, r_back = 0x%08x",
+ bus_id, host_addr, val, read_back_val);
+ } else if (!no_read_back && (full_print && !print_vir_addr)) {
+ GDL_LOGI_RRW("bus_id = %d, addr = 0x%08x/0x%08x, w_val = 0x%08x, r_back = 0x%08x",
+ bus_id, host_addr, bus_addr, val, read_back_val);
+ } else {
+ /* if (!no_read_back && (full_print && print_vir_addr)) */
+ GDL_LOGI_RRW("bus_id = %d, addr = 0x%p/0x%08x/0x%08x, w_val = 0x%08x, r_back = 0x%08x",
+ bus_id, host_vir_addr, host_addr, bus_addr, val, read_back_val);
+ }
+}
+
+void gps_dl_bus_write(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr, unsigned int val)
+{
+ /* gps_dl_bus_wr_opt(bus_id, bus_addr, val, BMASK_RW_DO_CHECK); */
+ gps_dl_bus_wr_opt(bus_id, bus_addr, val, 0);
+}
+
+void gps_dl_bus_write_no_rb(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr, unsigned int val)
+{
+ gps_dl_bus_wr_opt(bus_id, bus_addr, val, BMASK_WR_NO_READ_BACK);
+}
+
+unsigned int gps_dl_bus_rd_opt(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr,
+ unsigned int opt_bitmask)
+{
+ bool do_check = !!(opt_bitmask & BMASK_RW_DO_CHECK);
+ bool force_print = !!(opt_bitmask & BMASK_RW_FORCE_PRINT);
+ bool full_print = !!(opt_bitmask & BMASK_RW_FULL_PRINT);
+ bool print_vir_addr = false;
+
+ unsigned int val = 0;
+ unsigned int host_addr = gps_dl_bus_to_host_addr(bus_id, bus_addr);
+#if GPS_DL_ON_LINUX
+#if GPS_DL_HAS_PLAT_DRV
+ void __iomem *host_vir_addr = gps_dl_host_addr_to_virt(host_addr);
+#else
+ void __iomem *host_vir_addr = phys_to_virt(host_addr);
+#endif
+#else
+ void *host_vir_addr = NULL;
+#endif
+
+ /*
+ * For linux preparation and checking
+ */
+#if GPS_DL_ON_LINUX
+ if (host_vir_addr == NULL) {
+ GDL_LOGW_RRW("bus_id = %d, addr = 0x%p/0x%08x/0x%08x, NULL!",
+ bus_id, host_vir_addr, host_addr, bus_addr);
+ return 0;
+ }
+ print_vir_addr = true;
+
+ if (do_check) {
+ /* gps_dl_conninfra_not_readable_show_warning(host_addr); */
+ gps_dl_bus_check_and_print(host_addr);
+ }
+#endif /* GPS_DL_ON_LINUX */
+
+ /*
+ * Do reading
+ */
+#if GPS_DL_HW_IS_MOCK
+ /* do nothing if it's mock */
+#elif GPS_DL_ON_LINUX
+ val = __raw_readl(host_vir_addr);
+#else
+ val = GPS_DL_HOST_REG_RD(host_addr);
+#endif
+ if (!(gps_dl_show_reg_rw_log() || force_print))
+ return val;
+
+ /*
+ * Do printing if need
+ */
+ if (!full_print) {
+ GDL_LOGI_RRW("bus_id = %d, addr = 0x%08x, r_val = 0x%08x",
+ bus_id, host_addr, val);
+ } else if (full_print && !print_vir_addr) {
+ GDL_LOGI_RRW("bus_id = %d, addr = 0x%08x/0x%08x, r_val = 0x%08x",
+ bus_id, host_addr, bus_addr, val);
+ } else {
+ /* if (full_print && print_vir_addr) */
+ GDL_LOGI_RRW("bus_id = %d, addr = 0x%p/0x%08x/0x%08x, r_val = 0x%08x",
+ bus_id, host_vir_addr, host_addr, bus_addr, val);
+ }
+ return val;
+}
+
+unsigned int gps_dl_bus_read(enum GPS_DL_BUS_ENUM bus_id, unsigned int bus_addr)
+{
+ /* return gps_dl_bus_rd_opt(bus_id, bus_addr, BMASK_RW_DO_CHECK); */
+ return gps_dl_bus_rd_opt(bus_id, bus_addr, 0);
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/gps_dl_hw_api.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/gps_dl_hw_api.h
new file mode 100644
index 0000000..7ac1c0d
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/gps_dl_hw_api.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_HW_API_H
+#define _GPS_DL_HW_API_H
+
+#include "gps_dl_config.h"
+#include "gps_dl_dma_buf.h"
+#include "gps_dl_hal_api.h"
+#include "gps_dl_hal_type.h"
+
+enum GDL_HW_RET {
+ HW_OKAY, /* hw CRs access okay */
+ E_INV_PARAMS, /* invalid parameters */
+ E_RESETTING, /* whole chip reset is on-going */
+ E_POLL_TIMEOUT, /* timeout when waiting CR change to excepted value */
+ E_MAX
+};
+
+#if GPS_DL_ON_LINUX
+#define GDL_HW_STATUS_POLL_INTERVAL_USEC (1) /* 1us */
+#else
+#define GDL_HW_STATUS_POLL_INTERVAL_USEC (2*1000) /* 2ms */
+#endif
+
+enum dsp_ctrl_enum {
+ GPS_L1_DSP_ON,
+ GPS_L1_DSP_OFF,
+ GPS_L5_DSP_ON,
+ GPS_L5_DSP_OFF,
+ GPS_L1_DSP_ENTER_DSLEEP,
+ GPS_L1_DSP_EXIT_DSLEEP,
+ GPS_L1_DSP_ENTER_DSTOP,
+ GPS_L1_DSP_EXIT_DSTOP,
+ GPS_L5_DSP_ENTER_DSLEEP,
+ GPS_L5_DSP_EXIT_DSLEEP,
+ GPS_L5_DSP_ENTER_DSTOP,
+ GPS_L5_DSP_EXIT_DSTOP,
+ GPS_L1_DSP_CLEAR_PWR_STAT,
+ GPS_L5_DSP_CLEAR_PWR_STAT,
+ GPS_DSP_CTRL_MAX
+};
+int gps_dl_hw_gps_dsp_ctrl(enum dsp_ctrl_enum ctrl);
+bool gps_dl_hw_gps_dsp_is_off_done(enum gps_dl_link_id_enum link_id);
+void gps_dl_hw_gps_adie_force_off(void);
+void gps_dl_hw_gps_dump_top_rf_cr(void);
+
+int gps_dl_hw_gps_common_on(void);
+int gps_dl_hw_gps_common_off(void);
+bool gps_dl_hw_gps_force_wakeup_conninfra_top_off(bool enable);
+void gps_dl_hw_gps_sw_request_emi_usage(bool request);
+
+enum GDL_HW_RET gps_dl_hw_get_mcub_info(
+ enum gps_dl_link_id_enum link_id, struct gps_dl_hal_mcub_info *p);
+
+void gps_dl_hw_clear_mcub_d2a_flag(
+ enum gps_dl_link_id_enum link_id, unsigned int d2a_flag);
+
+unsigned int gps_dl_hw_get_mcub_a2d_flag(enum gps_dl_link_id_enum link_id);
+
+enum GDL_RET_STATUS gps_dl_hw_mcub_dsp_read_request(
+ enum gps_dl_link_id_enum link_id, u16 dsp_addr);
+
+void gps_dl_hw_set_gps_emi_remapping(unsigned int _20msb_of_36bit_phy_addr);
+unsigned int gps_dl_hw_get_gps_emi_remapping(void);
+
+void gps_dl_hw_set_dma_start(enum gps_dl_hal_dma_ch_index channel,
+ struct gdl_hw_dma_transfer *p_transfer);
+
+void gps_dl_hw_set_dma_stop(enum gps_dl_hal_dma_ch_index channel);
+
+bool gps_dl_hw_get_dma_int_status(enum gps_dl_hal_dma_ch_index channel);
+
+unsigned int gps_dl_hw_get_dma_left_len(enum gps_dl_hal_dma_ch_index channel);
+
+struct gps_dl_hw_dma_status_struct {
+ unsigned int wrap_count;
+ unsigned int wrap_to_addr;
+ unsigned int total_count;
+ unsigned int config;
+ unsigned int start_flag;
+ unsigned int intr_flag;
+ unsigned int left_count;
+ unsigned int curr_addr;
+ unsigned int state;
+};
+
+void gps_dl_hw_save_dma_status_struct(
+ enum gps_dl_hal_dma_ch_index ch, struct gps_dl_hw_dma_status_struct *p);
+
+void gps_dl_hw_print_dma_status_struct(
+ enum gps_dl_hal_dma_ch_index ch, struct gps_dl_hw_dma_status_struct *p);
+
+enum GDL_RET_STATUS gps_dl_hw_wait_until_dma_complete_and_stop_it(
+ enum gps_dl_hal_dma_ch_index ch, int timeout_usec, bool return_if_not_start);
+
+
+struct gps_dl_hw_usrt_status_struct {
+ unsigned int ctrl_setting;
+ unsigned int intr_enable;
+ unsigned int state;
+ unsigned int mcub_d2a_flag;
+ unsigned int mcub_d2a_d0;
+ unsigned int mcub_d2a_d1;
+ unsigned int mcub_a2d_flag;
+ unsigned int mcub_a2d_d0;
+ unsigned int mcub_a2d_d1;
+};
+
+/* TODO: replace gps_dl_hw_usrt_status_struct */
+struct gps_dl_hw_link_status_struct {
+ bool usrt_has_data;
+ bool usrt_has_nodata;
+ bool rx_dma_done;
+ bool tx_dma_done;
+};
+
+void gps_dl_hw_get_link_status(
+ enum gps_dl_link_id_enum link_id, struct gps_dl_hw_link_status_struct *p);
+
+void gps_dl_hw_save_usrt_status_struct(
+ enum gps_dl_link_id_enum link_id, struct gps_dl_hw_usrt_status_struct *p);
+
+void gps_dl_hw_print_usrt_status_struct(
+ enum gps_dl_link_id_enum link_id, struct gps_dl_hw_usrt_status_struct *p);
+
+void gps_dl_hw_dump_sleep_prot_status(void);
+void gps_dl_hw_dump_host_csr_gps_info(bool force_show_log);
+void gps_dl_hw_dump_host_csr_conninfra_info(bool force_show_log);
+void gps_dl_hw_print_hw_status(enum gps_dl_link_id_enum link_id, bool dump_rf_cr);
+void gps_dl_hw_do_gps_a2z_dump(void);
+void gps_dl_hw_print_usrt_status(enum gps_dl_link_id_enum link_id);
+bool gps_dl_hw_poll_usrt_dsp_rx_empty(enum gps_dl_link_id_enum link_id);
+void gps_dl_hw_gps_dump_gps_rf_cr(void);
+void gps_dl_hw_print_ms_counter_status(void);
+
+void gps_dl_hw_switch_dsp_jtag(void);
+
+void gps_dl_hw_usrt_rx_irq_enable(
+ enum gps_dl_link_id_enum link_id, bool enable);
+void gps_dl_hw_usrt_ctrl(enum gps_dl_link_id_enum link_id,
+ bool is_on, bool is_dma_mode, bool is_1byte_mode);
+void gps_dl_hw_usrt_clear_nodata_irq(enum gps_dl_link_id_enum link_id);
+bool gps_dl_hw_usrt_has_set_nodata_flag(enum gps_dl_link_id_enum link_id);
+
+
+bool gps_dl_hw_is_pta_clk_cfg_ready(void);
+
+bool gps_dl_hw_is_pta_uart_init_done(void);
+bool gps_dl_hw_init_pta_uart(void);
+void gps_dl_hw_deinit_pta_uart(void);
+
+bool gps_dl_hw_is_pta_init_done(void);
+void gps_dl_hw_init_pta(void);
+void gps_dl_hw_deinit_pta(void);
+
+void gps_dl_hw_claim_pta_used_by_gps(void);
+void gps_dl_hw_disclaim_pta_used_by_gps(void);
+void gps_dl_hw_set_pta_blanking_parameter(void);
+
+bool gps_dl_hw_take_conn_coex_hw_sema(unsigned int timeout_ms);
+void gps_dl_hw_give_conn_coex_hw_sema(void);
+bool gps_dl_hw_take_conn_rfspi_hw_sema(unsigned int timeout_ms);
+void gps_dl_hw_give_conn_rfspi_hw_sema(void);
+
+unsigned int gps_dl_hw_get_mcub_a2d1_boot_cfg(enum gps_dl_link_id_enum link_id, bool is_1byte_mode);
+void gps_dl_hw_set_mcub_a2d1_cfg(enum gps_dl_link_id_enum link_id, unsigned int cfg);
+
+#endif /* _GPS_DL_HW_API_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/gps_dl_hw_type.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/gps_dl_hw_type.h
new file mode 100644
index 0000000..62f9b35
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/gps_dl_hw_type.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_HW_TYPE_H
+#define _GPS_DL_HW_TYPE_H
+
+#include "gps_dl_config.h"
+
+/* to import u32 series types */
+#if GPS_DL_ON_LINUX
+#include <linux/types.h>
+#elif GPS_DL_ON_CTP
+#include "kernel_to_ctp.h"
+#endif
+
+typedef u32 conn_reg;
+
+
+#define GPS_DL_HW_INVALID_ADDR (0xFFFFFFFF)
+
+#endif /* _GPS_DL_HW_TYPE_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/conn_infra/conn_host_csr_top.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/conn_infra/conn_host_csr_top.h
new file mode 100644
index 0000000..2a2fca1
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/conn_infra/conn_host_csr_top.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+#ifndef __CONN_HOST_CSR_TOP_REGS_H__
+#define __CONN_HOST_CSR_TOP_REGS_H__
+
+#define CONN_HOST_CSR_TOP_BASE 0x18060000
+
+#define CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_ADDR (CONN_HOST_CSR_TOP_BASE + 0x00B0)
+#define CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_ADDR (CONN_HOST_CSR_TOP_BASE + 0x0240)
+#define CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_GPS_ADDR (CONN_HOST_CSR_TOP_BASE + 0x01AC)
+#define CONN_HOST_CSR_TOP_CONN_INFRA_ON_DEBUG_AO_DEBUGSYS_ADDR (CONN_HOST_CSR_TOP_BASE + 0x0138)
+#define CONN_HOST_CSR_TOP_CONN_INFRA_ON_DEBUG_CTRL_AO2SYS_OUT_ADDR (CONN_HOST_CSR_TOP_BASE + 0x0150)
+#define CONN_HOST_CSR_TOP_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_ADDR (CONN_HOST_CSR_TOP_BASE + 0x01D0)
+
+
+#define CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_HOST2GPS_DEGUG_SEL_ADDR CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_ADDR
+#define CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_HOST2GPS_DEGUG_SEL_MASK 0x000000FF
+#define CONN_HOST_CSR_TOP_HOST2GPS_DEGUG_SEL_HOST2GPS_DEGUG_SEL_SHFT 0
+
+#define CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_GPS_CFG2HOST_DEBUG_ADDR CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_ADDR
+#define CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_GPS_CFG2HOST_DEBUG_MASK 0x0000FFFF
+#define CONN_HOST_CSR_TOP_GPS_CFG2HOST_DEBUG_GPS_CFG2HOST_DEBUG_SHFT 0
+
+#define CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_GPS_CONN_INFRA_WAKEPU_GPS_ADDR CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_GPS_ADDR
+#define CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_GPS_CONN_INFRA_WAKEPU_GPS_MASK 0x00000001
+#define CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_GPS_CONN_INFRA_WAKEPU_GPS_SHFT 0
+
+#define CONN_HOST_CSR_TOP_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_ADDR \
+ CONN_HOST_CSR_TOP_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_ADDR
+#define CONN_HOST_CSR_TOP_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_MASK 0x000FFFFF
+#define CONN_HOST_CSR_TOP_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_CONN2AP_REMAP_GPS_EMI_BASE_ADDR_SHFT 0
+
+#endif /* __CONN_HOST_CSR_TOP_REGS_H__ */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/conn_infra/conn_infra_cfg.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/conn_infra/conn_infra_cfg.h
new file mode 100644
index 0000000..6b3b752
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/conn_infra/conn_infra_cfg.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+#ifndef __CONN_INFRA_CFG_REGS_H__
+#define __CONN_INFRA_CFG_REGS_H__
+
+#define CONN_INFRA_CFG_BASE 0x18001000
+
+#define CONN_INFRA_CFG_CONN_HW_VER_ADDR (CONN_INFRA_CFG_BASE + 0x0000)
+#define CONN_INFRA_CFG_GPS_PWRCTRL0_ADDR (CONN_INFRA_CFG_BASE + 0x020C)
+#define CONN_INFRA_CFG_EMI_CTL_TOP_ADDR (CONN_INFRA_CFG_BASE + 0x0410)
+#define CONN_INFRA_CFG_EMI_CTL_WF_ADDR (CONN_INFRA_CFG_BASE + 0x0414)
+#define CONN_INFRA_CFG_EMI_CTL_BT_ADDR (CONN_INFRA_CFG_BASE + 0x0418)
+#define CONN_INFRA_CFG_EMI_CTL_GPS_ADDR (CONN_INFRA_CFG_BASE + 0x041C)
+#define CONN_INFRA_CFG_CONN_INFRA_CONN2GPS_SLP_CTRL_ADDR (CONN_INFRA_CFG_BASE + 0x0570)
+#define CONN_INFRA_CFG_GALS_CONN2GPS_SLP_STATUS_ADDR (CONN_INFRA_CFG_BASE + 0x0574)
+#define CONN_INFRA_CFG_CONN_INFRA_GPS2CONN_SLP_CTRL_ADDR (CONN_INFRA_CFG_BASE + 0x0580)
+#define CONN_INFRA_CFG_GALS_GPS2CONN_SLP_STATUS_ADDR (CONN_INFRA_CFG_BASE + 0x0584)
+
+
+#define CONN_INFRA_CFG_CONN_HW_VER_RO_CONN_HW_VERSION_ADDR CONN_INFRA_CFG_CONN_HW_VER_ADDR
+#define CONN_INFRA_CFG_CONN_HW_VER_RO_CONN_HW_VERSION_MASK 0xFFFFFFFF
+#define CONN_INFRA_CFG_CONN_HW_VER_RO_CONN_HW_VERSION_SHFT 0
+
+#define CONN_INFRA_CFG_GPS_PWRCTRL0_GPS_FUNCTION_EN_ADDR CONN_INFRA_CFG_GPS_PWRCTRL0_ADDR
+#define CONN_INFRA_CFG_GPS_PWRCTRL0_GPS_FUNCTION_EN_MASK 0x00000001
+#define CONN_INFRA_CFG_GPS_PWRCTRL0_GPS_FUNCTION_EN_SHFT 0
+
+#define CONN_INFRA_CFG_EMI_CTL_TOP_EMI_REQ_TOP_ADDR CONN_INFRA_CFG_EMI_CTL_TOP_ADDR
+#define CONN_INFRA_CFG_EMI_CTL_TOP_EMI_REQ_TOP_MASK 0x00000001
+#define CONN_INFRA_CFG_EMI_CTL_TOP_EMI_REQ_TOP_SHFT 0
+
+#define CONN_INFRA_CFG_EMI_CTL_GPS_EMI_REQ_GPS_ADDR CONN_INFRA_CFG_EMI_CTL_GPS_ADDR
+#define CONN_INFRA_CFG_EMI_CTL_GPS_EMI_REQ_GPS_MASK 0x00000001
+#define CONN_INFRA_CFG_EMI_CTL_GPS_EMI_REQ_GPS_SHFT 0
+
+#define CONN_INFRA_CFG_CONN_INFRA_CONN2GPS_SLP_CTRL_CFG_CONN2GPS_GALS_RX_SLP_PROT_SW_EN_ADDR \
+ CONN_INFRA_CFG_CONN_INFRA_CONN2GPS_SLP_CTRL_ADDR
+#define CONN_INFRA_CFG_CONN_INFRA_CONN2GPS_SLP_CTRL_CFG_CONN2GPS_GALS_RX_SLP_PROT_SW_EN_MASK 0x00000010
+#define CONN_INFRA_CFG_CONN_INFRA_CONN2GPS_SLP_CTRL_CFG_CONN2GPS_GALS_RX_SLP_PROT_SW_EN_SHFT 4
+#define CONN_INFRA_CFG_CONN_INFRA_CONN2GPS_SLP_CTRL_CFG_CONN2GPS_GALS_TX_SLP_PROT_SW_EN_ADDR \
+ CONN_INFRA_CFG_CONN_INFRA_CONN2GPS_SLP_CTRL_ADDR
+#define CONN_INFRA_CFG_CONN_INFRA_CONN2GPS_SLP_CTRL_CFG_CONN2GPS_GALS_TX_SLP_PROT_SW_EN_MASK 0x00000001
+#define CONN_INFRA_CFG_CONN_INFRA_CONN2GPS_SLP_CTRL_CFG_CONN2GPS_GALS_TX_SLP_PROT_SW_EN_SHFT 0
+
+#define CONN_INFRA_CFG_CONN_INFRA_GPS2CONN_SLP_CTRL_CFG_GPS2CONN_GALS_RX_SLP_PROT_SW_EN_ADDR \
+ CONN_INFRA_CFG_CONN_INFRA_GPS2CONN_SLP_CTRL_ADDR
+#define CONN_INFRA_CFG_CONN_INFRA_GPS2CONN_SLP_CTRL_CFG_GPS2CONN_GALS_RX_SLP_PROT_SW_EN_MASK 0x00000010
+#define CONN_INFRA_CFG_CONN_INFRA_GPS2CONN_SLP_CTRL_CFG_GPS2CONN_GALS_RX_SLP_PROT_SW_EN_SHFT 4
+#define CONN_INFRA_CFG_CONN_INFRA_GPS2CONN_SLP_CTRL_CFG_GPS2CONN_GALS_TX_SLP_PROT_SW_EN_ADDR \
+ CONN_INFRA_CFG_CONN_INFRA_GPS2CONN_SLP_CTRL_ADDR
+#define CONN_INFRA_CFG_CONN_INFRA_GPS2CONN_SLP_CTRL_CFG_GPS2CONN_GALS_TX_SLP_PROT_SW_EN_MASK 0x00000001
+#define CONN_INFRA_CFG_CONN_INFRA_GPS2CONN_SLP_CTRL_CFG_GPS2CONN_GALS_TX_SLP_PROT_SW_EN_SHFT 0
+
+#endif /* __CONN_INFRA_CFG_REGS_H__ */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/conn_infra/conn_infra_rgu.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/conn_infra/conn_infra_rgu.h
new file mode 100644
index 0000000..cc0225d
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/conn_infra/conn_infra_rgu.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+#ifndef __CONN_INFRA_RGU_REGS_H__
+#define __CONN_INFRA_RGU_REGS_H__
+
+#define CONN_INFRA_RGU_BASE 0x18000000
+
+#define CONN_INFRA_RGU_BGFYS_ON_TOP_PWR_CTL_ADDR (CONN_INFRA_RGU_BASE + 0x0020)
+#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_ADDR (CONN_INFRA_RGU_BASE + 0x0414)
+
+
+#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_AN_BGFSYS_ON_TOP_PWR_ACK_S_ADDR \
+ CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_ADDR
+#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_AN_BGFSYS_ON_TOP_PWR_ACK_S_MASK 0x02000000
+#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_AN_BGFSYS_ON_TOP_PWR_ACK_S_SHFT 25
+#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_BGFSYS_ON_TOP_PWR_ACK_ADDR CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_ADDR
+#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_BGFSYS_ON_TOP_PWR_ACK_MASK 0x01000000
+#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_ACK_ST_BGFSYS_ON_TOP_PWR_ACK_SHFT 24
+
+#endif /* __CONN_INFRA_RGU_REGS_H__ */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/conn_infra/conn_rf_spi_mst_reg.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/conn_infra/conn_rf_spi_mst_reg.h
new file mode 100644
index 0000000..849e60a
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/conn_infra/conn_rf_spi_mst_reg.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+#ifndef __CONN_RF_SPI_MST_REG_REGS_H__
+#define __CONN_RF_SPI_MST_REG_REGS_H__
+
+#define CONN_RF_SPI_MST_REG_BASE 0x18004000
+
+#define CONN_RF_SPI_MST_ADDR_SPI_STA_ADDR (CONN_RF_SPI_MST_REG_BASE + 0x0000)
+#define CONN_RF_SPI_MST_ADDR_FM_CTRL_ADDR (CONN_RF_SPI_MST_REG_BASE + 0x000C)
+#define CONN_RF_SPI_MST_ADDR_SPI_FM_ADDR_ADDR (CONN_RF_SPI_MST_REG_BASE + 0x0030)
+#define CONN_RF_SPI_MST_ADDR_SPI_FM_WDAT_ADDR (CONN_RF_SPI_MST_REG_BASE + 0x0034)
+#define CONN_RF_SPI_MST_ADDR_SPI_FM_RDAT_ADDR (CONN_RF_SPI_MST_REG_BASE + 0x0038)
+#define CONN_RF_SPI_MST_ADDR_SPI_GPS_GPS_ADDR_ADDR (CONN_RF_SPI_MST_REG_BASE + 0x0210)
+#define CONN_RF_SPI_MST_ADDR_SPI_GPS_GPS_WDAT_ADDR (CONN_RF_SPI_MST_REG_BASE + 0x0214)
+#define CONN_RF_SPI_MST_ADDR_SPI_GPS_GPS_RDAT_ADDR (CONN_RF_SPI_MST_REG_BASE + 0x0218)
+
+
+#define CONN_RF_SPI_MST_REG_SPI_STA_FM_BUSY_ADDR CONN_RF_SPI_MST_ADDR_SPI_STA_ADDR
+#define CONN_RF_SPI_MST_REG_SPI_STA_FM_BUSY_MASK 0x00000008
+#define CONN_RF_SPI_MST_REG_SPI_STA_FM_BUSY_SHFT 3
+
+#define CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_EN_ADDR CONN_RF_SPI_MST_ADDR_FM_CTRL_ADDR
+#define CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_EN_MASK 0x00008000
+#define CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_EN_SHFT 15
+#define CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_CNT_ADDR CONN_RF_SPI_MST_ADDR_FM_CTRL_ADDR
+#define CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_CNT_MASK 0x000000FF
+#define CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_CNT_SHFT 0
+
+#endif /* __CONN_RF_SPI_MST_REG_REGS_H__ */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/conn_infra/conn_semaphore.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/conn_infra/conn_semaphore.h
new file mode 100644
index 0000000..7b80746
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/conn_infra/conn_semaphore.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+#ifndef __CONN_SEMAPHORE_REGS_H__
+#define __CONN_SEMAPHORE_REGS_H__
+
+#define CONN_SEMAPHORE_BASE 0x18070000
+
+#define CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_STA_ADDR (CONN_SEMAPHORE_BASE + 0x3014)
+#define CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_STA_ADDR (CONN_SEMAPHORE_BASE + 0x302C)
+#define CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_REL_ADDR (CONN_SEMAPHORE_BASE + 0x3214)
+#define CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_REL_ADDR (CONN_SEMAPHORE_BASE + 0x322C)
+
+
+#define CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_STA_CONN_SEMA05_M3_OWN_STA_ADDR CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_STA_ADDR
+#define CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_STA_CONN_SEMA05_M3_OWN_STA_MASK 0x00000003
+#define CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_STA_CONN_SEMA05_M3_OWN_STA_SHFT 0
+
+#define CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_STA_CONN_SEMA11_M3_OWN_STA_ADDR CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_STA_ADDR
+#define CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_STA_CONN_SEMA11_M3_OWN_STA_MASK 0x00000003
+#define CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_STA_CONN_SEMA11_M3_OWN_STA_SHFT 0
+
+#define CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_REL_CONN_SEMA05_M3_OWN_REL_ADDR CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_REL_ADDR
+#define CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_REL_CONN_SEMA05_M3_OWN_REL_MASK 0x00000001
+#define CONN_SEMAPHORE_CONN_SEMA05_M3_OWN_REL_CONN_SEMA05_M3_OWN_REL_SHFT 0
+
+#define CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_REL_CONN_SEMA11_M3_OWN_REL_ADDR CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_REL_ADDR
+#define CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_REL_CONN_SEMA11_M3_OWN_REL_MASK 0x00000001
+#define CONN_SEMAPHORE_CONN_SEMA11_M3_OWN_REL_CONN_SEMA11_M3_OWN_REL_SHFT 0
+
+#endif /* __CONN_SEMAPHORE_REGS_H__ */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/conn_infra/conn_wt_slp_ctl_reg.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/conn_infra/conn_wt_slp_ctl_reg.h
new file mode 100644
index 0000000..82d00f0
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/conn_infra/conn_wt_slp_ctl_reg.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+#ifndef __CONN_WT_SLP_CTL_REG_REGS_H__
+#define __CONN_WT_SLP_CTL_REG_REGS_H__
+
+#define CONN_WT_SLP_CTL_REG_BASE 0x18005000
+
+#define CONN_WT_SLP_CTL_ADDR_WB_SLP_TOP_CK_5_ADDR (CONN_WT_SLP_CTL_REG_BASE + 0x0134)
+
+
+#define CONN_WT_SLP_CTL_REG_WB_SLP_TOP_CK_5_WB_SLP_TOP_CK_5_BSY_ADDR CONN_WT_SLP_CTL_ADDR_WB_SLP_TOP_CK_5_ADDR
+#define CONN_WT_SLP_CTL_REG_WB_SLP_TOP_CK_5_WB_SLP_TOP_CK_5_BSY_MASK 0x00000002
+#define CONN_WT_SLP_CTL_REG_WB_SLP_TOP_CK_5_WB_SLP_TOP_CK_5_BSY_SHFT 1
+#define CONN_WT_SLP_CTL_REG_WB_SLP_TOP_CK_5_WB_SLP_TOP_CK_5_ADDR CONN_WT_SLP_CTL_ADDR_WB_SLP_TOP_CK_5_ADDR
+#define CONN_WT_SLP_CTL_REG_WB_SLP_TOP_CK_5_WB_SLP_TOP_CK_5_MASK 0x00000001
+#define CONN_WT_SLP_CTL_REG_WB_SLP_TOP_CK_5_WB_SLP_TOP_CK_5_SHFT 0
+
+#endif /* __CONN_WT_SLP_CTL_REG_REGS_H__ */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/bgf_gps_cfg.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/bgf_gps_cfg.h
new file mode 100644
index 0000000..3106378
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/bgf_gps_cfg.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+#ifndef __BGF_GPS_CFG_REGS_H__
+#define __BGF_GPS_CFG_REGS_H__
+
+#define BGF_GPS_CFG_BASE 0x80021000
+
+#define BGF_GPS_CFG_BGF_IP_VERSION_ADDR (BGF_GPS_CFG_BASE + 0x0010)
+#define BGF_GPS_CFG_BGF_IP_CONFIG_ADDR (BGF_GPS_CFG_BASE + 0x0014)
+
+
+#define BGF_GPS_CFG_BGF_IP_VERSION_BGFSYS_VERSION_ADDR BGF_GPS_CFG_BGF_IP_VERSION_ADDR
+#define BGF_GPS_CFG_BGF_IP_VERSION_BGFSYS_VERSION_MASK 0xFFFFFFFF
+#define BGF_GPS_CFG_BGF_IP_VERSION_BGFSYS_VERSION_SHFT 0
+
+#define BGF_GPS_CFG_BGF_IP_CONFIG_BGFSYS_CONFIG_ADDR BGF_GPS_CFG_BGF_IP_CONFIG_ADDR
+#define BGF_GPS_CFG_BGF_IP_CONFIG_BGFSYS_CONFIG_MASK 0x000000FF
+#define BGF_GPS_CFG_BGF_IP_CONFIG_BGFSYS_CONFIG_SHFT 0
+
+#endif /* __BGF_GPS_CFG_REGS_H__ */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/bgf_gps_dma.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/bgf_gps_dma.h
new file mode 100644
index 0000000..681be81
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/bgf_gps_dma.h
@@ -0,0 +1,195 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+#ifndef __BGF_GPS_DMA_REGS_H__
+#define __BGF_GPS_DMA_REGS_H__
+
+#define BGF_GPS_DMA_BASE 0x80010000
+
+#define BGF_GPS_DMA_DMA1_WPPT_ADDR (BGF_GPS_DMA_BASE + 0x0108)
+#define BGF_GPS_DMA_DMA1_WPTO_ADDR (BGF_GPS_DMA_BASE + 0x010C)
+#define BGF_GPS_DMA_DMA1_COUNT_ADDR (BGF_GPS_DMA_BASE + 0x0110)
+#define BGF_GPS_DMA_DMA1_CON_ADDR (BGF_GPS_DMA_BASE + 0x0114)
+#define BGF_GPS_DMA_DMA1_START_ADDR (BGF_GPS_DMA_BASE + 0x0118)
+#define BGF_GPS_DMA_DMA1_INTSTA_ADDR (BGF_GPS_DMA_BASE + 0x011C)
+#define BGF_GPS_DMA_DMA1_ACKINT_ADDR (BGF_GPS_DMA_BASE + 0x0120)
+#define BGF_GPS_DMA_DMA1_RLCT_ADDR (BGF_GPS_DMA_BASE + 0x0124)
+#define BGF_GPS_DMA_DMA1_PGMADDR_ADDR (BGF_GPS_DMA_BASE + 0x012C)
+#define BGF_GPS_DMA_DMA1_STATE_ADDR (BGF_GPS_DMA_BASE + 0x0148)
+#define BGF_GPS_DMA_DMA2_WPPT_ADDR (BGF_GPS_DMA_BASE + 0x0208)
+#define BGF_GPS_DMA_DMA2_WPTO_ADDR (BGF_GPS_DMA_BASE + 0x020C)
+#define BGF_GPS_DMA_DMA2_COUNT_ADDR (BGF_GPS_DMA_BASE + 0x0210)
+#define BGF_GPS_DMA_DMA2_CON_ADDR (BGF_GPS_DMA_BASE + 0x0214)
+#define BGF_GPS_DMA_DMA2_START_ADDR (BGF_GPS_DMA_BASE + 0x0218)
+#define BGF_GPS_DMA_DMA2_INTSTA_ADDR (BGF_GPS_DMA_BASE + 0x021C)
+#define BGF_GPS_DMA_DMA2_ACKINT_ADDR (BGF_GPS_DMA_BASE + 0x0220)
+#define BGF_GPS_DMA_DMA2_RLCT_ADDR (BGF_GPS_DMA_BASE + 0x0224)
+#define BGF_GPS_DMA_DMA2_PGMADDR_ADDR (BGF_GPS_DMA_BASE + 0x022C)
+#define BGF_GPS_DMA_DMA3_WPPT_ADDR (BGF_GPS_DMA_BASE + 0x0308)
+#define BGF_GPS_DMA_DMA3_WPTO_ADDR (BGF_GPS_DMA_BASE + 0x030C)
+#define BGF_GPS_DMA_DMA3_COUNT_ADDR (BGF_GPS_DMA_BASE + 0x0310)
+#define BGF_GPS_DMA_DMA3_CON_ADDR (BGF_GPS_DMA_BASE + 0x0314)
+#define BGF_GPS_DMA_DMA3_START_ADDR (BGF_GPS_DMA_BASE + 0x0318)
+#define BGF_GPS_DMA_DMA3_INTSTA_ADDR (BGF_GPS_DMA_BASE + 0x031C)
+#define BGF_GPS_DMA_DMA3_ACKINT_ADDR (BGF_GPS_DMA_BASE + 0x0320)
+#define BGF_GPS_DMA_DMA3_RLCT_ADDR (BGF_GPS_DMA_BASE + 0x0324)
+#define BGF_GPS_DMA_DMA3_PGMADDR_ADDR (BGF_GPS_DMA_BASE + 0x032C)
+#define BGF_GPS_DMA_DMA4_WPPT_ADDR (BGF_GPS_DMA_BASE + 0x0408)
+#define BGF_GPS_DMA_DMA4_WPTO_ADDR (BGF_GPS_DMA_BASE + 0x040C)
+#define BGF_GPS_DMA_DMA4_COUNT_ADDR (BGF_GPS_DMA_BASE + 0x0410)
+#define BGF_GPS_DMA_DMA4_CON_ADDR (BGF_GPS_DMA_BASE + 0x0414)
+#define BGF_GPS_DMA_DMA4_START_ADDR (BGF_GPS_DMA_BASE + 0x0418)
+#define BGF_GPS_DMA_DMA4_INTSTA_ADDR (BGF_GPS_DMA_BASE + 0x041C)
+#define BGF_GPS_DMA_DMA4_ACKINT_ADDR (BGF_GPS_DMA_BASE + 0x0420)
+#define BGF_GPS_DMA_DMA4_RLCT_ADDR (BGF_GPS_DMA_BASE + 0x0424)
+#define BGF_GPS_DMA_DMA4_PGMADDR_ADDR (BGF_GPS_DMA_BASE + 0x042C)
+
+
+#define BGF_GPS_DMA_DMA1_WPPT_WPPT_ADDR BGF_GPS_DMA_DMA1_WPPT_ADDR
+#define BGF_GPS_DMA_DMA1_WPPT_WPPT_MASK 0x0000FFFF
+#define BGF_GPS_DMA_DMA1_WPPT_WPPT_SHFT 0
+
+#define BGF_GPS_DMA_DMA1_WPTO_WPTO_ADDR BGF_GPS_DMA_DMA1_WPTO_ADDR
+#define BGF_GPS_DMA_DMA1_WPTO_WPTO_MASK 0xFFFFFFFF
+#define BGF_GPS_DMA_DMA1_WPTO_WPTO_SHFT 0
+
+#define BGF_GPS_DMA_DMA1_COUNT_LEN_ADDR BGF_GPS_DMA_DMA1_COUNT_ADDR
+#define BGF_GPS_DMA_DMA1_COUNT_LEN_MASK 0x0000FFFF
+#define BGF_GPS_DMA_DMA1_COUNT_LEN_SHFT 0
+
+#define BGF_GPS_DMA_DMA1_CON_MAS_ADDR BGF_GPS_DMA_DMA1_CON_ADDR
+#define BGF_GPS_DMA_DMA1_CON_MAS_MASK 0x00300000
+#define BGF_GPS_DMA_DMA1_CON_MAS_SHFT 20
+#define BGF_GPS_DMA_DMA1_CON_W2B_ADDR BGF_GPS_DMA_DMA1_CON_ADDR
+#define BGF_GPS_DMA_DMA1_CON_W2B_MASK 0x00000040
+#define BGF_GPS_DMA_DMA1_CON_W2B_SHFT 6
+#define BGF_GPS_DMA_DMA1_CON_B2W_ADDR BGF_GPS_DMA_DMA1_CON_ADDR
+#define BGF_GPS_DMA_DMA1_CON_B2W_MASK 0x00000020
+#define BGF_GPS_DMA_DMA1_CON_B2W_SHFT 5
+#define BGF_GPS_DMA_DMA1_CON_SIZE_ADDR BGF_GPS_DMA_DMA1_CON_ADDR
+#define BGF_GPS_DMA_DMA1_CON_SIZE_MASK 0x00000003
+#define BGF_GPS_DMA_DMA1_CON_SIZE_SHFT 0
+
+#define BGF_GPS_DMA_DMA1_START_STR_ADDR BGF_GPS_DMA_DMA1_START_ADDR
+#define BGF_GPS_DMA_DMA1_START_STR_MASK 0x00008000
+#define BGF_GPS_DMA_DMA1_START_STR_SHFT 15
+
+#define BGF_GPS_DMA_DMA1_INTSTA_INT_ADDR BGF_GPS_DMA_DMA1_INTSTA_ADDR
+#define BGF_GPS_DMA_DMA1_INTSTA_INT_MASK 0x00008000
+#define BGF_GPS_DMA_DMA1_INTSTA_INT_SHFT 15
+
+#define BGF_GPS_DMA_DMA1_ACKINT_ACK_ADDR BGF_GPS_DMA_DMA1_ACKINT_ADDR
+#define BGF_GPS_DMA_DMA1_ACKINT_ACK_MASK 0x00008000
+#define BGF_GPS_DMA_DMA1_ACKINT_ACK_SHFT 15
+
+#define BGF_GPS_DMA_DMA1_RLCT_RLCT_ADDR BGF_GPS_DMA_DMA1_RLCT_ADDR
+#define BGF_GPS_DMA_DMA1_RLCT_RLCT_MASK 0x0000FFFF
+#define BGF_GPS_DMA_DMA1_RLCT_RLCT_SHFT 0
+
+#define BGF_GPS_DMA_DMA1_PGMADDR_PGMADDR_ADDR BGF_GPS_DMA_DMA1_PGMADDR_ADDR
+#define BGF_GPS_DMA_DMA1_PGMADDR_PGMADDR_MASK 0xFFFFFFFF
+#define BGF_GPS_DMA_DMA1_PGMADDR_PGMADDR_SHFT 0
+
+#define BGF_GPS_DMA_DMA1_STATE_STATE_ADDR BGF_GPS_DMA_DMA1_STATE_ADDR
+#define BGF_GPS_DMA_DMA1_STATE_STATE_MASK 0x0000007F
+#define BGF_GPS_DMA_DMA1_STATE_STATE_SHFT 0
+
+#define BGF_GPS_DMA_DMA2_WPPT_WPPT_ADDR BGF_GPS_DMA_DMA2_WPPT_ADDR
+#define BGF_GPS_DMA_DMA2_WPPT_WPPT_MASK 0x0000FFFF
+#define BGF_GPS_DMA_DMA2_WPPT_WPPT_SHFT 0
+
+#define BGF_GPS_DMA_DMA2_WPTO_WPTO_ADDR BGF_GPS_DMA_DMA2_WPTO_ADDR
+#define BGF_GPS_DMA_DMA2_WPTO_WPTO_MASK 0xFFFFFFFF
+#define BGF_GPS_DMA_DMA2_WPTO_WPTO_SHFT 0
+
+#define BGF_GPS_DMA_DMA2_COUNT_LEN_ADDR BGF_GPS_DMA_DMA2_COUNT_ADDR
+#define BGF_GPS_DMA_DMA2_COUNT_LEN_MASK 0x0000FFFF
+#define BGF_GPS_DMA_DMA2_COUNT_LEN_SHFT 0
+
+#define BGF_GPS_DMA_DMA2_START_STR_ADDR BGF_GPS_DMA_DMA2_START_ADDR
+#define BGF_GPS_DMA_DMA2_START_STR_MASK 0x00008000
+#define BGF_GPS_DMA_DMA2_START_STR_SHFT 15
+
+#define BGF_GPS_DMA_DMA2_INTSTA_INT_ADDR BGF_GPS_DMA_DMA2_INTSTA_ADDR
+#define BGF_GPS_DMA_DMA2_INTSTA_INT_MASK 0x00008000
+#define BGF_GPS_DMA_DMA2_INTSTA_INT_SHFT 15
+
+#define BGF_GPS_DMA_DMA2_ACKINT_ACK_ADDR BGF_GPS_DMA_DMA2_ACKINT_ADDR
+#define BGF_GPS_DMA_DMA2_ACKINT_ACK_MASK 0x00008000
+#define BGF_GPS_DMA_DMA2_ACKINT_ACK_SHFT 15
+
+#define BGF_GPS_DMA_DMA2_RLCT_RLCT_ADDR BGF_GPS_DMA_DMA2_RLCT_ADDR
+#define BGF_GPS_DMA_DMA2_RLCT_RLCT_MASK 0x0000FFFF
+#define BGF_GPS_DMA_DMA2_RLCT_RLCT_SHFT 0
+
+#define BGF_GPS_DMA_DMA2_PGMADDR_PGMADDR_ADDR BGF_GPS_DMA_DMA2_PGMADDR_ADDR
+#define BGF_GPS_DMA_DMA2_PGMADDR_PGMADDR_MASK 0xFFFFFFFF
+#define BGF_GPS_DMA_DMA2_PGMADDR_PGMADDR_SHFT 0
+
+#define BGF_GPS_DMA_DMA3_WPPT_WPPT_ADDR BGF_GPS_DMA_DMA3_WPPT_ADDR
+#define BGF_GPS_DMA_DMA3_WPPT_WPPT_MASK 0x0000FFFF
+#define BGF_GPS_DMA_DMA3_WPPT_WPPT_SHFT 0
+
+#define BGF_GPS_DMA_DMA3_WPTO_WPTO_ADDR BGF_GPS_DMA_DMA3_WPTO_ADDR
+#define BGF_GPS_DMA_DMA3_WPTO_WPTO_MASK 0xFFFFFFFF
+#define BGF_GPS_DMA_DMA3_WPTO_WPTO_SHFT 0
+
+#define BGF_GPS_DMA_DMA3_COUNT_LEN_ADDR BGF_GPS_DMA_DMA3_COUNT_ADDR
+#define BGF_GPS_DMA_DMA3_COUNT_LEN_MASK 0x0000FFFF
+#define BGF_GPS_DMA_DMA3_COUNT_LEN_SHFT 0
+
+#define BGF_GPS_DMA_DMA3_START_STR_ADDR BGF_GPS_DMA_DMA3_START_ADDR
+#define BGF_GPS_DMA_DMA3_START_STR_MASK 0x00008000
+#define BGF_GPS_DMA_DMA3_START_STR_SHFT 15
+
+#define BGF_GPS_DMA_DMA3_INTSTA_INT_ADDR BGF_GPS_DMA_DMA3_INTSTA_ADDR
+#define BGF_GPS_DMA_DMA3_INTSTA_INT_MASK 0x00008000
+#define BGF_GPS_DMA_DMA3_INTSTA_INT_SHFT 15
+
+#define BGF_GPS_DMA_DMA3_ACKINT_ACK_ADDR BGF_GPS_DMA_DMA3_ACKINT_ADDR
+#define BGF_GPS_DMA_DMA3_ACKINT_ACK_MASK 0x00008000
+#define BGF_GPS_DMA_DMA3_ACKINT_ACK_SHFT 15
+
+#define BGF_GPS_DMA_DMA3_RLCT_RLCT_ADDR BGF_GPS_DMA_DMA3_RLCT_ADDR
+#define BGF_GPS_DMA_DMA3_RLCT_RLCT_MASK 0x0000FFFF
+#define BGF_GPS_DMA_DMA3_RLCT_RLCT_SHFT 0
+
+#define BGF_GPS_DMA_DMA3_PGMADDR_PGMADDR_ADDR BGF_GPS_DMA_DMA3_PGMADDR_ADDR
+#define BGF_GPS_DMA_DMA3_PGMADDR_PGMADDR_MASK 0xFFFFFFFF
+#define BGF_GPS_DMA_DMA3_PGMADDR_PGMADDR_SHFT 0
+
+#define BGF_GPS_DMA_DMA4_WPPT_WPPT_ADDR BGF_GPS_DMA_DMA4_WPPT_ADDR
+#define BGF_GPS_DMA_DMA4_WPPT_WPPT_MASK 0x0000FFFF
+#define BGF_GPS_DMA_DMA4_WPPT_WPPT_SHFT 0
+
+#define BGF_GPS_DMA_DMA4_WPTO_WPTO_ADDR BGF_GPS_DMA_DMA4_WPTO_ADDR
+#define BGF_GPS_DMA_DMA4_WPTO_WPTO_MASK 0xFFFFFFFF
+#define BGF_GPS_DMA_DMA4_WPTO_WPTO_SHFT 0
+
+#define BGF_GPS_DMA_DMA4_COUNT_LEN_ADDR BGF_GPS_DMA_DMA4_COUNT_ADDR
+#define BGF_GPS_DMA_DMA4_COUNT_LEN_MASK 0x0000FFFF
+#define BGF_GPS_DMA_DMA4_COUNT_LEN_SHFT 0
+
+#define BGF_GPS_DMA_DMA4_START_STR_ADDR BGF_GPS_DMA_DMA4_START_ADDR
+#define BGF_GPS_DMA_DMA4_START_STR_MASK 0x00008000
+#define BGF_GPS_DMA_DMA4_START_STR_SHFT 15
+
+#define BGF_GPS_DMA_DMA4_INTSTA_INT_ADDR BGF_GPS_DMA_DMA4_INTSTA_ADDR
+#define BGF_GPS_DMA_DMA4_INTSTA_INT_MASK 0x00008000
+#define BGF_GPS_DMA_DMA4_INTSTA_INT_SHFT 15
+
+#define BGF_GPS_DMA_DMA4_ACKINT_ACK_ADDR BGF_GPS_DMA_DMA4_ACKINT_ADDR
+#define BGF_GPS_DMA_DMA4_ACKINT_ACK_MASK 0x00008000
+#define BGF_GPS_DMA_DMA4_ACKINT_ACK_SHFT 15
+
+#define BGF_GPS_DMA_DMA4_RLCT_RLCT_ADDR BGF_GPS_DMA_DMA4_RLCT_ADDR
+#define BGF_GPS_DMA_DMA4_RLCT_RLCT_MASK 0x0000FFFF
+#define BGF_GPS_DMA_DMA4_RLCT_RLCT_SHFT 0
+
+#define BGF_GPS_DMA_DMA4_PGMADDR_PGMADDR_ADDR BGF_GPS_DMA_DMA4_PGMADDR_ADDR
+#define BGF_GPS_DMA_DMA4_PGMADDR_PGMADDR_MASK 0xFFFFFFFF
+#define BGF_GPS_DMA_DMA4_PGMADDR_PGMADDR_SHFT 0
+
+#endif /* __BGF_GPS_DMA_REGS_H__ */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_aon_top.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_aon_top.h
new file mode 100644
index 0000000..ce7b4ce
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_aon_top.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+#ifndef __GPS_AON_TOP_REGS_H__
+#define __GPS_AON_TOP_REGS_H__
+
+#define GPS_AON_TOP_BASE 0x80073000
+
+#define GPS_AON_TOP_DSLEEP_CTL_ADDR (GPS_AON_TOP_BASE + 0x0108)
+#define GPS_AON_TOP_WAKEUP_CTL_ADDR (GPS_AON_TOP_BASE + 0x0110)
+#define GPS_AON_TOP_TCXO_MS_H_ADDR (GPS_AON_TOP_BASE + 0x0114)
+#define GPS_AON_TOP_TCXO_MS_L_ADDR (GPS_AON_TOP_BASE + 0x0118)
+
+
+#define GPS_AON_TOP_DSLEEP_CTL_FORCE_OSC_EN_ON_ADDR GPS_AON_TOP_DSLEEP_CTL_ADDR
+#define GPS_AON_TOP_DSLEEP_CTL_FORCE_OSC_EN_ON_MASK 0x00000008
+#define GPS_AON_TOP_DSLEEP_CTL_FORCE_OSC_EN_ON_SHFT 3
+#define GPS_AON_TOP_DSLEEP_CTL_GPS_PWR_STAT_ADDR GPS_AON_TOP_DSLEEP_CTL_ADDR
+#define GPS_AON_TOP_DSLEEP_CTL_GPS_PWR_STAT_MASK 0x00000003
+#define GPS_AON_TOP_DSLEEP_CTL_GPS_PWR_STAT_SHFT 0
+
+#endif /* __GPS_AON_TOP_REGS_H__ */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_cfg_on.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_cfg_on.h
new file mode 100644
index 0000000..2dd8ce5
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_cfg_on.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+#ifndef __GPS_CFG_ON_REGS_H__
+#define __GPS_CFG_ON_REGS_H__
+
+#define GPS_CFG_ON_BASE 0x80001000
+
+#define GPS_CFG_ON_GPS_L1_SLP_PWR_CTL_ADDR (GPS_CFG_ON_BASE + 0x0020)
+#define GPS_CFG_ON_GPS_L5_SLP_PWR_CTL_ADDR (GPS_CFG_ON_BASE + 0x0024)
+#define GPS_CFG_ON_GPS_CLKGEN1_CTL_ADDR (GPS_CFG_ON_BASE + 0x003C)
+
+
+#define GPS_CFG_ON_GPS_L1_SLP_PWR_CTL_GPS_L1_SLP_PWR_CTL_CS_ADDR GPS_CFG_ON_GPS_L1_SLP_PWR_CTL_ADDR
+#define GPS_CFG_ON_GPS_L1_SLP_PWR_CTL_GPS_L1_SLP_PWR_CTL_CS_MASK 0x0000000F
+#define GPS_CFG_ON_GPS_L1_SLP_PWR_CTL_GPS_L1_SLP_PWR_CTL_CS_SHFT 0
+
+#define GPS_CFG_ON_GPS_L5_SLP_PWR_CTL_GPS_L5_SLP_PWR_CTL_CS_ADDR GPS_CFG_ON_GPS_L5_SLP_PWR_CTL_ADDR
+#define GPS_CFG_ON_GPS_L5_SLP_PWR_CTL_GPS_L5_SLP_PWR_CTL_CS_MASK 0x0000000F
+#define GPS_CFG_ON_GPS_L5_SLP_PWR_CTL_GPS_L5_SLP_PWR_CTL_CS_SHFT 0
+
+#define GPS_CFG_ON_GPS_CLKGEN1_CTL_CR_GPS_DIGCK_DIV_EN_ADDR GPS_CFG_ON_GPS_CLKGEN1_CTL_ADDR
+#define GPS_CFG_ON_GPS_CLKGEN1_CTL_CR_GPS_DIGCK_DIV_EN_MASK 0x00000010
+#define GPS_CFG_ON_GPS_CLKGEN1_CTL_CR_GPS_DIGCK_DIV_EN_SHFT 4
+
+#endif /* __GPS_CFG_ON_REGS_H__ */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_l5_sys_adrdec.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_l5_sys_adrdec.h
new file mode 100644
index 0000000..ef074d6
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_l5_sys_adrdec.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+#ifndef __GPS_L5_SYS_ADRDEC_REGS_H__
+#define __GPS_L5_SYS_ADRDEC_REGS_H__
+
+#define GPS_L5_SYS_ADRDEC_BASE 0x80080400
+
+
+
+
+#endif /* __GPS_L5_SYS_ADRDEC_REGS_H__ */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_l5_usrt_apb.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_l5_usrt_apb.h
new file mode 100644
index 0000000..2e0a17f
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_l5_usrt_apb.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+#ifndef __GPS_L5_USRT_APB_REGS_H__
+#define __GPS_L5_USRT_APB_REGS_H__
+
+#define GPS_L5_USRT_APB_BASE 0x80083000
+
+#define GPS_L5_USRT_APB_GPS_APB_DATA_ADDR (GPS_L5_USRT_APB_BASE + 0x0000)
+#define GPS_L5_USRT_APB_APB_CTRL_ADDR (GPS_L5_USRT_APB_BASE + 0x0004)
+#define GPS_L5_USRT_APB_APB_INTEN_ADDR (GPS_L5_USRT_APB_BASE + 0x0008)
+#define GPS_L5_USRT_APB_APB_STA_ADDR (GPS_L5_USRT_APB_BASE + 0x000C)
+#define GPS_L5_USRT_APB_MONF_ADDR (GPS_L5_USRT_APB_BASE + 0x0010)
+#define GPS_L5_USRT_APB_MCUB_A2DF_ADDR (GPS_L5_USRT_APB_BASE + 0x0020)
+#define GPS_L5_USRT_APB_MCUB_D2AF_ADDR (GPS_L5_USRT_APB_BASE + 0x0024)
+#define GPS_L5_USRT_APB_MCU_A2D0_ADDR (GPS_L5_USRT_APB_BASE + 0x0030)
+#define GPS_L5_USRT_APB_MCU_A2D1_ADDR (GPS_L5_USRT_APB_BASE + 0x0034)
+#define GPS_L5_USRT_APB_MCU_D2A0_ADDR (GPS_L5_USRT_APB_BASE + 0x0050)
+#define GPS_L5_USRT_APB_MCU_D2A1_ADDR (GPS_L5_USRT_APB_BASE + 0x0054)
+
+
+#define GPS_L5_USRT_APB_APB_CTRL_BYTEN_ADDR GPS_L5_USRT_APB_APB_CTRL_ADDR
+#define GPS_L5_USRT_APB_APB_CTRL_BYTEN_MASK 0x00000008
+#define GPS_L5_USRT_APB_APB_CTRL_BYTEN_SHFT 3
+#define GPS_L5_USRT_APB_APB_CTRL_TX_EN_ADDR GPS_L5_USRT_APB_APB_CTRL_ADDR
+#define GPS_L5_USRT_APB_APB_CTRL_TX_EN_MASK 0x00000002
+#define GPS_L5_USRT_APB_APB_CTRL_TX_EN_SHFT 1
+#define GPS_L5_USRT_APB_APB_CTRL_RX_EN_ADDR GPS_L5_USRT_APB_APB_CTRL_ADDR
+#define GPS_L5_USRT_APB_APB_CTRL_RX_EN_MASK 0x00000001
+#define GPS_L5_USRT_APB_APB_CTRL_RX_EN_SHFT 0
+
+#define GPS_L5_USRT_APB_APB_INTEN_NODAIEN_ADDR GPS_L5_USRT_APB_APB_INTEN_ADDR
+#define GPS_L5_USRT_APB_APB_INTEN_NODAIEN_MASK 0x00000002
+#define GPS_L5_USRT_APB_APB_INTEN_NODAIEN_SHFT 1
+#define GPS_L5_USRT_APB_APB_INTEN_TXIEN_ADDR GPS_L5_USRT_APB_APB_INTEN_ADDR
+#define GPS_L5_USRT_APB_APB_INTEN_TXIEN_MASK 0x00000001
+#define GPS_L5_USRT_APB_APB_INTEN_TXIEN_SHFT 0
+
+#define GPS_L5_USRT_APB_APB_STA_RX_EMP_ADDR GPS_L5_USRT_APB_APB_STA_ADDR
+#define GPS_L5_USRT_APB_APB_STA_RX_EMP_MASK 0x20000000
+#define GPS_L5_USRT_APB_APB_STA_RX_EMP_SHFT 29
+#define GPS_L5_USRT_APB_APB_STA_NODAINTB_ADDR GPS_L5_USRT_APB_APB_STA_ADDR
+#define GPS_L5_USRT_APB_APB_STA_NODAINTB_MASK 0x00000002
+#define GPS_L5_USRT_APB_APB_STA_NODAINTB_SHFT 1
+
+#define GPS_L5_USRT_APB_MCUB_A2DF_A2DF3_ADDR GPS_L5_USRT_APB_MCUB_A2DF_ADDR
+#define GPS_L5_USRT_APB_MCUB_A2DF_A2DF3_MASK 0x00000008
+#define GPS_L5_USRT_APB_MCUB_A2DF_A2DF3_SHFT 3
+
+#define GPS_L5_USRT_APB_MCUB_D2AF_D2AF3_ADDR GPS_L5_USRT_APB_MCUB_D2AF_ADDR
+#define GPS_L5_USRT_APB_MCUB_D2AF_D2AF3_MASK 0x00000008
+#define GPS_L5_USRT_APB_MCUB_D2AF_D2AF3_SHFT 3
+
+#define GPS_L5_USRT_APB_MCU_A2D1_A2D_1_ADDR GPS_L5_USRT_APB_MCU_A2D1_ADDR
+#define GPS_L5_USRT_APB_MCU_A2D1_A2D_1_MASK 0x0000FFFF
+#define GPS_L5_USRT_APB_MCU_A2D1_A2D_1_SHFT 0
+
+#endif /* __GPS_L5_USRT_APB_REGS_H__ */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_rgu_on.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_rgu_on.h
new file mode 100644
index 0000000..8f469f8
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_rgu_on.h
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+#ifndef __GPS_RGU_ON_REGS_H__
+#define __GPS_RGU_ON_REGS_H__
+
+#define GPS_RGU_ON_BASE 0x80000000
+
+#define GPS_RGU_ON_GPS_L1_CR_ADDR (GPS_RGU_ON_BASE + 0x0014)
+#define GPS_RGU_ON_GPS_L1_DSPPRAM_PDN_EN_ADDR (GPS_RGU_ON_BASE + 0x0048)
+#define GPS_RGU_ON_GPS_L1_DSPPRAM_SLP_EN_ADDR (GPS_RGU_ON_BASE + 0x004C)
+#define GPS_RGU_ON_GPS_L1_DSPXRAM_PDN_EN_ADDR (GPS_RGU_ON_BASE + 0x0050)
+#define GPS_RGU_ON_GPS_L1_DSPXRAM_SLP_EN_ADDR (GPS_RGU_ON_BASE + 0x0054)
+#define GPS_RGU_ON_GPS_L1_DSPYRAM_PDN_EN_ADDR (GPS_RGU_ON_BASE + 0x0058)
+#define GPS_RGU_ON_GPS_L1_DSPYRAM_SLP_EN_ADDR (GPS_RGU_ON_BASE + 0x005C)
+#define GPS_RGU_ON_GPS_L1_DLY_CHAIN_CTL_ADDR (GPS_RGU_ON_BASE + 0x0160)
+#define GPS_RGU_ON_GPS_L1_MEM_DLY_CTL_ADDR (GPS_RGU_ON_BASE + 0x0164)
+#define GPS_RGU_ON_GPS_L5_CR_ADDR (GPS_RGU_ON_BASE + 0x0214)
+#define GPS_RGU_ON_GPS_L5_DSPPRAM_PDN_EN_ADDR (GPS_RGU_ON_BASE + 0x0248)
+#define GPS_RGU_ON_GPS_L5_DSPPRAM_SLP_EN_ADDR (GPS_RGU_ON_BASE + 0x024C)
+#define GPS_RGU_ON_GPS_L5_DSPXRAM_PDN_EN_ADDR (GPS_RGU_ON_BASE + 0x0250)
+#define GPS_RGU_ON_GPS_L5_DSPXRAM_SLP_EN_ADDR (GPS_RGU_ON_BASE + 0x0254)
+#define GPS_RGU_ON_GPS_L5_DSPYRAM_PDN_EN_ADDR (GPS_RGU_ON_BASE + 0x0258)
+#define GPS_RGU_ON_GPS_L5_DSPYRAM_SLP_EN_ADDR (GPS_RGU_ON_BASE + 0x025C)
+#define GPS_RGU_ON_GPS_L5_DLY_CHAIN_CTL_ADDR (GPS_RGU_ON_BASE + 0x0360)
+#define GPS_RGU_ON_GPS_L5_MEM_DLY_CTL_ADDR (GPS_RGU_ON_BASE + 0x0364)
+
+
+#define GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_SOFT_RST_B_ADDR GPS_RGU_ON_GPS_L1_CR_ADDR
+#define GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_SOFT_RST_B_MASK 0x00000020
+#define GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_SOFT_RST_B_SHFT 5
+#define GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_ON_ADDR GPS_RGU_ON_GPS_L1_CR_ADDR
+#define GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_ON_MASK 0x00000001
+#define GPS_RGU_ON_GPS_L1_CR_RGU_GPS_L1_ON_SHFT 0
+
+#define GPS_RGU_ON_GPS_L1_DSPPRAM_PDN_EN_RGU_GPS_L1_PRAM_HWCTL_PDN_ADDR GPS_RGU_ON_GPS_L1_DSPPRAM_PDN_EN_ADDR
+#define GPS_RGU_ON_GPS_L1_DSPPRAM_PDN_EN_RGU_GPS_L1_PRAM_HWCTL_PDN_MASK 0x000003FF
+#define GPS_RGU_ON_GPS_L1_DSPPRAM_PDN_EN_RGU_GPS_L1_PRAM_HWCTL_PDN_SHFT 0
+
+#define GPS_RGU_ON_GPS_L1_DSPPRAM_SLP_EN_RGU_GPS_L1_PRAM_HWCTL_SLP_ADDR GPS_RGU_ON_GPS_L1_DSPPRAM_SLP_EN_ADDR
+#define GPS_RGU_ON_GPS_L1_DSPPRAM_SLP_EN_RGU_GPS_L1_PRAM_HWCTL_SLP_MASK 0x000003FF
+#define GPS_RGU_ON_GPS_L1_DSPPRAM_SLP_EN_RGU_GPS_L1_PRAM_HWCTL_SLP_SHFT 0
+
+#define GPS_RGU_ON_GPS_L1_DSPXRAM_PDN_EN_RGU_GPS_L1_XRAM_HWCTL_PDN_ADDR GPS_RGU_ON_GPS_L1_DSPXRAM_PDN_EN_ADDR
+#define GPS_RGU_ON_GPS_L1_DSPXRAM_PDN_EN_RGU_GPS_L1_XRAM_HWCTL_PDN_MASK 0x0000000F
+#define GPS_RGU_ON_GPS_L1_DSPXRAM_PDN_EN_RGU_GPS_L1_XRAM_HWCTL_PDN_SHFT 0
+
+#define GPS_RGU_ON_GPS_L1_DSPXRAM_SLP_EN_RGU_GPS_L1_XRAM_HWCTL_SLP_ADDR GPS_RGU_ON_GPS_L1_DSPXRAM_SLP_EN_ADDR
+#define GPS_RGU_ON_GPS_L1_DSPXRAM_SLP_EN_RGU_GPS_L1_XRAM_HWCTL_SLP_MASK 0x0000000F
+#define GPS_RGU_ON_GPS_L1_DSPXRAM_SLP_EN_RGU_GPS_L1_XRAM_HWCTL_SLP_SHFT 0
+
+#define GPS_RGU_ON_GPS_L1_DSPYRAM_PDN_EN_RGU_GPS_L1_YRAM_HWCTL_PDN_ADDR GPS_RGU_ON_GPS_L1_DSPYRAM_PDN_EN_ADDR
+#define GPS_RGU_ON_GPS_L1_DSPYRAM_PDN_EN_RGU_GPS_L1_YRAM_HWCTL_PDN_MASK 0x000007FF
+#define GPS_RGU_ON_GPS_L1_DSPYRAM_PDN_EN_RGU_GPS_L1_YRAM_HWCTL_PDN_SHFT 0
+
+#define GPS_RGU_ON_GPS_L1_DSPYRAM_SLP_EN_RGU_GPS_L1_YRAM_HWCTL_SLP_ADDR GPS_RGU_ON_GPS_L1_DSPYRAM_SLP_EN_ADDR
+#define GPS_RGU_ON_GPS_L1_DSPYRAM_SLP_EN_RGU_GPS_L1_YRAM_HWCTL_SLP_MASK 0x000007FF
+#define GPS_RGU_ON_GPS_L1_DSPYRAM_SLP_EN_RGU_GPS_L1_YRAM_HWCTL_SLP_SHFT 0
+
+#define GPS_RGU_ON_GPS_L1_DLY_CHAIN_CTL_RGU_GPS_L1_MEM_PDN_DELAY_DUMMY_NUM_ADDR GPS_RGU_ON_GPS_L1_DLY_CHAIN_CTL_ADDR
+#define GPS_RGU_ON_GPS_L1_DLY_CHAIN_CTL_RGU_GPS_L1_MEM_PDN_DELAY_DUMMY_NUM_MASK 0x000F0000
+#define GPS_RGU_ON_GPS_L1_DLY_CHAIN_CTL_RGU_GPS_L1_MEM_PDN_DELAY_DUMMY_NUM_SHFT 16
+
+#define GPS_RGU_ON_GPS_L1_MEM_DLY_CTL_RGU_GPSSYS_L1_MEM_ADJ_DLY_EN_ADDR GPS_RGU_ON_GPS_L1_MEM_DLY_CTL_ADDR
+#define GPS_RGU_ON_GPS_L1_MEM_DLY_CTL_RGU_GPSSYS_L1_MEM_ADJ_DLY_EN_MASK 0x80000000
+#define GPS_RGU_ON_GPS_L1_MEM_DLY_CTL_RGU_GPSSYS_L1_MEM_ADJ_DLY_EN_SHFT 31
+
+#define GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_SOFT_RST_B_ADDR GPS_RGU_ON_GPS_L5_CR_ADDR
+#define GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_SOFT_RST_B_MASK 0x00000020
+#define GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_SOFT_RST_B_SHFT 5
+#define GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_ON_ADDR GPS_RGU_ON_GPS_L5_CR_ADDR
+#define GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_ON_MASK 0x00000001
+#define GPS_RGU_ON_GPS_L5_CR_RGU_GPS_L5_ON_SHFT 0
+
+#define GPS_RGU_ON_GPS_L5_DSPPRAM_PDN_EN_RGU_GPS_L5_PRAM_HWCTL_PDN_ADDR GPS_RGU_ON_GPS_L5_DSPPRAM_PDN_EN_ADDR
+#define GPS_RGU_ON_GPS_L5_DSPPRAM_PDN_EN_RGU_GPS_L5_PRAM_HWCTL_PDN_MASK 0x000003FF
+#define GPS_RGU_ON_GPS_L5_DSPPRAM_PDN_EN_RGU_GPS_L5_PRAM_HWCTL_PDN_SHFT 0
+
+#define GPS_RGU_ON_GPS_L5_DSPPRAM_SLP_EN_RGU_GPS_L5_PRAM_HWCTL_SLP_ADDR GPS_RGU_ON_GPS_L5_DSPPRAM_SLP_EN_ADDR
+#define GPS_RGU_ON_GPS_L5_DSPPRAM_SLP_EN_RGU_GPS_L5_PRAM_HWCTL_SLP_MASK 0x000003FF
+#define GPS_RGU_ON_GPS_L5_DSPPRAM_SLP_EN_RGU_GPS_L5_PRAM_HWCTL_SLP_SHFT 0
+
+#define GPS_RGU_ON_GPS_L5_DSPXRAM_PDN_EN_RGU_GPS_L5_XRAM_HWCTL_PDN_ADDR GPS_RGU_ON_GPS_L5_DSPXRAM_PDN_EN_ADDR
+#define GPS_RGU_ON_GPS_L5_DSPXRAM_PDN_EN_RGU_GPS_L5_XRAM_HWCTL_PDN_MASK 0x0000000F
+#define GPS_RGU_ON_GPS_L5_DSPXRAM_PDN_EN_RGU_GPS_L5_XRAM_HWCTL_PDN_SHFT 0
+
+#define GPS_RGU_ON_GPS_L5_DSPXRAM_SLP_EN_RGU_GPS_L5_XRAM_HWCTL_SLP_ADDR GPS_RGU_ON_GPS_L5_DSPXRAM_SLP_EN_ADDR
+#define GPS_RGU_ON_GPS_L5_DSPXRAM_SLP_EN_RGU_GPS_L5_XRAM_HWCTL_SLP_MASK 0x0000000F
+#define GPS_RGU_ON_GPS_L5_DSPXRAM_SLP_EN_RGU_GPS_L5_XRAM_HWCTL_SLP_SHFT 0
+
+#define GPS_RGU_ON_GPS_L5_DSPYRAM_PDN_EN_RGU_GPS_L5_YRAM_HWCTL_PDN_ADDR GPS_RGU_ON_GPS_L5_DSPYRAM_PDN_EN_ADDR
+#define GPS_RGU_ON_GPS_L5_DSPYRAM_PDN_EN_RGU_GPS_L5_YRAM_HWCTL_PDN_MASK 0x000003FF
+#define GPS_RGU_ON_GPS_L5_DSPYRAM_PDN_EN_RGU_GPS_L5_YRAM_HWCTL_PDN_SHFT 0
+
+#define GPS_RGU_ON_GPS_L5_DSPYRAM_SLP_EN_RGU_GPS_L5_YRAM_HWCTL_SLP_ADDR GPS_RGU_ON_GPS_L5_DSPYRAM_SLP_EN_ADDR
+#define GPS_RGU_ON_GPS_L5_DSPYRAM_SLP_EN_RGU_GPS_L5_YRAM_HWCTL_SLP_MASK 0x000003FF
+#define GPS_RGU_ON_GPS_L5_DSPYRAM_SLP_EN_RGU_GPS_L5_YRAM_HWCTL_SLP_SHFT 0
+
+#define GPS_RGU_ON_GPS_L5_DLY_CHAIN_CTL_RGU_GPS_L5_MEM_PDN_DELAY_DUMMY_NUM_ADDR GPS_RGU_ON_GPS_L5_DLY_CHAIN_CTL_ADDR
+#define GPS_RGU_ON_GPS_L5_DLY_CHAIN_CTL_RGU_GPS_L5_MEM_PDN_DELAY_DUMMY_NUM_MASK 0x000F0000
+#define GPS_RGU_ON_GPS_L5_DLY_CHAIN_CTL_RGU_GPS_L5_MEM_PDN_DELAY_DUMMY_NUM_SHFT 16
+
+#define GPS_RGU_ON_GPS_L5_MEM_DLY_CTL_RGU_GPSSYS_L5_MEM_ADJ_DLY_EN_ADDR GPS_RGU_ON_GPS_L5_MEM_DLY_CTL_ADDR
+#define GPS_RGU_ON_GPS_L5_MEM_DLY_CTL_RGU_GPSSYS_L5_MEM_ADJ_DLY_EN_MASK 0x80000000
+#define GPS_RGU_ON_GPS_L5_MEM_DLY_CTL_RGU_GPSSYS_L5_MEM_ADJ_DLY_EN_SHFT 31
+
+#endif /* __GPS_RGU_ON_REGS_H__ */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_sys_adrdec.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_sys_adrdec.h
new file mode 100644
index 0000000..5a81b94
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_sys_adrdec.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+#ifndef __GPS_SYS_ADRDEC_REGS_H__
+#define __GPS_SYS_ADRDEC_REGS_H__
+
+#define GPS_SYS_ADRDEC_BASE 0x80070400
+
+
+
+
+#endif /* __GPS_SYS_ADRDEC_REGS_H__ */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_usrt_apb.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_usrt_apb.h
new file mode 100644
index 0000000..99153d3
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/coda_gen/gps/gps_usrt_apb.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+#ifndef __GPS_USRT_APB_REGS_H__
+#define __GPS_USRT_APB_REGS_H__
+
+#define GPS_USRT_APB_BASE 0x80073000
+
+#define GPS_USRT_APB_GPS_APB_DATA_ADDR (GPS_USRT_APB_BASE + 0x0000)
+#define GPS_USRT_APB_APB_CTRL_ADDR (GPS_USRT_APB_BASE + 0x0004)
+#define GPS_USRT_APB_APB_INTEN_ADDR (GPS_USRT_APB_BASE + 0x0008)
+#define GPS_USRT_APB_APB_STA_ADDR (GPS_USRT_APB_BASE + 0x000C)
+#define GPS_USRT_APB_MONF_ADDR (GPS_USRT_APB_BASE + 0x0010)
+#define GPS_USRT_APB_MCUB_A2DF_ADDR (GPS_USRT_APB_BASE + 0x0020)
+#define GPS_USRT_APB_MCUB_D2AF_ADDR (GPS_USRT_APB_BASE + 0x0024)
+#define GPS_USRT_APB_MCU_A2D0_ADDR (GPS_USRT_APB_BASE + 0x0030)
+#define GPS_USRT_APB_MCU_A2D1_ADDR (GPS_USRT_APB_BASE + 0x0034)
+#define GPS_USRT_APB_MCU_D2A0_ADDR (GPS_USRT_APB_BASE + 0x0050)
+#define GPS_USRT_APB_MCU_D2A1_ADDR (GPS_USRT_APB_BASE + 0x0054)
+
+
+#define GPS_USRT_APB_APB_CTRL_BYTEN_ADDR GPS_USRT_APB_APB_CTRL_ADDR
+#define GPS_USRT_APB_APB_CTRL_BYTEN_MASK 0x00000008
+#define GPS_USRT_APB_APB_CTRL_BYTEN_SHFT 3
+#define GPS_USRT_APB_APB_CTRL_TX_EN_ADDR GPS_USRT_APB_APB_CTRL_ADDR
+#define GPS_USRT_APB_APB_CTRL_TX_EN_MASK 0x00000002
+#define GPS_USRT_APB_APB_CTRL_TX_EN_SHFT 1
+#define GPS_USRT_APB_APB_CTRL_RX_EN_ADDR GPS_USRT_APB_APB_CTRL_ADDR
+#define GPS_USRT_APB_APB_CTRL_RX_EN_MASK 0x00000001
+#define GPS_USRT_APB_APB_CTRL_RX_EN_SHFT 0
+
+#define GPS_USRT_APB_APB_INTEN_NODAIEN_ADDR GPS_USRT_APB_APB_INTEN_ADDR
+#define GPS_USRT_APB_APB_INTEN_NODAIEN_MASK 0x00000002
+#define GPS_USRT_APB_APB_INTEN_NODAIEN_SHFT 1
+#define GPS_USRT_APB_APB_INTEN_TXIEN_ADDR GPS_USRT_APB_APB_INTEN_ADDR
+#define GPS_USRT_APB_APB_INTEN_TXIEN_MASK 0x00000001
+#define GPS_USRT_APB_APB_INTEN_TXIEN_SHFT 0
+
+#define GPS_USRT_APB_APB_STA_RX_UNDR_ADDR GPS_USRT_APB_APB_STA_ADDR
+#define GPS_USRT_APB_APB_STA_RX_UNDR_MASK 0x80000000
+#define GPS_USRT_APB_APB_STA_RX_UNDR_SHFT 31
+#define GPS_USRT_APB_APB_STA_RX_OVF_ADDR GPS_USRT_APB_APB_STA_ADDR
+#define GPS_USRT_APB_APB_STA_RX_OVF_MASK 0x40000000
+#define GPS_USRT_APB_APB_STA_RX_OVF_SHFT 30
+#define GPS_USRT_APB_APB_STA_RX_EMP_ADDR GPS_USRT_APB_APB_STA_ADDR
+#define GPS_USRT_APB_APB_STA_RX_EMP_MASK 0x20000000
+#define GPS_USRT_APB_APB_STA_RX_EMP_SHFT 29
+#define GPS_USRT_APB_APB_STA_RX_FULL_ADDR GPS_USRT_APB_APB_STA_ADDR
+#define GPS_USRT_APB_APB_STA_RX_FULL_MASK 0x10000000
+#define GPS_USRT_APB_APB_STA_RX_FULL_SHFT 28
+#define GPS_USRT_APB_APB_STA_TX_UNDR_ADDR GPS_USRT_APB_APB_STA_ADDR
+#define GPS_USRT_APB_APB_STA_TX_UNDR_MASK 0x08000000
+#define GPS_USRT_APB_APB_STA_TX_UNDR_SHFT 27
+#define GPS_USRT_APB_APB_STA_TX_OVF_ADDR GPS_USRT_APB_APB_STA_ADDR
+#define GPS_USRT_APB_APB_STA_TX_OVF_MASK 0x04000000
+#define GPS_USRT_APB_APB_STA_TX_OVF_SHFT 26
+#define GPS_USRT_APB_APB_STA_TX_EMP_ADDR GPS_USRT_APB_APB_STA_ADDR
+#define GPS_USRT_APB_APB_STA_TX_EMP_MASK 0x02000000
+#define GPS_USRT_APB_APB_STA_TX_EMP_SHFT 25
+#define GPS_USRT_APB_APB_STA_TX_FULL_ADDR GPS_USRT_APB_APB_STA_ADDR
+#define GPS_USRT_APB_APB_STA_TX_FULL_MASK 0x01000000
+#define GPS_USRT_APB_APB_STA_TX_FULL_SHFT 24
+#define GPS_USRT_APB_APB_STA_TX_ST_ADDR GPS_USRT_APB_APB_STA_ADDR
+#define GPS_USRT_APB_APB_STA_TX_ST_MASK 0x00700000
+#define GPS_USRT_APB_APB_STA_TX_ST_SHFT 20
+#define GPS_USRT_APB_APB_STA_RX_ST_ADDR GPS_USRT_APB_APB_STA_ADDR
+#define GPS_USRT_APB_APB_STA_RX_ST_MASK 0x00070000
+#define GPS_USRT_APB_APB_STA_RX_ST_SHFT 16
+#define GPS_USRT_APB_APB_STA_REGE_ADDR GPS_USRT_APB_APB_STA_ADDR
+#define GPS_USRT_APB_APB_STA_REGE_MASK 0x00000020
+#define GPS_USRT_APB_APB_STA_REGE_SHFT 5
+#define GPS_USRT_APB_APB_STA_URAME_ADDR GPS_USRT_APB_APB_STA_ADDR
+#define GPS_USRT_APB_APB_STA_URAME_MASK 0x00000010
+#define GPS_USRT_APB_APB_STA_URAME_SHFT 4
+#define GPS_USRT_APB_APB_STA_TX_IND_ADDR GPS_USRT_APB_APB_STA_ADDR
+#define GPS_USRT_APB_APB_STA_TX_IND_MASK 0x00000008
+#define GPS_USRT_APB_APB_STA_TX_IND_SHFT 3
+#define GPS_USRT_APB_APB_STA_NODAINTB_ADDR GPS_USRT_APB_APB_STA_ADDR
+#define GPS_USRT_APB_APB_STA_NODAINTB_MASK 0x00000002
+#define GPS_USRT_APB_APB_STA_NODAINTB_SHFT 1
+#define GPS_USRT_APB_APB_STA_TXINTB_ADDR GPS_USRT_APB_APB_STA_ADDR
+#define GPS_USRT_APB_APB_STA_TXINTB_MASK 0x00000001
+#define GPS_USRT_APB_APB_STA_TXINTB_SHFT 0
+
+#define GPS_USRT_APB_MCUB_A2DF_A2DF3_ADDR GPS_USRT_APB_MCUB_A2DF_ADDR
+#define GPS_USRT_APB_MCUB_A2DF_A2DF3_MASK 0x00000008
+#define GPS_USRT_APB_MCUB_A2DF_A2DF3_SHFT 3
+
+#define GPS_USRT_APB_MCUB_D2AF_D2AF3_ADDR GPS_USRT_APB_MCUB_D2AF_ADDR
+#define GPS_USRT_APB_MCUB_D2AF_D2AF3_MASK 0x00000008
+#define GPS_USRT_APB_MCUB_D2AF_D2AF3_SHFT 3
+
+#define GPS_USRT_APB_MCU_A2D1_A2D_1_ADDR GPS_USRT_APB_MCU_A2D1_ADDR
+#define GPS_USRT_APB_MCU_A2D1_A2D_1_MASK 0x0000FFFF
+#define GPS_USRT_APB_MCU_A2D1_A2D_1_SHFT 0
+
+#endif /* __GPS_USRT_APB_REGS_H__ */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/gps_dl_hw_dep_api.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/gps_dl_hw_dep_api.h
new file mode 100644
index 0000000..47ecc7c
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/hw/inc/mt6880/gps_dl_hw_dep_api.h
@@ -0,0 +1,201 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ */
+#ifndef _GPS_DL_HW_DEP_API_H
+#define _GPS_DL_HW_DEP_API_H
+
+#include "conn_infra/conn_infra_cfg.h"
+#include "conn_infra/conn_host_csr_top.h"
+#include "conn_infra/conn_wt_slp_ctl_reg.h"
+
+
+#define GDL_HW_SUPPORT_LIST "SUPPORT:MT6880"
+#define GDL_HW_CONN_INFRA_VER_MT6880 (0x02030100)
+#define GDL_HW_BGF_VER (0x02030100)
+
+#define GDL_HW_CHECK_CONN_INFRA_VER(p_poll_okay, p_poll_ver) \
+ GDL_HW_POLL_ENTRY_VERBOSE(GPS_DL_CONN_INFRA_BUS, \
+ CONN_INFRA_CFG_CONN_HW_VER_RO_CONN_HW_VERSION, \
+ p_poll_okay, p_poll_ver, POLL_DEFAULT, ( \
+ (*p_poll_ver == GDL_HW_CONN_INFRA_VER_MT6880)) \
+ )
+
+#define CONN2GPS_SLP_PROT_RX_ACK_ADDR CONN_INFRA_CFG_GALS_CONN2GPS_SLP_STATUS_ADDR
+#define CONN2GPS_SLP_PROT_RX_ACK_MASK (1UL << 22)
+#define CONN2GPS_SLP_PROT_RX_ACK_SHFT 22
+
+#define CONN2GPS_SLP_PROT_TX_ACK_ADDR CONN_INFRA_CFG_GALS_CONN2GPS_SLP_STATUS_ADDR
+#define CONN2GPS_SLP_PROT_TX_ACK_MASK (1UL << 23)
+#define CONN2GPS_SLP_PROT_TX_ACK_SHFT 23
+
+#define GPS2CONN_SLP_PROT_RX_ACK_ADDR CONN_INFRA_CFG_GALS_GPS2CONN_SLP_STATUS_ADDR
+#define GPS2CONN_SLP_PROT_RX_ACK_MASK (1UL << 22)
+#define GPS2CONN_SLP_PROT_RX_ACK_SHFT 22
+
+#define GPS2CONN_SLP_PROT_TX_ACK_ADDR CONN_INFRA_CFG_GALS_GPS2CONN_SLP_STATUS_ADDR
+#define GPS2CONN_SLP_PROT_TX_ACK_MASK (1UL << 23)
+#define GPS2CONN_SLP_PROT_TX_ACK_SHFT 23
+
+#define GDL_HW_SET_CONN2GPS_SLP_PROT_RX_VAL(val) \
+ GDL_HW_SET_CONN_INFRA_ENTRY( \
+ CONN_INFRA_CFG_CONN_INFRA_CONN2GPS_SLP_CTRL_CFG_CONN2GPS_GALS_RX_SLP_PROT_SW_EN, val)
+
+#define GDL_HW_POLL_CONN2GPS_SLP_PROT_RX_UNTIL_VAL(val, timeout, p_is_okay) \
+ GDL_HW_POLL_CONN_INFRA_ENTRY( \
+ CONN2GPS_SLP_PROT_RX_ACK, \
+ val, timeout, p_is_okay)
+
+
+#define GDL_HW_SET_CONN2GPS_SLP_PROT_TX_VAL(val) \
+ GDL_HW_SET_CONN_INFRA_ENTRY( \
+ CONN_INFRA_CFG_CONN_INFRA_CONN2GPS_SLP_CTRL_CFG_CONN2GPS_GALS_TX_SLP_PROT_SW_EN, val)
+
+#define GDL_HW_POLL_CONN2GPS_SLP_PROT_TX_UNTIL_VAL(val, timeout, p_is_okay) \
+ GDL_HW_POLL_CONN_INFRA_ENTRY( \
+ CONN2GPS_SLP_PROT_TX_ACK, \
+ val, timeout, p_is_okay)
+
+
+#define GDL_HW_SET_GPS2CONN_SLP_PROT_RX_VAL(val) \
+ GDL_HW_SET_CONN_INFRA_ENTRY( \
+ CONN_INFRA_CFG_CONN_INFRA_GPS2CONN_SLP_CTRL_CFG_GPS2CONN_GALS_RX_SLP_PROT_SW_EN, val)
+
+#define GDL_HW_POLL_GPS2CONN_SLP_PROT_RX_UNTIL_VAL(val, timeout, p_is_okay) \
+ GDL_HW_POLL_CONN_INFRA_ENTRY( \
+ GPS2CONN_SLP_PROT_RX_ACK, \
+ val, timeout, p_is_okay)
+
+
+#define GDL_HW_SET_GPS2CONN_SLP_PROT_TX_VAL(val) \
+ GDL_HW_SET_CONN_INFRA_ENTRY( \
+ CONN_INFRA_CFG_CONN_INFRA_GPS2CONN_SLP_CTRL_CFG_GPS2CONN_GALS_TX_SLP_PROT_SW_EN, val)
+
+#define GDL_HW_POLL_GPS2CONN_SLP_PROT_TX_UNTIL_VAL(val, timeout, p_is_okay) \
+ GDL_HW_POLL_CONN_INFRA_ENTRY( \
+ GPS2CONN_SLP_PROT_TX_ACK, \
+ val, timeout, p_is_okay)
+
+
+/* For MT6880, no need to wait */
+#define GDL_HW_MAY_WAIT_CONN_INFRA_SLP_PROT_DISABLE_ACK(p_poll_okay) \
+ do { *p_poll_okay = true; } while(0)
+
+
+/* For MT6880, the dump address list as below */
+#define GDL_HW_DUMP_SLP_RPOT_STATUS() do { \
+ gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS, \
+ CONN_INFRA_CFG_CONN_INFRA_CONN2GPS_SLP_CTRL_ADDR, \
+ BMASK_RW_FORCE_PRINT); \
+ gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS, \
+ CONN_INFRA_CFG_GALS_CONN2GPS_SLP_STATUS_ADDR, \
+ BMASK_RW_FORCE_PRINT); \
+ gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS, \
+ CONN_INFRA_CFG_CONN_INFRA_GPS2CONN_SLP_CTRL_ADDR, \
+ BMASK_RW_FORCE_PRINT); \
+ gps_dl_bus_rd_opt(GPS_DL_CONN_INFRA_BUS, \
+ CONN_INFRA_CFG_GALS_GPS2CONN_SLP_STATUS_ADDR, \
+ BMASK_RW_FORCE_PRINT); \
+} while (0)
+
+/* For MT6880, the address is 0x18000020 */
+#define GDL_HW_SET_CONN_INFRA_BGF_EN(val) do { \
+ unsigned int tmp_val; \
+ tmp_val = GDL_HW_RD_CONN_INFRA_REG(CONN_INFRA_RGU_BGFYS_ON_TOP_PWR_CTL_ADDR); \
+ if (val == 0) \
+ tmp_val = (0x42540000 | (tmp_val & 0xFFFF)) & ~0x80; \
+ else \
+ tmp_val = (0x42540000 | (tmp_val & 0xFFFF)) | 0x80; \
+ GDL_HW_WR_CONN_INFRA_REG(CONN_INFRA_RGU_BGFYS_ON_TOP_PWR_CTL_ADDR, tmp_val); \
+ GDL_HW_RD_CONN_INFRA_REG(CONN_INFRA_RGU_BGFYS_ON_TOP_PWR_CTL_ADDR); \
+} while (0)
+
+#define GDL_HW_SET_GPS_FUNC_EN(val) \
+ GDL_HW_SET_CONN_INFRA_ENTRY(CONN_INFRA_CFG_GPS_PWRCTRL0_GPS_FUNCTION_EN, val)
+
+/* For MT6880, GPS has dedicate entry for top clk control */
+#define GDL_HW_ADIE_TOP_CLK_EN(val, p_poll_okay) do { \
+ GDL_HW_SET_CONN_INFRA_ENTRY( \
+ CONN_WT_SLP_CTL_REG_WB_SLP_TOP_CK_5_WB_SLP_TOP_CK_5, val); \
+ GDL_HW_POLL_CONN_INFRA_ENTRY( \
+ CONN_WT_SLP_CTL_REG_WB_SLP_TOP_CK_5_WB_SLP_TOP_CK_5_BSY, 0, POLL_DEFAULT, p_poll_okay); \
+} while (0)
+
+
+/* For MT6880:
+ * 8: HW TICK H/L, BG tick H/L, TX_END/TX_RD, RX_END/RX_WR
+ * 3: PC, GALMAN CNT, WRHOST CNT
+ */
+#define GPS_DSP_REG_POLL_MAX (11)
+#define GPS_L1_REG_POLL_LIST { \
+ 0x5028, 0x5029, 0x0100, 0x0101, 0x4882, 0x4883, 0x4886, 0x4887, \
+ 0x9FF0, 0x9FF1, 0x9FF2, }
+
+#define GPS_L5_REG_POLL_LIST { \
+ 0x5014, 0x5015, 0x0100, 0x0101, 0x4882, 0x4883, 0x4886, 0x4887, \
+ 0x9FF0, 0x9FF1, 0x9FF2, }
+
+
+/* For MT6880:
+ * 9: PC, GALMAN CNT, WRHOST CNT, DBTT CNT, NEXT CNT, BG TICK H/L, HW TICK H/L
+ * 11: USRT CTL, STA, TX_END/RD/MAX, RX_MAX/END/WR, TX_CNT, RX_CNT, MISC
+ */
+#define GPS_DSP_REG_DBG_POLL_MAX (20)
+#define GPS_L1_REG_DBG_POLL_LIST { \
+ 0x9FF0, 0x9FF1, 0x9FF2, 0x9FF3, 0x9FF4, 0x0100, 0x0101, 0x5028, 0x5029, \
+ 0x4880, 0x4881, 0x4882, 0x4883, 0x4884, 0x4885, 0x4886, 0x4887, 0x4888, 0x4889, 0x488a, }
+
+#define GPS_L5_REG_DBG_POLL_LIST { \
+ 0x9FF0, 0x9FF1, 0x9FF2, 0x9FF3, 0x9FF4, 0x0100, 0x0101, 0x5014, 0x5015, \
+ 0x4880, 0x4881, 0x4882, 0x4883, 0x4884, 0x4885, 0x4886, 0x4887, 0x4888, 0x4889, 0x488a, }
+
+
+#if 0
+#define CONN_RF_SPI_MST_ADDR_SPI_STA_ADDR \
+ CONN_RF_SPI_MST_REG_SPI_STA_ADDR
+
+#define CONN_RF_SPI_MST_ADDR_SPI_GPS_GPS_ADDR_ADDR \
+ CONN_RF_SPI_MST_REG_SPI_GPS_GPS_ADDR_ADDR
+
+#define CONN_RF_SPI_MST_ADDR_SPI_GPS_GPS_WDAT_ADDR \
+ CONN_RF_SPI_MST_REG_SPI_GPS_GPS_WDAT_ADDR
+
+#define CONN_RF_SPI_MST_ADDR_SPI_GPS_GPS_RDAT_ADDR \
+ CONN_RF_SPI_MST_REG_SPI_GPS_GPS_RDAT_ADDR
+
+#define CONN_RF_SPI_MST_ADDR_SPI_FM_ADDR_ADDR \
+ CONN_RF_SPI_MST_REG_SPI_FM_ADDR_ADDR
+
+#define CONN_RF_SPI_MST_ADDR_SPI_FM_WDAT_ADDR \
+ CONN_RF_SPI_MST_REG_SPI_FM_WDAT_ADDR
+
+#define CONN_RF_SPI_MST_ADDR_SPI_FM_RDAT_ADDR \
+ CONN_RF_SPI_MST_REG_SPI_FM_RDAT_ADDR
+#endif
+
+#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_ADDR \
+ CONN_HOST_CSR_TOP_CONN_INFRA_ON_DEBUG_AO_DEBUGSYS_ADDR
+
+#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_ADDR \
+ CONN_HOST_CSR_TOP_CONN_INFRA_ON_DEBUG_CTRL_AO2SYS_OUT_ADDR
+
+#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_ADDR \
+ CONN_HOST_CSR_TOP_CONN_INFRA_ON_DEBUG_AO_DEBUGSYS_ADDR
+
+#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_ADDR \
+ CONN_HOST_CSR_TOP_CONN_INFRA_ON_DEBUG_CTRL_AO2SYS_OUT_ADDR
+
+#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_ADDR \
+ CONN_HOST_CSR_TOP_CONN_INFRA_ON_DEBUG_AO_DEBUGSYS_ADDR
+
+#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_ADDR \
+ CONN_HOST_CSR_TOP_CONN_INFRA_ON_DEBUG_CTRL_AO2SYS_OUT_ADDR
+
+#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS_ADDR \
+ CONN_HOST_CSR_TOP_CONN_INFRA_ON_DEBUG_AO_DEBUGSYS_ADDR
+
+#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT_ADDR \
+ CONN_HOST_CSR_TOP_CONN_INFRA_ON_DEBUG_CTRL_AO2SYS_OUT_ADDR
+
+#endif /* _GPS_DL_HW_DEP_API_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/inc/gps_dl_config.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/inc/gps_dl_config.h
new file mode 100644
index 0000000..d5b4524
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/inc/gps_dl_config.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_CONFIG_H
+#define _GPS_DL_CONFIG_H
+
+enum gps_dl_link_id_enum {
+ GPS_DATA_LINK_ID0 = 0,
+ GPS_DATA_LINK_ID1 = 1,
+ GPS_DATA_LINK_NUM = 2,
+};
+
+#define LINK_ID_IS_VALID(link_id) \
+ (((link_id) >= 0) && ((link_id) < GPS_DATA_LINK_NUM))
+
+#define CHOOSE_BY_LINK_ID(link_id, val_for_id0, val_for_id1, val_for_otherwise) \
+ (!LINK_ID_IS_VALID((link_id)) ? (val_for_otherwise) : ( \
+ (link_id == GPS_DATA_LINK_ID0) ? val_for_id0 : val_for_id1))
+
+#ifdef GPS_DL_HAS_MOCK
+#define GPS_DL_HW_IS_MOCK (1)
+#define GPS_DL_MOCK_HAL (1)
+#else
+#define GPS_DL_HW_IS_MOCK (0)
+#define GPS_DL_MOCK_HAL (0)
+#endif
+
+#define GPS_DL_MOCK_RX_TIMEOUT (0)
+
+#define GPS_DL_ON_LINUX (1)
+#define GPS_DL_ON_CTP (0)
+
+#define GPS_DL_HAS_CTRLD (1)
+#define GPS_DL_NO_USE_IRQ (0)
+#define GPS_DL_USE_THREADED_IRQ (1)
+
+#ifndef GPS_DL_HAS_CONNINFRA_DRV
+#define GPS_DL_HAS_CONNINFRA_DRV (0)
+#endif
+
+#define GPS_DL_HAS_PLAT_DRV (1)
+#define GPS_DL_HAS_PTA (0)
+#define GPS_DL_USE_TIA (1)
+
+#define GPS_DL_IS_MODULE (1)
+
+#define GPS_DL_USE_MTK_SYNC_WRITE (0)
+#define GPS_DL_SET_EMI_MPU_CFG (1)
+#define GPS_DL_GET_RSV_MEM_IN_MODULE (1)
+
+
+#include "gps_dl_log.h"
+
+#endif /* _GPS_DL_CONFIG_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/inc/gps_dl_context.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/inc/gps_dl_context.h
new file mode 100644
index 0000000..402aa01
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/inc/gps_dl_context.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_CONTEXT_H
+#define _GPS_DL_CONTEXT_H
+
+#include "gps_dl_config.h"
+#include "gps_each_link.h"
+#include "gps_dl_isr.h"
+
+#if GPS_DL_ON_LINUX
+#include "gps_each_device.h"
+#include "gps_dl_linux.h"
+#include "gps_dl_ctrld.h"
+#define GPS_DL_TX_BUF_SIZE (8 * 1024)
+#define GPS_DL_RX_BUF_SIZE (8 * 1024)
+#else
+#define GPS_DL_TX_BUF_SIZE (4 * 1024)
+#define GPS_DL_RX_BUF_SIZE (4 * 1024)
+#endif
+
+struct gps_dl_remap_ctx {
+ unsigned int gps_emi_phy_high20;
+};
+
+struct gps_dl_ctx {
+ int major;
+ int minor;
+#if GPS_DL_ON_LINUX
+ struct gps_each_device devices[GPS_DATA_LINK_NUM];
+#endif
+ struct gps_each_link links[GPS_DATA_LINK_NUM];
+ struct gps_each_irq irqs[GPS_DL_IRQ_NUM];
+ struct gps_dl_remap_ctx remap_ctx;
+};
+
+struct gps_dl_remap_ctx *gps_dl_remap_ctx_get(void);
+
+struct gps_dl_runtime_cfg {
+ bool dma_is_1byte_mode;
+ bool dma_is_enabled;
+ bool show_reg_rw_log;
+ bool show_reg_wait_log;
+ bool only_show_wait_done_log;
+ enum gps_dl_log_level_enum log_level;
+ unsigned int log_mod_bitmask;
+ unsigned int log_reg_rw_bitmask;
+};
+
+bool gps_dl_is_1byte_mode(void);
+bool gps_dl_is_dma_enabled(void);
+
+bool gps_dl_show_reg_rw_log(void);
+bool gps_dl_show_reg_wait_log(void);
+bool gps_dl_only_show_wait_done_log(void);
+
+bool gps_dl_set_1byte_mode(bool is_1byte_mode);
+bool gps_dl_set_dma_enabled(bool to_enable);
+
+bool gps_dl_set_show_reg_rw_log(bool on);
+void gps_dl_set_show_reg_wait_log(bool on);
+
+int gps_dl_set_rx_transfer_max(enum gps_dl_link_id_enum link_id, int max);
+int gps_dl_set_tx_transfer_max(enum gps_dl_link_id_enum link_id, int max);
+
+#endif /* _GPS_DL_CONTEXT_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/inc/gps_dl_log.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/inc/gps_dl_log.h
new file mode 100644
index 0000000..b82c94c
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/inc/gps_dl_log.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_LOG_H
+#define _GPS_DL_LOG_H
+
+#include "gps_dl_config.h"
+#if GPS_DL_ON_LINUX
+#include <linux/printk.h>
+#elif GPS_DL_ON_CTP
+#include "gps_dl_ctp_log.h"
+#endif
+
+enum gps_dl_log_level_enum {
+ GPS_DL_LOG_LEVEL_DBG = 1,
+ GPS_DL_LOG_LEVEL_INFO = 3,
+ GPS_DL_LOG_LEVEL_WARN = 5,
+ GPS_DL_LOG_LEVEL_ERR = 7,
+};
+
+enum gps_dl_log_module_enum {
+ GPS_DL_LOG_MOD_DEFAULT = 0,
+ GPS_DL_LOG_MOD_OPEN_CLOSE = 1,
+ GPS_DL_LOG_MOD_READ_WRITE = 2,
+ GPS_DL_LOG_MOD_REG_RW = 3,
+ GPS_DL_LOG_MOD_STATUS = 4,
+ GPS_DL_LOG_MOD_EVENT = 5,
+ GPS_DL_LOG_MOD_INIT = 6,
+
+ GPS_DL_LOG_MOD_MAX = 32
+};
+
+enum gps_dl_log_reg_rw_ctrl_enum {
+ GPS_DL_REG_RW_HOST_CSR_PTA_INIT,
+ GPS_DL_REG_RW_HOST_CSR_GPS_OFF,
+ GPS_DL_REG_RW_EMI_SW_REQ_CTRL,
+ GPS_DL_REG_RW_MCUB_IRQ_HANDLER,
+
+ GPS_DL_REG_RW_MAX = 32
+};
+
+#define GPS_DL_LOG_DEF_SETTING_LEVEL GPS_DL_LOG_LEVEL_INFO
+#define GPS_DL_LOG_DEF_SETTING_MODULES ( \
+ (1UL << GPS_DL_LOG_MOD_DEFAULT) | \
+ (1UL << GPS_DL_LOG_MOD_OPEN_CLOSE) | \
+ (0UL << GPS_DL_LOG_MOD_READ_WRITE) | \
+ (1UL << GPS_DL_LOG_MOD_REG_RW) | \
+ (1UL << GPS_DL_LOG_MOD_STATUS) | \
+ (0UL << GPS_DL_LOG_MOD_EVENT) | \
+ (1UL << GPS_DL_LOG_MOD_INIT) | \
+ 0)
+#define GPS_DL_LOG_REG_RW_BITMASK ( \
+ (0UL << GPS_DL_REG_RW_HOST_CSR_PTA_INIT) |\
+ (0UL << GPS_DL_REG_RW_HOST_CSR_GPS_OFF) |\
+ (0UL << GPS_DL_REG_RW_EMI_SW_REQ_CTRL) |\
+ (0UL << GPS_DL_REG_RW_MCUB_IRQ_HANDLER) |\
+ 0)
+
+enum gps_dl_log_level_enum gps_dl_log_level_get(void);
+void gps_dl_log_level_set(enum gps_dl_log_level_enum level);
+
+unsigned int gps_dl_log_mod_bitmask_get(void);
+void gps_dl_log_mod_bitmask_set(unsigned int bitmask);
+bool gps_dl_log_mod_is_on(enum gps_dl_log_module_enum mod);
+void gps_dl_log_mod_on(enum gps_dl_log_module_enum mod);
+void gps_dl_log_mod_off(enum gps_dl_log_module_enum mod);
+
+bool gps_dl_log_reg_rw_is_on(enum gps_dl_log_reg_rw_ctrl_enum log_reg_rw);
+
+void gps_dl_log_info_show(void);
+
+
+#if GPS_DL_ON_LINUX
+#define __GDL_LOGE(mod, fmt, ...) pr_notice("GDL[E:%d] [%s:%d]: "fmt, \
+ mod, __func__, __LINE__, ##__VA_ARGS__)
+#define __GDL_LOGW(mod, fmt, ...) pr_notice("GDL[W:%d] [%s:%d]: "fmt, \
+ mod, __func__, __LINE__, ##__VA_ARGS__)
+#define __GDL_LOGI(mod, fmt, ...) pr_info("GDL[I:%d] [%s:%d]: "fmt, \
+ mod, __func__, __LINE__, ##__VA_ARGS__)
+#define __GDL_LOGD(mod, fmt, ...) pr_info("GDL[D:%d] [%s:%d]: "fmt, \
+ mod, __func__, __LINE__, ##__VA_ARGS__)
+
+#define __GDL_LOGXE(mod, link_id, fmt, ...) pr_notice("GDL-%d[E:%d] [%s:%d]: "fmt, \
+ link_id, mod, __func__, __LINE__, ##__VA_ARGS__)
+
+#define __GDL_LOGXW(mod, link_id, fmt, ...) pr_notice("GDL-%d[W:%d] [%s:%d]: "fmt, \
+ link_id, mod, __func__, __LINE__, ##__VA_ARGS__)
+
+#define __GDL_LOGXI(mod, link_id, fmt, ...) pr_info("GDL-%d[I:%d] [%s:%d]: "fmt, \
+ link_id, mod, __func__, __LINE__, ##__VA_ARGS__)
+
+#define __GDL_LOGXD(mod, link_id, fmt, ...) pr_info("GDL-%d[D:%d] [%s:%d]: "fmt, \
+ link_id, mod, __func__, __LINE__, ##__VA_ARGS__)
+#endif /* GPS_DL_ON_XX */
+
+
+#define _GDL_LOGE(...) \
+ do { if (gps_dl_log_level_get() <= GPS_DL_LOG_LEVEL_ERR) __GDL_LOGE(__VA_ARGS__); } while (0)
+#define _GDL_LOGW(...) \
+ do { if (gps_dl_log_level_get() <= GPS_DL_LOG_LEVEL_WARN) __GDL_LOGW(__VA_ARGS__); } while (0)
+#define _GDL_LOGI(...) \
+ do { if (gps_dl_log_level_get() <= GPS_DL_LOG_LEVEL_INFO) __GDL_LOGI(__VA_ARGS__); } while (0)
+#define _GDL_LOGD(...) \
+ do { if (gps_dl_log_level_get() <= GPS_DL_LOG_LEVEL_DBG) __GDL_LOGD(__VA_ARGS__); } while (0)
+#define _GDL_LOGXE(...) \
+ do { if (gps_dl_log_level_get() <= GPS_DL_LOG_LEVEL_ERR) __GDL_LOGXE(__VA_ARGS__); } while (0)
+#define _GDL_LOGXW(...) \
+ do { if (gps_dl_log_level_get() <= GPS_DL_LOG_LEVEL_WARN) __GDL_LOGXW(__VA_ARGS__); } while (0)
+#define _GDL_LOGXI(...) \
+ do { if (gps_dl_log_level_get() <= GPS_DL_LOG_LEVEL_INFO) __GDL_LOGXI(__VA_ARGS__); } while (0)
+#define _GDL_LOGXD(...) \
+ do { if (gps_dl_log_level_get() <= GPS_DL_LOG_LEVEL_DBG) __GDL_LOGXD(__VA_ARGS__); } while (0)
+
+
+#define GDL_LOGE2(mod, ...) \
+ do { if (1) \
+ _GDL_LOGE(mod, __VA_ARGS__); } while (0)
+#define GDL_LOGW2(mod, ...) \
+ do { if (1) \
+ _GDL_LOGW(mod, __VA_ARGS__); } while (0)
+#define GDL_LOGI2(mod, ...) \
+ do { if (gps_dl_log_mod_is_on(mod)) \
+ _GDL_LOGI(mod, __VA_ARGS__); } while (0)
+#define GDL_LOGD2(mod, ...) \
+ do { if (gps_dl_log_mod_is_on(mod)) \
+ _GDL_LOGD(mod, __VA_ARGS__); } while (0)
+
+/* Usage:
+ * 1. Bellow macro can be used to output log:
+ * err level: GDL_LOGE, GDL_LOGE_YYY, GDL_LOGXE, GDL_LOGXE_YYY
+ * warn level: GDL_LOGW, GDL_LOGW_YYY, GDL_LOGXW, GDL_LOGXW_YYY
+ * info level: GDL_LOGI, GDL_LOGI_YYY, GDL_LOGXI, GDL_LOGXI_YYY
+ * dbg level: GDL_LOGD, GDL_LOGE_YYY, GDL_LOGXD, GDL_LOGXD_YYY
+ *
+ * 2. _YYY stands for log module(group), the list are:
+ * _ONF for device/link open or close flow
+ * _DRW for devcie/link read or write flow
+ * _RRW for hw register read or write flow
+ * _STA for state machine related flow
+ * _EVT for event processing related flow
+ * _INI for device initialization/deinitializaion flow
+ * if they are used, the log can be easily filtered by keywords like "[E:2]", "[I:5]" and so on
+ * if you don't know which to use, just use: GDL_LOG* or GDL_LOGX*, which have no _YYY subfix
+ *
+ * 3. Log of info and dbg level can be showed seeing log level and module setting meet:
+ * a) log level setting <= INFO or DBG and
+ * b) log module bitmask bit is 1 for the module
+ *
+ * 4. Log of warn and err level is showed only seeing log level:
+ * a) log level setting <= WARN or ERR
+ *
+ * 5. Difference between GDL_LOG* and GDL_LOGX*:
+ * GDL_LOG* can be used like: GDL_LOGD("a = %d", a)
+ * GDL_LOGX* can take a parameters of link_id, like: GDL_LOGXD(link_id, "a = %d", a)
+ */
+#define GDL_LOGE(...) GDL_LOGE2(GPS_DL_LOG_MOD_DEFAULT, __VA_ARGS__)
+#define GDL_LOGW(...) GDL_LOGW2(GPS_DL_LOG_MOD_DEFAULT, __VA_ARGS__)
+#define GDL_LOGI(...) GDL_LOGI2(GPS_DL_LOG_MOD_DEFAULT, __VA_ARGS__)
+#define GDL_LOGD(...) GDL_LOGD2(GPS_DL_LOG_MOD_DEFAULT, __VA_ARGS__)
+
+#define GDL_LOGD_ONF(...) GDL_LOGD2(GPS_DL_LOG_MOD_OPEN_CLOSE, __VA_ARGS__)
+
+#define GDL_LOGI_DRW(...) GDL_LOGI2(GPS_DL_LOG_MOD_READ_WRITE, __VA_ARGS__)
+
+#define GDL_LOGW_RRW(...) GDL_LOGI2(GPS_DL_LOG_MOD_REG_RW, __VA_ARGS__)
+#define GDL_LOGI_RRW(...) GDL_LOGI2(GPS_DL_LOG_MOD_REG_RW, __VA_ARGS__)
+
+#define GDL_LOGE_EVT(...) GDL_LOGE2(GPS_DL_LOG_MOD_EVENT, __VA_ARGS__)
+#define GDL_LOGW_EVT(...) GDL_LOGW2(GPS_DL_LOG_MOD_EVENT, __VA_ARGS__)
+#define GDL_LOGD_EVT(...) GDL_LOGD2(GPS_DL_LOG_MOD_EVENT, __VA_ARGS__)
+
+#define GDL_LOGE_INI(...) GDL_LOGE2(GPS_DL_LOG_MOD_INIT, __VA_ARGS__)
+#define GDL_LOGW_INI(...) GDL_LOGW2(GPS_DL_LOG_MOD_INIT, __VA_ARGS__)
+#define GDL_LOGI_INI(...) GDL_LOGI2(GPS_DL_LOG_MOD_INIT, __VA_ARGS__)
+#define GDL_LOGD_INI(...) GDL_LOGD2(GPS_DL_LOG_MOD_INIT, __VA_ARGS__)
+
+#define GDL_LOGXE2(mod, ...) \
+ do { if (1) \
+ _GDL_LOGXE(mod, __VA_ARGS__); } while (0)
+#define GDL_LOGXW2(mod, ...) \
+ do { if (1) \
+ _GDL_LOGXW(mod, __VA_ARGS__); } while (0)
+#define GDL_LOGXI2(mod, ...) \
+ do { if (gps_dl_log_mod_is_on(mod)) \
+ _GDL_LOGXI(mod, __VA_ARGS__); } while (0)
+#define GDL_LOGXD2(mod, ...) \
+ do { if (gps_dl_log_mod_is_on(mod)) \
+ _GDL_LOGXD(mod, __VA_ARGS__); } while (0)
+
+#define GDL_LOGXE(...) GDL_LOGXE2(GPS_DL_LOG_MOD_DEFAULT, __VA_ARGS__)
+#define GDL_LOGXW(...) GDL_LOGXW2(GPS_DL_LOG_MOD_DEFAULT, __VA_ARGS__)
+#define GDL_LOGXI(...) GDL_LOGXI2(GPS_DL_LOG_MOD_DEFAULT, __VA_ARGS__)
+#define GDL_LOGXD(...) GDL_LOGXD2(GPS_DL_LOG_MOD_DEFAULT, __VA_ARGS__)
+
+#define GDL_LOGXE_ONF(...) GDL_LOGXE2(GPS_DL_LOG_MOD_OPEN_CLOSE, __VA_ARGS__)
+#define GDL_LOGXW_ONF(...) GDL_LOGXW2(GPS_DL_LOG_MOD_OPEN_CLOSE, __VA_ARGS__)
+#define GDL_LOGXI_ONF(...) GDL_LOGXI2(GPS_DL_LOG_MOD_OPEN_CLOSE, __VA_ARGS__)
+#define GDL_LOGXD_ONF(...) GDL_LOGXD2(GPS_DL_LOG_MOD_OPEN_CLOSE, __VA_ARGS__)
+
+#define GDL_LOGXE_DRW(...) GDL_LOGXE2(GPS_DL_LOG_MOD_READ_WRITE, __VA_ARGS__)
+#define GDL_LOGXW_DRW(...) GDL_LOGXW2(GPS_DL_LOG_MOD_READ_WRITE, __VA_ARGS__)
+#define GDL_LOGXI_DRW(...) GDL_LOGXI2(GPS_DL_LOG_MOD_READ_WRITE, __VA_ARGS__)
+#define GDL_LOGXD_DRW(...) GDL_LOGXD2(GPS_DL_LOG_MOD_READ_WRITE, __VA_ARGS__)
+
+#define GDL_LOGXE_STA(...) GDL_LOGXE2(GPS_DL_LOG_MOD_STATUS, __VA_ARGS__)
+#define GDL_LOGXW_STA(...) GDL_LOGXW2(GPS_DL_LOG_MOD_STATUS, __VA_ARGS__)
+#define GDL_LOGXI_STA(...) GDL_LOGXI2(GPS_DL_LOG_MOD_STATUS, __VA_ARGS__)
+
+#define GDL_LOGXW_EVT(...) GDL_LOGXW2(GPS_DL_LOG_MOD_EVENT, __VA_ARGS__)
+#define GDL_LOGXI_EVT(...) GDL_LOGXI2(GPS_DL_LOG_MOD_EVENT, __VA_ARGS__)
+#define GDL_LOGXD_EVT(...) GDL_LOGXD2(GPS_DL_LOG_MOD_EVENT, __VA_ARGS__)
+
+#define GDL_LOGXE_INI(...) GDL_LOGXE2(GPS_DL_LOG_MOD_INIT, __VA_ARGS__)
+#define GDL_LOGXI_INI(...) GDL_LOGXI2(GPS_DL_LOG_MOD_INIT, __VA_ARGS__)
+#define GDL_LOGXD_INI(...) GDL_LOGXD2(GPS_DL_LOG_MOD_INIT, __VA_ARGS__)
+
+
+#define GDL_ASSERT(cond, ret, fmt, ...) \
+ do { if (!(cond)) { \
+ GDL_LOGE("{** GDL_ASSERT: [(%s) = %d] **}: "fmt, \
+ #cond, (cond), ##__VA_ARGS__); \
+ return ret; \
+ } } while (0)
+
+void GDL_VOIDF(void);
+
+#define GDL_ASSERT_RET_OKAY(gdl_ret) \
+ GDL_ASSERT((callee_ret) != GDL_OKAY, GDL_FAIL_ASSERT, "")
+
+#define GDL_ASSERT_RET_NOT_ASSERT(callee_ret, ret_to_caller) \
+ GDL_ASSERT((callee_ret) == GDL_FAIL_ASSERT, ret_to_caller, "")
+
+#define ASSERT_NOT_ZERO(val, ret)\
+ GDL_ASSERT(val != 0, ret, "%s should not be 0!", #val)
+
+#define ASSERT_ZERO(val, ret)\
+ GDL_ASSERT(val == 0, ret, "%s should be 0!", #val)
+
+#define ASSERT_NOT_NULL(ptr, ret)\
+ GDL_ASSERT(ptr != NULL, ret, "null ptr!")
+
+#define ASSERT_LINK_ID(link_id, ret) \
+ GDL_ASSERT(LINK_ID_IS_VALID(link_id), ret, "invalid link_id: %d", link_id)
+
+#endif /* _GPS_DL_LOG_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/inc/gps_each_link.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/inc/gps_each_link.h
new file mode 100644
index 0000000..0876ada
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/inc/gps_each_link.h
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_EACH_LINK_H
+#define _GPS_EACH_LINK_H
+
+#include "gps_dl_config.h"
+
+#if GPS_DL_ON_LINUX
+#include <linux/wait.h>
+#endif
+
+#if GPS_DL_ON_CTP
+#include "gps_dl_ctp_osal.h"
+#endif
+
+#if GPS_DL_HAS_CTRLD
+#include "gps_dl_ctrld.h"
+#endif
+
+#include "gps_dl_subsys_reset.h"
+#include "gps_dl_dma_buf.h"
+
+struct gps_each_link_cfg {
+ int tx_buf_size;
+ int rx_buf_size;
+};
+
+enum gps_each_link_waitable_type {
+ GPS_DL_WAIT_OPEN_CLOSE,
+ GPS_DL_WAIT_WRITE,
+ GPS_DL_WAIT_READ,
+ GPS_DL_WAIT_RESET,
+ GPS_DL_WAIT_NUM
+};
+
+struct gps_each_link_state_list {
+ bool is_ready_to_write;
+ bool is_active;
+ bool to_be_closed;
+ bool is_resetting;
+ bool open_result_okay;
+ bool user_open;
+ bool need_a2z_dump;
+ bool suspend_to_clk_ext;
+};
+
+enum gps_each_link_bool_state {
+ LINK_WRITE_READY,
+ LINK_IS_ACTIVE,
+ LINK_TO_BE_CLOSED,
+ LINK_USER_OPEN,
+ LINK_WAIT_RESET_DONE,
+ LINK_IS_RESETTING,
+ LINK_OPEN_RESULT_OKAY,
+ LINK_NEED_A2Z_DUMP,
+ LINK_SUSPEND_TO_CLK_EXT,
+ BOOL_STATE_NUM
+};
+
+void gps_each_link_set_bool_flag(enum gps_dl_link_id_enum link_id,
+ enum gps_each_link_bool_state name, bool value);
+bool gps_each_link_get_bool_flag(enum gps_dl_link_id_enum link_id,
+ enum gps_each_link_bool_state name);
+
+bool gps_dl_link_is_ready_to_write(enum gps_dl_link_id_enum link_id);
+void gps_dl_link_set_ready_to_write(enum gps_dl_link_id_enum link_id, bool is_ready);
+
+bool gps_each_link_is_active(enum gps_dl_link_id_enum link_id);
+void gps_each_link_set_active(enum gps_dl_link_id_enum link_id, bool is_active);
+
+enum gps_each_link_wait_status {
+ WAITING,
+ OKAY,
+ FAIL,
+ SIGNAL,
+};
+
+struct gps_each_link_waitable {
+#if GPS_DL_ON_LINUX
+ /* TODO: use completion */
+ wait_queue_head_t wq;
+#endif
+ bool fired;
+ bool waiting;
+ enum gps_each_link_wait_status status;
+ enum gps_each_link_waitable_type type;
+};
+
+enum gps_each_link_mutex {
+ GPS_DL_MTX_BIG_LOCK,
+ GPS_DL_MTX_NUM
+};
+
+void gps_each_link_mutex_take(enum gps_dl_link_id_enum link_id, enum gps_each_link_mutex mtx_id);
+void gps_each_link_mutex_give(enum gps_dl_link_id_enum link_id, enum gps_each_link_mutex mtx_id);
+
+enum gps_each_link_spinlock {
+ GPS_DL_SPINLOCK_FOR_LINK_STATE,
+ GPS_DL_SPINLOCK_FOR_DMA_BUF,
+ GPS_DL_SPINLOCK_NUM
+};
+
+void gps_each_link_spin_lock_take(enum gps_dl_link_id_enum link_id, enum gps_each_link_spinlock spin_lock_id);
+void gps_each_link_spin_lock_give(enum gps_dl_link_id_enum link_id, enum gps_each_link_spinlock spin_lock_id);
+
+
+enum gps_each_link_state_enum {
+ LINK_UNINIT,
+ LINK_CLOSED,
+ LINK_OPENING,
+ LINK_OPENED,
+ LINK_CLOSING,
+ LINK_RESETTING, /* Not distinguish EACH_LINK or WHOLE_GPS or WHOLE_CONNSYS */
+ LINK_RESET_DONE,
+ LINK_DISABLED,
+ LINK_SUSPENDING,
+ LINK_SUSPENDED,
+ LINK_RESUMING,
+ LINK_STATE_NUM
+};
+
+#define GPS_EACH_LINK_SID_MAX (0x7FFFFFFE)
+#define GPS_EACH_LINK_SID_NO_CHECK (0xFFFFFFFF)
+struct gps_each_link {
+ struct gps_each_link_cfg cfg;
+ struct gps_each_device *p_device;
+ struct gps_dl_dma_buf tx_dma_buf;
+ struct gps_dl_dma_buf rx_dma_buf;
+ struct gps_each_link_waitable waitables[GPS_DL_WAIT_NUM];
+ struct gps_dl_osal_sleepable_lock mutexes[GPS_DL_MTX_NUM];
+ struct gps_dl_osal_unsleepable_lock spin_locks[GPS_DL_SPINLOCK_NUM];
+ struct gps_each_link_state_list sub_states;
+ enum gps_each_link_state_enum state_for_user;
+ enum gps_each_link_reset_level reset_level;
+ int session_id;
+};
+
+void gps_each_link_mutexes_init(struct gps_each_link *p);
+void gps_each_link_mutexes_deinit(struct gps_each_link *p);
+void gps_each_link_spin_locks_init(struct gps_each_link *p);
+void gps_each_link_spin_locks_deinit(struct gps_each_link *p);
+
+
+struct gps_common_context {
+ struct gps_dl_osal_sleepable_lock big_lock;
+};
+
+/* only ctrld can change it */
+struct gps_dl_ctrl_context {
+ bool gps_reset;
+ bool connsys_reset;
+};
+
+struct gps_each_link *gps_dl_link_get(enum gps_dl_link_id_enum link_id);
+
+void gps_each_link_init(enum gps_dl_link_id_enum link_id);
+void gps_each_link_deinit(enum gps_dl_link_id_enum link_id);
+void gps_each_link_context_init(enum gps_dl_link_id_enum link_id);
+void gps_each_link_context_clear(enum gps_dl_link_id_enum link_id);
+void gps_each_link_inc_session_id(enum gps_dl_link_id_enum link_id);
+int gps_each_link_get_session_id(enum gps_dl_link_id_enum link_id);
+
+int gps_each_link_open(enum gps_dl_link_id_enum link_id);
+void gps_dl_link_open_ack(enum gps_dl_link_id_enum link_id, bool okay, bool hw_resume);
+
+enum gps_each_link_lock_reason {
+ GDL_LOCK_FOR_OPEN,
+ GDL_LOCK_FOR_OPEN_DONE,
+ GDL_LOCK_FOR_CLOSE,
+ GDL_LOCK_FOR_CLOSE_DONE,
+ GDL_LOCK_FOR_RESET,
+ GDL_LOCK_FOR_RESET_DONE,
+};
+
+enum gps_each_link_state_enum gps_each_link_get_state(enum gps_dl_link_id_enum link_id);
+void gps_each_link_set_state(enum gps_dl_link_id_enum link_id, enum gps_each_link_state_enum state);
+bool gps_each_link_change_state_from(enum gps_dl_link_id_enum link_id,
+ enum gps_each_link_state_enum from, enum gps_each_link_state_enum to);
+
+
+int gps_each_link_take_big_lock(enum gps_dl_link_id_enum link_id,
+ enum gps_each_link_lock_reason reason);
+int gps_each_link_give_big_lock(enum gps_dl_link_id_enum link_id);
+
+int gps_each_link_reset(enum gps_dl_link_id_enum link_id);
+void gps_dl_link_reset_ack(enum gps_dl_link_id_enum link_id);
+void gps_dl_link_on_post_conn_reset(enum gps_dl_link_id_enum link_id);
+bool gps_dl_link_try_to_clear_both_resetting_status(void);
+int gps_dl_link_get_clock_flag(void);
+
+enum gps_each_link_close_or_suspend_op {
+ GDL_CLOSE,
+ GDL_DPSTOP,
+ GDL_CLKEXT,
+};
+int gps_each_link_enter_dsleep(enum gps_dl_link_id_enum link_id);
+int gps_each_link_leave_dsleep(enum gps_dl_link_id_enum link_id);
+int gps_each_link_hw_suspend(enum gps_dl_link_id_enum link_id, bool need_clk_ext);
+int gps_each_link_hw_resume(enum gps_dl_link_id_enum link_id);
+int gps_each_link_close(enum gps_dl_link_id_enum link_id);
+int gps_each_link_check(enum gps_dl_link_id_enum link_id, int reason);
+
+int gps_each_link_write(enum gps_dl_link_id_enum link_id,
+ unsigned char *buf, unsigned int len);
+int gps_each_link_write_with_opt(enum gps_dl_link_id_enum link_id,
+ unsigned char *buf, unsigned int len, bool wait_tx_done);
+int gps_each_link_read(enum gps_dl_link_id_enum link_id,
+ unsigned char *buf, unsigned int len);
+int gps_each_link_read_with_timeout(enum gps_dl_link_id_enum link_id,
+ unsigned char *buf, unsigned int len, int timeout_usec, bool *p_is_nodata);
+
+bool gps_dl_link_start_tx_dma_if_has_data(enum gps_dl_link_id_enum link_id);
+
+void gps_dl_link_waitable_init(struct gps_each_link_waitable *p,
+ enum gps_each_link_waitable_type type);
+
+void gps_dl_link_waitable_reset(enum gps_dl_link_id_enum link_id, enum gps_each_link_waitable_type type);
+
+enum GDL_RET_STATUS gps_dl_link_wait_on(struct gps_each_link_waitable *p, long *p_sigval);
+
+enum GDL_RET_STATUS gps_dl_link_try_wait_on(enum gps_dl_link_id_enum link_id,
+ enum gps_each_link_waitable_type type);
+
+void gps_dl_link_wake_up(struct gps_each_link_waitable *p);
+
+enum gps_dl_link_event_id {
+ GPS_DL_EVT_LINK_OPEN,
+ GPS_DL_EVT_LINK_CLOSE,
+ GPS_DL_EVT_LINK_WRITE,
+ GPS_DL_EVT_LINK_READ,
+ GPS_DL_EVT_LINK_DSP_ROM_READY_TIMEOUT,
+ GPS_DL_EVT_LINK_DSP_FSM_TIMEOUT,
+ GPS_DL_EVT_LINK_RESET_DSP,
+ GPS_DL_EVT_LINK_RESET_GPS,
+ GPS_DL_EVT_LINK_PRE_CONN_RESET,
+ GPS_DL_EVT_LINK_POST_CONN_RESET,
+ GPS_DL_EVT_LINK_PRINT_HW_STATUS,
+ GPS_DL_EVT_LINK_ENTER_DPSLEEP,
+ GPS_DL_EVT_LINK_LEAVE_DPSLEEP,
+ GPS_DL_EVT_LINK_ENTER_DPSTOP,
+ GPS_DL_EVT_LINK_LEAVE_DPSTOP,
+ GPS_DL_EVT_LINK_UPDATE_SETTING,
+ GPS_DL_EVT_LINK_PRINT_DATA_STATUS,
+ GPS_DL_LINK_EVT_NUM,
+};
+
+void gps_dl_link_event_send(enum gps_dl_link_event_id evt,
+ enum gps_dl_link_id_enum link_id);
+
+void gps_dl_link_event_proc(enum gps_dl_link_event_id evt,
+ enum gps_dl_link_id_enum link_id);
+
+#endif /* _GPS_EACH_LINK_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/gps_dl_dma_buf.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/gps_dl_dma_buf.c
new file mode 100644
index 0000000..18a945e
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/gps_dl_dma_buf.c
@@ -0,0 +1,722 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+#include "gps_dl_context.h"
+
+#include "gps_dl_dma_buf.h"
+#if GPS_DL_ON_LINUX
+#include "asm/barrier.h"
+#endif
+
+#define GDL_COUNT_FREE(r, w, l)\
+ ((w >= r) ? (l + r - w) : (r - w))
+
+#define GDL_COUNT_DATA(r, w, l)\
+ ((w >= r) ? (w - r) : (l + w - r))
+
+void gps_dma_buf_reset(struct gps_dl_dma_buf *p_dma)
+{
+ gps_each_link_spin_lock_take(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+ p_dma->read_index = 0;
+ p_dma->reader_working = 0;
+ p_dma->write_index = 0;
+ p_dma->writer_working = 0;
+ p_dma->dma_working_entry.is_valid = false;
+ p_dma->entry_r = 0;
+ p_dma->entry_w = 0;
+ memset(&p_dma->data_entries[0], 0, sizeof(p_dma->data_entries));
+ gps_each_link_spin_lock_give(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+
+ GDL_LOGXD(p_dma->dev_index, "dir = %d", p_dma->dir);
+}
+
+void gps_dma_buf_show(struct gps_dl_dma_buf *p_dma, bool is_warning)
+{
+ unsigned int ri, wi, fl, re, we, fe;
+ bool r_working, w_working;
+
+ gps_each_link_spin_lock_take(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+ ri = p_dma->read_index;
+ r_working = p_dma->reader_working;
+ wi = p_dma->write_index;
+ w_working = p_dma->writer_working;
+ fl = GDL_COUNT_FREE(p_dma->read_index, p_dma->writer_working, p_dma->len);
+ re = p_dma->entry_r;
+ we = p_dma->entry_w;
+ fe = GDL_COUNT_FREE(p_dma->entry_r, p_dma->entry_w, GPS_DL_DMA_BUF_ENTRY_MAX);
+ gps_each_link_spin_lock_give(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+
+ if (is_warning) {
+ GDL_LOGXW_DRW(p_dma->dev_index,
+ "dir = %d, l = %d, r = %d(%d), w = %d(%d), fl = %d, re = %d, we = %d, fe = %d",
+ p_dma->dir, p_dma->len, ri, r_working, wi, w_working, fl, re, we, fe);
+ } else {
+ GDL_LOGXD_DRW(p_dma->dev_index,
+ "dir = %d, l = %d, r = %d(%d), w = %d(%d), fl = %d, re = %d, we = %d, fe = %d",
+ p_dma->dir, p_dma->len, ri, r_working, wi, w_working, fl, re, we, fe);
+ }
+}
+
+void gps_dma_buf_align_as_byte_mode(struct gps_dl_dma_buf *p_dma)
+{
+ unsigned int ri, wi;
+ unsigned int ri_new, wi_new;
+
+ gps_each_link_spin_lock_take(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+ ri = p_dma->read_index;
+ wi = p_dma->write_index;
+
+ if (!gps_dl_is_1byte_mode()) {
+ p_dma->read_index = ((p_dma->read_index + 3) / 4) * 4;
+ if (p_dma->read_index >= p_dma->len)
+ p_dma->read_index -= p_dma->len;
+ p_dma->reader_working = 0;
+
+ p_dma->write_index = ((p_dma->write_index + 3) / 4) * 4;
+ if (p_dma->write_index >= p_dma->len)
+ p_dma->write_index -= p_dma->len;
+ p_dma->writer_working = 0;
+ p_dma->dma_working_entry.is_valid = false;
+ }
+
+ ri_new = p_dma->read_index;
+ wi_new = p_dma->write_index;
+
+ /* clear it anyway */
+ p_dma->read_index = p_dma->write_index;
+ gps_each_link_spin_lock_give(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+
+ GDL_LOGXD(p_dma->dev_index, "is_1byte = %d, ri: %u -> %u, wi: %u -> %u",
+ gps_dl_is_1byte_mode(), ri, ri_new, wi, wi_new);
+}
+
+#if 0
+enum GDL_RET_STATUS gdl_dma_buf_init(struct gps_dl_dma_buf *p_dma_buf)
+{
+ return GDL_OKAY;
+}
+
+enum GDL_RET_STATUS gdl_dma_buf_deinit(struct gps_dl_dma_buf *p_dma_buf)
+{
+ return GDL_OKAY;
+}
+#endif
+
+bool gps_dma_buf_is_empty(struct gps_dl_dma_buf *p_dma)
+{
+ bool is_empty;
+
+ gps_each_link_spin_lock_take(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+ is_empty = (p_dma->read_index == p_dma->write_index);
+ gps_each_link_spin_lock_give(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+
+ return is_empty;
+}
+
+enum GDL_RET_STATUS gdl_dma_buf_put(struct gps_dl_dma_buf *p_dma,
+ const unsigned char *p_buf, unsigned int buf_len)
+{
+ struct gdl_dma_buf_entry entry;
+ struct gdl_dma_buf_entry *p_entry = &entry;
+
+ /* unsigned int free_len; */
+ /* unsigned int wrap_len; */
+ enum GDL_RET_STATUS gdl_ret;
+
+ ASSERT_NOT_NULL(p_dma, GDL_FAIL_ASSERT);
+ ASSERT_NOT_NULL(p_buf, GDL_FAIL_ASSERT);
+
+ gdl_ret = gdl_dma_buf_get_free_entry(p_dma, p_entry, false);
+
+ if (GDL_OKAY != gdl_ret)
+ return gdl_ret;
+
+#if 0
+ free_len = GDL_COUNT_FREE(p_entry->read_index,
+ p_entry->write_index, p_entry->buf_length);
+ GDL_LOGD("r=%u, w=%u, l=%u, f=%u", p_entry->read_index,
+ p_entry->write_index, p_entry->buf_length, free_len);
+
+ if (free_len < buf_len) {
+ gdl_dma_buf_set_free_entry(p_dma, NULL);
+ return GDL_FAIL_NOSPACE;
+ }
+
+ wrap_len = p_entry->buf_length - p_entry->write_index;
+ if (wrap_len >= buf_len) {
+ memcpy(((unsigned char *)p_entry->vir_addr) + p_entry->write_index,
+ p_buf, buf_len);
+
+ p_entry->write_index += buf_len;
+ if (p_entry->write_index >= p_entry->buf_length)
+ p_entry->write_index = 0;
+ } else {
+ memcpy(((unsigned char *)p_entry->vir_addr) + p_entry->write_index,
+ p_buf, wrap_len);
+
+ memcpy(((unsigned char *)p_entry->vir_addr) + 0,
+ p_buf + wrap_len, buf_len - wrap_len);
+
+ p_entry->write_index = buf_len - wrap_len;
+ }
+#endif
+ gdl_ret = gdl_dma_buf_buf_to_entry(p_entry, p_buf, buf_len,
+ &p_entry->write_index);
+
+ if (GDL_OKAY != gdl_ret)
+ return gdl_ret;
+
+ /* TODO: make a data entry */
+
+ GDL_LOGD("new_w=%u", p_entry->write_index);
+ gdl_dma_buf_set_free_entry(p_dma, p_entry);
+
+ return GDL_OKAY;
+}
+
+enum GDL_RET_STATUS gdl_dma_buf_get(struct gps_dl_dma_buf *p_dma,
+ unsigned char *p_buf, unsigned int buf_len, unsigned int *p_data_len,
+ bool *p_is_nodata)
+{
+ struct gdl_dma_buf_entry entry;
+ struct gdl_dma_buf_entry *p_entry = &entry;
+
+ /* unsigned int data_len; */
+ /* unsigned int wrap_len; */
+ enum GDL_RET_STATUS gdl_ret;
+
+ ASSERT_NOT_NULL(p_entry, GDL_FAIL_ASSERT);
+ ASSERT_NOT_NULL(p_buf, GDL_FAIL_ASSERT);
+ ASSERT_NOT_ZERO(buf_len, GDL_FAIL_ASSERT);
+ ASSERT_NOT_NULL(p_data_len, GDL_FAIL_ASSERT);
+
+ gdl_ret = gdl_dma_buf_get_data_entry(p_dma, p_entry);
+
+ if (GDL_OKAY != gdl_ret)
+ return gdl_ret;
+
+#if 0
+ data_len = GDL_COUNT_DATA(p_entry->read_index,
+ p_entry->write_index, p_entry->buf_length);
+ GDL_LOGD("r=%u, w=%u, l=%u, d=%u", p_entry->read_index,
+ p_entry->write_index, p_entry->buf_length, data_len);
+
+ /* assert data_len > 0 */
+
+ if (data_len > buf_len) {
+ /* TODO: improve it */
+ gdl_dma_buf_set_data_entry(p_dma, p_entry);
+ return GDL_FAIL_NOSPACE;
+ }
+
+ if (p_entry->write_index > p_entry->read_index) {
+ memcpy(p_buf, ((unsigned char *)p_entry->vir_addr) + p_entry->read_index,
+ data_len);
+ } else {
+ wrap_len = p_entry->buf_length - p_entry->read_index;
+
+ memcpy(p_buf, ((unsigned char *)p_entry->vir_addr) + p_entry->read_index,
+ wrap_len);
+
+ memcpy(p_buf + wrap_len, ((unsigned char *)p_entry->vir_addr) + 0,
+ data_len - wrap_len);
+ }
+#endif
+ gdl_ret = gdl_dma_buf_entry_to_buf(p_entry, p_buf, buf_len, p_data_len);
+
+ if (GDL_OKAY != gdl_ret)
+ return gdl_ret;
+
+ /* Todo: Case1: buf < data in entry */
+ /* Note: we can limit the rx transfer max to 512, then case1 should not be happened */
+
+ /* Todo: Case2: buf > data in entry, need to combine multiple entry until no data entry? */
+
+ if (p_is_nodata)
+ *p_is_nodata = p_entry->is_nodata;
+
+ /* *p_data_len = data_len; */
+ p_entry->read_index = p_entry->write_index;
+ gdl_dma_buf_set_data_entry(p_dma, p_entry);
+
+ return GDL_OKAY;
+}
+
+static enum GDL_RET_STATUS gdl_dma_buf_get_data_entry_inner(struct gps_dl_dma_buf *p_dma,
+ struct gdl_dma_buf_entry *p_entry)
+{
+ struct gdl_dma_buf_entry *p_data_entry;
+ unsigned int data_len;
+
+ if (p_dma->reader_working)
+ return GDL_FAIL_BUSY;
+
+ p_dma->reader_working = true;
+
+ if (p_dma->read_index == p_dma->write_index) {
+ p_dma->reader_working = false;
+ return GDL_FAIL_NODATA;
+ }
+
+ if (p_dma->entry_r == p_dma->entry_w) {
+ /* impossible: has data but no data entry */
+ p_dma->reader_working = false;
+ return GDL_FAIL_NOENTRY;
+ }
+
+ p_data_entry = &p_dma->data_entries[p_dma->entry_r];
+ p_entry->write_index = p_data_entry->write_index;
+ p_entry->is_nodata = p_data_entry->is_nodata;
+ if ((p_dma->transfer_max > 0) && (p_dma->dir == GDL_DMA_A2D)) {
+ data_len = GDL_COUNT_DATA(p_data_entry->read_index,
+ p_data_entry->write_index, p_data_entry->buf_length);
+
+ if (data_len > p_dma->transfer_max) {
+ p_entry->write_index = p_data_entry->read_index + p_dma->transfer_max;
+ if (p_entry->write_index >= p_data_entry->buf_length)
+ p_entry->write_index -= p_data_entry->buf_length;
+ p_entry->is_nodata = false;
+ }
+ }
+ p_entry->read_index = p_data_entry->read_index;
+ p_entry->buf_length = p_data_entry->buf_length;
+ p_entry->phy_addr = p_data_entry->phy_addr;
+ p_entry->vir_addr = p_data_entry->vir_addr;
+ p_entry->is_valid = true;
+ return GDL_OKAY;
+}
+enum GDL_RET_STATUS gdl_dma_buf_get_data_entry(struct gps_dl_dma_buf *p_dma,
+ struct gdl_dma_buf_entry *p_entry)
+{
+ enum GDL_RET_STATUS ret;
+
+ ASSERT_NOT_NULL(p_dma, GDL_FAIL_ASSERT);
+ ASSERT_NOT_NULL(p_entry, GDL_FAIL_ASSERT);
+
+ gps_each_link_spin_lock_take(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+ ret = gdl_dma_buf_get_data_entry_inner(p_dma, p_entry);
+ gps_each_link_spin_lock_give(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+
+ return ret;
+}
+
+
+static enum GDL_RET_STATUS gdl_dma_buf_set_data_entry_inner(struct gps_dl_dma_buf *p_dma,
+ struct gdl_dma_buf_entry *p_entry)
+{
+ struct gdl_dma_buf_entry *p_data_entry;
+
+ if (!p_dma->reader_working)
+ return GDL_FAIL_STATE_MISMATCH;
+
+ if (NULL == p_entry) {
+ p_dma->reader_working = false;
+ return GDL_OKAY;
+ }
+
+ if (p_dma->entry_r == p_dma->entry_w) {
+ /* impossible due to get_data_entry already check it */
+ p_dma->writer_working = false;
+ return GDL_FAIL_NOENTRY2;
+ }
+
+ p_data_entry = &p_dma->data_entries[p_dma->entry_r];
+ if (p_entry->write_index == p_data_entry->write_index) {
+ p_data_entry->is_valid = false;
+ p_dma->entry_r++;
+ if (p_dma->entry_r >= GPS_DL_DMA_BUF_ENTRY_MAX)
+ p_dma->entry_r = 0;
+ } else
+ p_data_entry->read_index = p_entry->write_index;
+
+ p_dma->read_index = p_entry->write_index;
+ p_dma->reader_working = false;
+ return GDL_OKAY;
+}
+
+enum GDL_RET_STATUS gdl_dma_buf_set_data_entry(struct gps_dl_dma_buf *p_dma,
+ struct gdl_dma_buf_entry *p_entry)
+{
+ enum GDL_RET_STATUS ret;
+
+ ASSERT_NOT_NULL(p_dma, GDL_FAIL_ASSERT);
+
+ gps_each_link_spin_lock_take(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+ ret = gdl_dma_buf_set_data_entry_inner(p_dma, p_entry);
+ gps_each_link_spin_lock_give(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+
+ return ret;
+}
+
+
+static enum GDL_RET_STATUS gdl_dma_buf_get_free_entry_inner(struct gps_dl_dma_buf *p_dma,
+ struct gdl_dma_buf_entry *p_entry)
+{
+ unsigned int free_len;
+
+ if (p_dma->writer_working)
+ return GDL_FAIL_BUSY;
+
+ p_dma->writer_working = true;
+
+ if (GDL_COUNT_FREE(p_dma->read_index, p_dma->write_index, p_dma->len) <= 1) {
+ /* dma buf is full */
+ p_dma->writer_working = false;
+ return GDL_FAIL_NOSPACE;
+ }
+
+ if (GDL_COUNT_FREE(p_dma->entry_r, p_dma->entry_w, GPS_DL_DMA_BUF_ENTRY_MAX) <= 1) {
+ /* entries is all used (not use the last one) */
+ p_dma->writer_working = false;
+ return GDL_FAIL_NOENTRY;
+ }
+
+ p_entry->read_index = p_dma->read_index;
+ if ((p_dma->transfer_max > 0) && (p_dma->dir == GDL_DMA_D2A)) {
+ /* the free space is between write_index to read_index,
+ * if transfer_max set and free_len > it,
+ * limit the free space from write_index to write_index + transfer_max
+ */
+ free_len = GDL_COUNT_FREE(p_dma->read_index, p_dma->write_index, p_dma->len);
+ if (free_len > p_dma->transfer_max) {
+ p_entry->read_index = p_dma->write_index + p_dma->transfer_max;
+ if (p_entry->read_index >= p_dma->len)
+ p_entry->read_index -= p_dma->len;
+ }
+ }
+ p_entry->write_index = p_dma->write_index;
+ p_entry->buf_length = p_dma->len;
+ p_entry->phy_addr = p_dma->phy_addr;
+ p_entry->vir_addr = p_dma->vir_addr;
+ p_entry->is_valid = true;
+
+ /* This field not used for free entry, just make static analysis tool happy. */
+ p_entry->is_nodata = false;
+ return GDL_OKAY;
+}
+
+enum GDL_RET_STATUS gdl_dma_buf_get_free_entry(struct gps_dl_dma_buf *p_dma,
+ struct gdl_dma_buf_entry *p_entry, bool nospace_set_pending_rx)
+{
+ enum GDL_RET_STATUS ret;
+
+ ASSERT_NOT_NULL(p_dma, GDL_FAIL_ASSERT);
+ ASSERT_NOT_NULL(p_entry, GDL_FAIL_ASSERT);
+
+ gps_each_link_spin_lock_take(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+ ret = gdl_dma_buf_get_free_entry_inner(p_dma, p_entry);
+ if (nospace_set_pending_rx &&
+ (ret == GDL_FAIL_NOSPACE || ret == GDL_FAIL_NOENTRY)) {
+ p_dma->has_pending_rx = true;
+ ret = GDL_FAIL_NOSPACE_PENDING_RX;
+ }
+ gps_each_link_spin_lock_give(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+
+ return ret;
+}
+
+static enum GDL_RET_STATUS gdl_dma_buf_set_free_entry_inner(struct gps_dl_dma_buf *p_dma,
+ struct gdl_dma_buf_entry *p_entry)
+{
+ struct gdl_dma_buf_entry *p_data_entry;
+
+ if (!p_dma->writer_working)
+ return GDL_FAIL_STATE_MISMATCH;
+
+ if (GDL_COUNT_FREE(p_dma->entry_r, p_dma->entry_w, GPS_DL_DMA_BUF_ENTRY_MAX) <= 1) {
+ /* impossible due to get_free_entry already check it */
+ p_dma->writer_working = false;
+ return GDL_FAIL_NOENTRY2;
+ }
+
+ p_data_entry = &p_dma->data_entries[p_dma->entry_w];
+ p_dma->entry_w++;
+ if (p_dma->entry_w >= GPS_DL_DMA_BUF_ENTRY_MAX)
+ p_dma->entry_w = 0;
+
+ p_data_entry->read_index = p_dma->write_index;
+ p_data_entry->write_index = p_entry->write_index;
+ p_data_entry->buf_length = p_dma->len;
+ p_data_entry->phy_addr = p_dma->phy_addr;
+ p_data_entry->vir_addr = p_dma->vir_addr;
+ p_data_entry->is_valid = true;
+ p_data_entry->is_nodata = p_entry->is_nodata;
+
+ p_dma->write_index = p_entry->write_index;
+ p_dma->writer_working = false;
+
+ return GDL_OKAY;
+}
+
+enum GDL_RET_STATUS gdl_dma_buf_set_free_entry(struct gps_dl_dma_buf *p_dma,
+ struct gdl_dma_buf_entry *p_entry)
+{
+ enum GDL_RET_STATUS ret;
+
+ ASSERT_NOT_NULL(p_dma, GDL_FAIL_ASSERT);
+ ASSERT_NOT_NULL(p_entry, GDL_FAIL_ASSERT);
+
+ gps_each_link_spin_lock_take(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+ ret = gdl_dma_buf_set_free_entry_inner(p_dma, p_entry);
+ gps_each_link_spin_lock_give(p_dma->dev_index, GPS_DL_SPINLOCK_FOR_DMA_BUF);
+
+ return ret;
+}
+
+
+void gps_dma_buf_memcpy_from_rx(void *p_dst, const void *p_src, unsigned int len)
+{
+ /* TODO:
+ * __dma_unmap_area((void *)p_dst, len, DMA_FROM_DEVICE);
+ * dma_sync_single_for_cpu(DMA_FROM_DEVICE);
+ */
+#if GPS_DL_ON_LINUX
+ memcpy_fromio(p_dst, p_src, len);
+#elif GPS_DL_ON_CTP
+ /* gps_dl_ctp_memcpy((unsigned char *)p_dst, (const unsigned char *)p_src, len); */
+ memcpy(p_dst, p_src, len);
+#else
+ memcpy(p_dst, p_src, len);
+#endif
+}
+
+void gps_dma_buf_memcpy_to_tx(void *p_dst, const void *p_src, unsigned int len)
+{
+#if GPS_DL_ON_LINUX
+ memcpy_toio(p_dst, p_src, len);
+#elif GPS_DL_ON_CTP
+ /* gps_dl_ctp_memcpy((unsigned char *)p_dst, (const unsigned char *)p_src, len); */
+ memcpy(p_dst, p_src, len);
+#else
+ memcpy(p_dst, p_src, len);
+#endif
+ /* Use mb to make sure memcpy is done by CPU, and then DMA can be started. */
+ mb();
+ /* TODO:
+ * __dma_flush_area((void *)p_dst, len);
+ * dma_sync_single_for_device(DMA_TO_DEVICE);
+ */
+}
+
+void gps_dma_buf_memset_io(void *p_dst, unsigned char val, unsigned int len)
+{
+#if GPS_DL_ON_LINUX
+ memset_io(p_dst, val, len);
+#elif GPS_DL_ON_CTP
+ gps_dl_ctp_memset((unsigned char *)p_dst, val, len);
+#else
+ memset(p_dst, val, len);
+#endif
+ /* Use mb to make sure memcpy is done by CPU, and then DMA can be started. */
+ mb();
+ /* TODO:
+ * __dma_flush_area((void *)p_dst, len);
+ * dma_sync_single_for_device(DMA_TO_DEVICE);
+ */
+}
+
+enum GDL_RET_STATUS gdl_dma_buf_entry_to_buf(const struct gdl_dma_buf_entry *p_entry,
+ unsigned char *p_buf, unsigned int buf_len, unsigned int *p_data_len)
+{
+ unsigned int data_len;
+ unsigned int wrap_len;
+ unsigned char *p_src;
+
+ ASSERT_NOT_NULL(p_entry, GDL_FAIL_ASSERT);
+ ASSERT_NOT_NULL(p_buf, GDL_FAIL_ASSERT);
+ ASSERT_NOT_ZERO(buf_len, GDL_FAIL_ASSERT);
+ ASSERT_NOT_NULL(p_data_len, GDL_FAIL_ASSERT);
+
+ data_len = GDL_COUNT_DATA(p_entry->read_index,
+ p_entry->write_index, p_entry->buf_length);
+ GDL_LOGD("r=%u, w=%u, l=%u, d=%u", p_entry->read_index,
+ p_entry->write_index, p_entry->buf_length, data_len);
+
+ if (data_len > buf_len) {
+ *p_data_len = 0;
+ return GDL_FAIL_NOSPACE;
+ }
+
+ if (p_entry->write_index > p_entry->read_index) {
+ p_src = ((unsigned char *)p_entry->vir_addr) + p_entry->read_index;
+ gps_dma_buf_memcpy_from_rx(p_buf, p_src, data_len);
+ } else {
+ wrap_len = p_entry->buf_length - p_entry->read_index;
+
+ p_src = ((unsigned char *)p_entry->vir_addr) + p_entry->read_index;
+ gps_dma_buf_memcpy_from_rx(p_buf, p_src, wrap_len);
+
+ p_src = ((unsigned char *)p_entry->vir_addr) + 0;
+ gps_dma_buf_memcpy_from_rx(p_buf + wrap_len, p_src, data_len - wrap_len);
+ }
+
+ *p_data_len = data_len;
+ return GDL_OKAY;
+}
+
+enum GDL_RET_STATUS gdl_dma_buf_buf_to_entry(const struct gdl_dma_buf_entry *p_entry,
+ const unsigned char *p_buf, unsigned int data_len, unsigned int *p_write_index)
+{
+ unsigned int free_len;
+ unsigned int wrap_len;
+ unsigned int write_index;
+ unsigned int alligned_data_len;
+ unsigned int fill_zero_len;
+ unsigned char *p_dst;
+
+ if (gps_dl_is_1byte_mode()) {
+ alligned_data_len = data_len;
+ fill_zero_len = 0;
+ } else {
+ alligned_data_len = ((data_len + 3) / 4) * 4;
+ fill_zero_len = alligned_data_len - data_len;
+ GDL_LOGD("data_len = %u, alligned = %u", data_len, alligned_data_len);
+ }
+
+ ASSERT_NOT_NULL(p_entry, GDL_FAIL_ASSERT);
+ ASSERT_NOT_NULL(p_buf, GDL_FAIL_ASSERT);
+ ASSERT_NOT_ZERO(data_len, GDL_FAIL_ASSERT);
+ ASSERT_NOT_NULL(p_write_index, GDL_FAIL_ASSERT);
+
+ /* TODO: make dma done event */
+
+ free_len = GDL_COUNT_FREE(p_entry->read_index,
+ p_entry->write_index, p_entry->buf_length);
+
+ GDL_LOGD("r=%u, w=%u, l=%u, f=%u", p_entry->read_index,
+ p_entry->write_index, p_entry->buf_length, free_len);
+
+ if (free_len < alligned_data_len)
+ return GDL_FAIL_NOSPACE;
+
+ wrap_len = p_entry->buf_length - p_entry->write_index;
+ if (wrap_len >= data_len) {
+ p_dst = ((unsigned char *)p_entry->vir_addr) + p_entry->write_index;
+ gps_dma_buf_memcpy_to_tx(p_dst, p_buf, data_len);
+
+ write_index = p_entry->write_index + data_len;
+ if (write_index >= p_entry->buf_length)
+ write_index = 0;
+ } else {
+ p_dst = ((unsigned char *)p_entry->vir_addr) + p_entry->write_index;
+ gps_dma_buf_memcpy_to_tx(p_dst, p_buf, wrap_len);
+
+ p_dst = ((unsigned char *)p_entry->vir_addr) + 0;
+ gps_dma_buf_memcpy_to_tx(p_dst, p_buf + wrap_len, data_len - wrap_len);
+
+ write_index = data_len - wrap_len;
+ }
+
+ /* fill it to allignment */
+ if (fill_zero_len > 0) {
+ wrap_len = p_entry->buf_length - write_index;
+ if (wrap_len >= fill_zero_len) {
+ p_dst = ((unsigned char *)p_entry->vir_addr) + write_index;
+ gps_dma_buf_memset_io(p_dst, 0, fill_zero_len);
+
+ write_index += fill_zero_len;
+ if (write_index >= p_entry->buf_length)
+ write_index = 0;
+ } else {
+ /* impossible case when buf_len is an integral multiple of 4byte */
+ p_dst = ((unsigned char *)p_entry->vir_addr) + write_index;
+ gps_dma_buf_memset_io(p_dst, 0, wrap_len);
+
+ p_dst = ((unsigned char *)p_entry->vir_addr) + 0;
+ gps_dma_buf_memset_io(p_dst, 0, fill_zero_len - wrap_len);
+
+ write_index = fill_zero_len - wrap_len;
+ }
+ }
+
+ GDL_LOGD("new_w=%u", write_index);
+ *p_write_index = write_index;
+
+ return GDL_OKAY;
+}
+
+enum GDL_RET_STATUS gdl_dma_buf_entry_to_transfer(
+ const struct gdl_dma_buf_entry *p_entry,
+ struct gdl_hw_dma_transfer *p_transfer, bool is_tx)
+{
+ ASSERT_NOT_NULL(p_entry, GDL_FAIL_ASSERT);
+ ASSERT_NOT_NULL(p_transfer, GDL_FAIL_ASSERT);
+
+ p_transfer->buf_start_addr = (unsigned int)p_entry->phy_addr;
+ if (is_tx) {
+ p_transfer->transfer_start_addr =
+ (unsigned int)p_entry->phy_addr + p_entry->read_index;
+ p_transfer->len_to_wrap = p_entry->buf_length - p_entry->read_index;
+ p_transfer->transfer_max_len = GDL_COUNT_DATA(
+ p_entry->read_index, p_entry->write_index, p_entry->buf_length);
+
+ if (!gps_dl_is_1byte_mode()) {
+ p_transfer->len_to_wrap /= 4;
+ p_transfer->transfer_max_len /= 4;
+ }
+ } else {
+ p_transfer->transfer_start_addr =
+ (unsigned int)p_entry->phy_addr + p_entry->write_index;
+ p_transfer->len_to_wrap = p_entry->buf_length - p_entry->write_index;
+ p_transfer->transfer_max_len = GDL_COUNT_FREE(
+ p_entry->read_index, p_entry->write_index, p_entry->buf_length);
+
+ if (!gps_dl_is_1byte_mode()) {
+ p_transfer->len_to_wrap /= 4;
+ p_transfer->transfer_max_len /= 4;
+ }
+ }
+
+ GDL_LOGD("r=%u, w=%u, l=%u, is_tx=%d, transfer: ba=0x%08x, ta=0x%08x, wl=%d, tl=%d",
+ p_entry->read_index, p_entry->write_index, p_entry->buf_length, is_tx,
+ p_transfer->buf_start_addr, p_transfer->transfer_start_addr,
+ p_transfer->len_to_wrap, p_transfer->transfer_max_len);
+
+ ASSERT_NOT_ZERO(p_transfer->buf_start_addr, GDL_FAIL_ASSERT);
+ ASSERT_NOT_ZERO(p_transfer->transfer_start_addr, GDL_FAIL_ASSERT);
+ ASSERT_NOT_ZERO(p_transfer->len_to_wrap, GDL_FAIL_ASSERT);
+ ASSERT_NOT_ZERO(p_transfer->transfer_max_len, GDL_FAIL_ASSERT);
+
+ return GDL_OKAY;
+}
+
+enum GDL_RET_STATUS gdl_dma_buf_entry_transfer_left_to_write_index(
+ const struct gdl_dma_buf_entry *p_entry,
+ unsigned int left_len, unsigned int *p_write_index)
+{
+ unsigned int free_len;
+ unsigned int new_write_index;
+
+ ASSERT_NOT_NULL(p_entry, GDL_FAIL_ASSERT);
+ ASSERT_NOT_NULL(p_write_index, GDL_FAIL_ASSERT);
+
+ free_len = GDL_COUNT_FREE(p_entry->read_index,
+ p_entry->write_index, p_entry->buf_length);
+
+ GDL_ASSERT(free_len > left_len, GDL_FAIL_ASSERT, "");
+
+ new_write_index = p_entry->write_index + free_len - left_len;
+ if (new_write_index >= p_entry->buf_length)
+ new_write_index -= p_entry->buf_length;
+
+ GDL_LOGD("r=%u, w=%u, l=%u, left=%d, new_w=%d",
+ p_entry->read_index, p_entry->write_index, p_entry->buf_length,
+ left_len, new_write_index);
+ GDL_ASSERT(new_write_index < p_entry->buf_length, GDL_FAIL_ASSERT, "");
+
+ *p_write_index = new_write_index;
+
+ return GDL_OKAY;
+}
+
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/gps_dl_hist_rec.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/gps_dl_hist_rec.c
new file mode 100644
index 0000000..03068ac
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/gps_dl_hist_rec.c
@@ -0,0 +1,159 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include "gps_dl_config.h"
+
+#include "gps_each_link.h"
+#include "gps_dl_osal.h"
+#include "gps_dl_hist_rec.h"
+
+enum gps_dl_hist_rec_rw_type {
+ GPS_DL_HIST_REC_RW_READ,
+ GPS_DL_HIST_REC_RW_WRITE,
+ GPS_DL_HIST_REC_RW_TYPE_MAX
+};
+
+enum gps_dl_hist_rec_rw_dump_point {
+ GPS_DL_HIST_REC_RW_DUMP_ON_REC_FULL,
+ GPS_DL_HIST_REC_RW_DUMP_ON_INTERVAL,
+ GPS_DL_HIST_REC_RW_DUMP_ON_PID_CHANGED,
+ GPS_DL_HIST_REC_RW_DUMP_ON_FORCE_DUMP,
+ GPS_DL_HIST_REC_RW_DUMP_ON_ERROR_LEN,
+};
+
+struct gps_dl_hist_rec_rw_item {
+ int len;
+};
+
+#define GPS_DL_HIST_REC_RW_ITEM_MAX (8)
+struct gps_dl_hist_rec_rw_list {
+ struct gps_dl_hist_rec_rw_item items[GPS_DL_HIST_REC_RW_ITEM_MAX];
+ unsigned int n_item;
+ unsigned int rec_idx;
+ int pid;
+ enum gps_dl_hist_rec_rw_rec_point rec_point;
+ enum gps_dl_hist_rec_rw_type type;
+};
+
+struct gps_dl_hist_rec_rw_list g_gps_dl_hist_rec_rw_list[GPS_DATA_LINK_NUM][GPS_DL_HIST_REC_RW_TYPE_MAX];
+
+
+static void gps_dl_hist_rec_rw_do_dump(enum gps_dl_link_id_enum link_id,
+ struct gps_dl_hist_rec_rw_list *p_list, enum gps_dl_hist_rec_rw_dump_point dump_point)
+{
+ GDL_LOGXW_DRW(link_id, "%s: dp=%d, pid=%d, i=%d, n=%d(%d), l=%d %d %d %d; %d %d %d %d",
+ (p_list->type == GPS_DL_HIST_REC_RW_READ) ? "rd" : "wr",
+ dump_point, p_list->pid, p_list->rec_idx, p_list->n_item, p_list->rec_point,
+ p_list->items[0].len, p_list->items[1].len, p_list->items[2].len, p_list->items[3].len,
+ p_list->items[4].len, p_list->items[5].len, p_list->items[6].len, p_list->items[7].len);
+ p_list->rec_idx += p_list->n_item;
+ p_list->n_item = 0;
+ memset(&p_list->items, 0, sizeof(p_list->items));
+}
+
+static void gps_dl_hist_rec_rw_check_dump(enum gps_dl_link_id_enum link_id,
+ struct gps_dl_hist_rec_rw_list *p_list, enum gps_dl_hist_rec_rw_rec_point rec_point)
+{
+ if (p_list->n_item > GPS_DL_HIST_REC_RW_ITEM_MAX) {
+ GDL_LOGXE_DRW(link_id, "type=%d, n_rec=%d, rec_point=%d",
+ p_list->type, p_list->n_item, rec_point);
+ p_list->n_item = GPS_DL_HIST_REC_RW_ITEM_MAX;
+ }
+
+ if (p_list->n_item == GPS_DL_HIST_REC_RW_ITEM_MAX)
+ gps_dl_hist_rec_rw_do_dump(link_id, p_list, GPS_DL_HIST_REC_RW_DUMP_ON_REC_FULL);
+}
+
+static void gps_dl_hist_rec_rw_add_rec(enum gps_dl_link_id_enum link_id,
+ enum gps_dl_hist_rec_rw_type type,
+ enum gps_dl_hist_rec_rw_rec_point rec_point,
+ int pid, int len)
+{
+ struct gps_dl_hist_rec_rw_list *p_list;
+ struct gps_dl_hist_rec_rw_item *p_item;
+ enum gps_dl_hist_rec_rw_rec_point last_point;
+
+ ASSERT_LINK_ID(link_id, GDL_VOIDF());
+ /* TODO: check type & rec_point */
+
+ /* TODO: protect it by lock */
+ p_list = &g_gps_dl_hist_rec_rw_list[link_id][type];
+ if (p_list->pid == 0)
+ p_list->pid = pid;
+ else if (pid != p_list->pid && rec_point == DRW_RETURN) {
+ gps_dl_hist_rec_rw_do_dump(link_id, p_list, GPS_DL_HIST_REC_RW_DUMP_ON_PID_CHANGED);
+ p_list->pid = pid;
+ }
+ gps_dl_hist_rec_rw_check_dump(link_id, p_list, rec_point);
+
+ p_item = &p_list->items[p_list->n_item];
+ last_point = p_list->rec_point;
+ p_list->rec_point = rec_point;
+
+ if (last_point == DRW_RETURN && rec_point == DRW_ENTER) {
+ /* TODO: record tiemstamp */
+ p_item->len = len;
+ } else if (last_point == DRW_ENTER && rec_point == DRW_RETURN) {
+ p_item->len = len;
+ p_list->n_item++;
+ if (len <= 0)
+ gps_dl_hist_rec_rw_do_dump(link_id, p_list, GPS_DL_HIST_REC_RW_DUMP_ON_PID_CHANGED);
+ else
+ gps_dl_hist_rec_rw_check_dump(link_id, p_list, DRW_RETURN);
+ } else {
+ GDL_LOGXE_DRW(link_id, "type=%d, n_rec=%d, mismatch rec_point=%d/%d, len=%d, pid=%d",
+ p_list->type, p_list->n_item, last_point, rec_point, len, pid);
+ }
+}
+
+
+void gps_each_link_rec_read(enum gps_dl_link_id_enum link_id, int pid, int len,
+ enum gps_dl_hist_rec_rw_rec_point rec_point)
+{
+ ASSERT_LINK_ID(link_id, GDL_VOIDF());
+ gps_each_link_mutex_take(link_id, GPS_DL_MTX_BIG_LOCK);
+ gps_dl_hist_rec_rw_add_rec(link_id, GPS_DL_HIST_REC_RW_READ, rec_point, pid, len);
+ gps_each_link_mutex_give(link_id, GPS_DL_MTX_BIG_LOCK);
+}
+
+void gps_each_link_rec_write(enum gps_dl_link_id_enum link_id, int pid, int len,
+ enum gps_dl_hist_rec_rw_rec_point rec_point)
+{
+ ASSERT_LINK_ID(link_id, GDL_VOIDF());
+ gps_each_link_mutex_take(link_id, GPS_DL_MTX_BIG_LOCK);
+ gps_dl_hist_rec_rw_add_rec(link_id, GPS_DL_HIST_REC_RW_WRITE, rec_point, pid, len);
+ gps_each_link_mutex_give(link_id, GPS_DL_MTX_BIG_LOCK);
+}
+
+void gps_each_link_rec_reset(enum gps_dl_link_id_enum link_id)
+{
+ enum gps_dl_hist_rec_rw_type type;
+ struct gps_dl_hist_rec_rw_list *p_list;
+
+ ASSERT_LINK_ID(link_id, GDL_VOIDF());
+ gps_each_link_mutex_take(link_id, GPS_DL_MTX_BIG_LOCK);
+ for (type = 0; type < GPS_DL_HIST_REC_RW_TYPE_MAX; type++) {
+ p_list = &g_gps_dl_hist_rec_rw_list[link_id][type];
+ memset(p_list, 0, sizeof(*p_list));
+ p_list->type = type;
+ p_list->rec_point = DRW_RETURN;
+ }
+ gps_each_link_mutex_give(link_id, GPS_DL_MTX_BIG_LOCK);
+}
+
+void gps_each_link_rec_force_dump(enum gps_dl_link_id_enum link_id)
+{
+ enum gps_dl_hist_rec_rw_type type;
+ struct gps_dl_hist_rec_rw_list *p_list;
+
+ ASSERT_LINK_ID(link_id, GDL_VOIDF());
+ gps_each_link_mutex_take(link_id, GPS_DL_MTX_BIG_LOCK);
+ for (type = 0; type < GPS_DL_HIST_REC_RW_TYPE_MAX; type++) {
+ p_list = &g_gps_dl_hist_rec_rw_list[link_id][type];
+ gps_dl_hist_rec_rw_do_dump(link_id, p_list, GPS_DL_HIST_REC_RW_DUMP_ON_FORCE_DUMP);
+ }
+ gps_each_link_mutex_give(link_id, GPS_DL_MTX_BIG_LOCK);
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/gps_dl_lib_misc.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/gps_dl_lib_misc.c
new file mode 100644
index 0000000..7f1f00c
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/gps_dl_lib_misc.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_lib_misc.h"
+#include "gps_dl_log.h"
+
+bool gps_dl_hal_comp_buf_match(unsigned char *data_buf, unsigned int data_len,
+ unsigned char *golden_buf, unsigned int golden_len, unsigned int data_shift) {
+ bool is_match = true;
+
+ int i;
+
+ if (data_len < golden_len + data_shift) {
+ GDL_LOGD("not match len: %d, %d, %d", data_len, golden_len, data_shift);
+ is_match = false;
+ }
+
+ if (is_match) {
+ for (i = 0; i < data_shift; i++) {
+ if (data_buf[i] != 0) {
+ GDL_LOGD("not fill 0 on start %d: %x", i, data_buf[i]);
+ is_match = false;
+ break;
+ }
+ }
+ }
+
+ if (is_match) {
+ for (; i < data_shift + golden_len; i++) {
+ if (data_buf[i] != golden_buf[i - data_shift]) {
+ GDL_LOGD("not match on data[%d] -> %x, gold[%d] -> %x",
+ i, data_buf[i], i - data_shift, golden_buf[i - data_shift]);
+ is_match = false;
+ break;
+ }
+ }
+ }
+
+ if (is_match) {
+ for (; i < data_len; i++) {
+ if (data_buf[i] != 0) {
+ GDL_LOGD("not fill 0 on end %d: %x", i, data_buf[i]);
+ is_match = false;
+ break;
+ }
+ }
+ }
+
+ GDL_LOGD("match = %d, data_len = %d, golden_len = %d, data_shift = %d",
+ is_match, data_len, golden_len, data_shift);
+
+ if (!is_match) {
+ gps_dl_hal_show_buf("data", data_buf, data_len);
+ gps_dl_hal_show_buf("golden", golden_buf, golden_len);
+ }
+
+ return is_match;
+}
+
+#define SHOW_BUF_MAX_LINE 2
+void gps_dl_hal_show_buf(unsigned char *tag,
+ unsigned char *buf, unsigned int len)
+{
+ int base = 0, line_idx = 0;
+ int line_len = 8;
+ int left_len = len;
+#define SHOW_BUF_FMT0 "[%s] len = %u"
+#define SHOW_BUF_FMT1 SHOW_BUF_FMT0", data = %02x"
+#define SHOW_BUF_FMT2 SHOW_BUF_FMT1" %02x"
+#define SHOW_BUF_FMT3 SHOW_BUF_FMT2" %02x"
+#define SHOW_BUF_FMT4 SHOW_BUF_FMT3" %02x"
+#define SHOW_BUF_FMT5 SHOW_BUF_FMT4", %02x"
+#define SHOW_BUF_FMT6 SHOW_BUF_FMT5" %02x"
+#define SHOW_BUF_FMT7 SHOW_BUF_FMT6" %02x"
+#define SHOW_BUF_FMT8 SHOW_BUF_FMT7" %02x"
+
+#define SHOW_BUF_ARG0 do {GDL_LOGI_DRW(SHOW_BUF_FMT0, tag, len); } while (0)
+
+#define SHOW_BUF_ARG1 do {GDL_LOGI_DRW(SHOW_BUF_FMT1, tag, len, buf[base+0]); } while (0)
+
+#define SHOW_BUF_ARG2 do {GDL_LOGI_DRW(SHOW_BUF_FMT2, tag, len, buf[base+0], buf[base+1]); } while (0)
+
+#define SHOW_BUF_ARG3 do {GDL_LOGI_DRW(SHOW_BUF_FMT3, tag, len, buf[base+0], buf[base+1], buf[base+2]) \
+ ; } while (0)
+
+#define SHOW_BUF_ARG4 do {GDL_LOGI_DRW(SHOW_BUF_FMT4, tag, len, buf[base+0], buf[base+1], buf[base+2], \
+ buf[base+3]); } while (0)
+
+#define SHOW_BUF_ARG5 do {GDL_LOGI_DRW(SHOW_BUF_FMT5, tag, len, buf[base+0], buf[base+1], buf[base+2], \
+ buf[base+3], buf[base+4]); } while (0)
+
+#define SHOW_BUF_ARG6 do {GDL_LOGI_DRW(SHOW_BUF_FMT6, tag, len, buf[base+0], buf[base+1], buf[base+2], \
+ buf[base+3], buf[base+4], buf[base+5]); } while (0)
+
+#define SHOW_BUF_ARG7 do {GDL_LOGI_DRW(SHOW_BUF_FMT7, tag, len, buf[base+0], buf[base+1], buf[base+2], \
+ buf[base+3], buf[base+4], buf[base+5], buf[base+6]); } while (0)
+
+#define SHOW_BUF_ARG8 do {GDL_LOGI_DRW(SHOW_BUF_FMT8, tag, len, buf[base+0], buf[base+1], buf[base+2], \
+ buf[base+3], buf[base+4], buf[base+5], buf[base+6], buf[base+7]); } while (0)
+
+ for (left_len = len, base = 0, line_idx = 0;
+ left_len > 0 && line_idx < SHOW_BUF_MAX_LINE;
+ left_len -= 8, base += 8, line_idx++) {
+
+ if (left_len > 8)
+ line_len = 8;
+ else
+ line_len = left_len;
+
+ switch (line_len) {
+#if 0
+ /* case 0 is impossible */
+ case 0:
+ SHOW_BUF_ARG0; break;
+#endif
+ case 1:
+ SHOW_BUF_ARG1; break;
+ case 2:
+ SHOW_BUF_ARG2; break;
+ case 3:
+ SHOW_BUF_ARG3; break;
+ case 4:
+ SHOW_BUF_ARG4; break;
+ case 5:
+ SHOW_BUF_ARG5; break;
+ case 6:
+ SHOW_BUF_ARG6; break;
+ case 7:
+ SHOW_BUF_ARG7; break;
+ default:
+ SHOW_BUF_ARG8; break;
+ }
+ }
+}
+
+void GDL_VOIDF(void) {}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/gps_dl_name_list.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/gps_dl_name_list.c
new file mode 100644
index 0000000..b22a25b
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/gps_dl_name_list.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+
+#include "gps_dl_base.h"
+#include "gps_dl_name_list.h"
+
+#if GPS_DL_ON_LINUX
+/* Make sure num for RETURN_NAME_IN_LIST is const to detect coding error such
+ * as swapping the position of num and index.
+ * MASK_BE_CONST can be empty if compiler not support the macros used.
+ */
+#define MUST_BE_CONST(num) BUILD_BUG_ON(!__builtin_constant_p(num))
+#else
+#define MUST_BE_CONST(num)
+#endif
+#define NAME_ON_NULL "(NULL)"
+#define RETURN_NAME_IN_LIST(list, num, index, retval) \
+ do { \
+ MUST_BE_CONST(num); \
+ if (((index) >= 0) && ((index) < (num))) { \
+ if ((list)[index]) \
+ retval = (list)[index]; \
+ else { \
+ GDL_LOGW("name is null for index: %d", index); \
+ retval = NAME_ON_NULL; \
+ } \
+ } else { \
+ GDL_LOGW("name index: %d out of range", index); \
+ retval = (list)[num]; \
+ } \
+ } while (0)
+
+
+const char *const gps_dl_ret_name_list[GDL_RET_NUM + 1] = {
+ [GDL_OKAY] = "OKAY",
+ [GDL_FAIL] = "FAIL_GENERAL",
+ [GDL_FAIL_ASSERT] = "FAIL_ASSERT",
+ [GDL_FAIL_BUSY] = "FAIL_BUSY",
+ [GDL_FAIL_NOSPACE] = "FAIL_NOSPACE",
+ [GDL_FAIL_NOSPACE_PENDING_RX] = "FAIL_NOSPACE_PENDING_RX",
+ [GDL_FAIL_NODATA] = "FAIL_NODATA",
+ [GDL_FAIL_STATE_MISMATCH] = "FAIL_STATE_MISMATCH",
+ [GDL_FAIL_SIGNALED] = "FAIL_SIGNALED",
+ [GDL_FAIL_TIMEOUT] = "FAIL_TIMEOUT",
+ [GDL_FAIL_NOT_SUPPORT] = "FAIL_NOT_SUPPORT",
+ [GDL_FAIL_INVAL] = "FAIL_INVAL",
+ [GDL_FAIL_NOENTRY] = "FAIL_NOENTRY",
+ [GDL_FAIL_NOENTRY2] = "FAIL_NOENTRY2",
+ [GDL_FAIL_CONN_NOT_OKAY] = "FAIL_CONN_NOT_OKAY",
+ [GDL_RET_NUM] = "FAIL_UNKNOWN"
+};
+
+const char *gdl_ret_to_name(enum GDL_RET_STATUS gdl_ret)
+{
+ const char *retval;
+
+ RETURN_NAME_IN_LIST(gps_dl_ret_name_list, GDL_RET_NUM, gdl_ret, retval);
+ return retval;
+}
+
+
+const char *const gps_dl_dsp_state_name_list[GPS_DSP_ST_MAX + 1] = {
+ [GPS_DSP_ST_OFF] = "OFF ",
+ [GPS_DSP_ST_TURNED_ON] = "ON ",
+ [GPS_DSP_ST_RESET_DONE] = "RST ",
+ [GPS_DSP_ST_WORKING] = "WORK",
+ [GPS_DSP_ST_HW_SLEEP_MODE] = "SLP ",
+ [GPS_DSP_ST_HW_STOP_MODE] = "STOP",
+ [GPS_DSP_ST_WAKEN_UP] = "WAKE",
+ [GPS_DSP_ST_MAX] = "UNKN"
+};
+
+const char *gps_dl_dsp_state_name(enum gps_dsp_state_t state)
+{
+ const char *retval;
+
+ RETURN_NAME_IN_LIST(gps_dl_dsp_state_name_list, GPS_DSP_ST_MAX, state, retval);
+ return retval;
+}
+
+
+const char *const gps_dl_dsp_event_name_list[GPS_DSP_EVT_MAX + 1] = {
+ [GPS_DSP_EVT_FUNC_OFF] = "FUNC_OFF",
+ [GPS_DSP_EVT_FUNC_ON] = "FUNC_ON ",
+ [GPS_DSP_EVT_RESET_DONE] = "RST_DONE",
+ [GPS_DSP_EVT_RAM_CODE_READY] = "RAM_OKAY",
+ [GPS_DSP_EVT_CTRL_TIMER_EXPIRE] = "TIMEOUT ",
+ [GPS_DSP_EVT_HW_SLEEP_REQ] = "SLP_REQ ",
+ [GPS_DSP_EVT_HW_SLEEP_EXIT] = "SLP_WAK ",
+ [GPS_DSP_EVT_HW_STOP_REQ] = "STOP_REQ",
+ [GPS_DSP_EVT_HW_STOP_EXIT] = "STOP_WAK",
+ [GPS_DSP_EVT_MAX] = "UNKNOWN "
+};
+
+const char *gps_dl_dsp_event_name(enum gps_dsp_event_t event)
+{
+ const char *retval;
+
+ RETURN_NAME_IN_LIST(gps_dl_dsp_event_name_list, GPS_DSP_EVT_MAX, event, retval);
+ return retval;
+}
+
+
+const char * const gps_dl_link_state_name_list[LINK_STATE_NUM + 1] = {
+ [LINK_UNINIT] = "UNINIT",
+ [LINK_CLOSED] = "CLOSED",
+ [LINK_OPENING] = "OPENING",
+ [LINK_OPENED] = "OPENED",
+ [LINK_CLOSING] = "CLOSING",
+ [LINK_RESETTING] = "RESETTING",
+ [LINK_RESET_DONE] = "RESET_DONE",
+ [LINK_DISABLED] = "DISABLED",
+ [LINK_SUSPENDING] = "SUSPNEDING",
+ [LINK_SUSPENDED] = "SUSPENDED",
+ [LINK_RESUMING] = "RESUMING",
+ /* [LNK_INIT_FAIL] = "INIT_FAIL", */
+ [LINK_STATE_NUM] = "INVALID"
+};
+
+const char *gps_dl_link_state_name(enum gps_each_link_state_enum state)
+{
+ const char *retval;
+
+ RETURN_NAME_IN_LIST(gps_dl_link_state_name_list, LINK_STATE_NUM, state, retval);
+ return retval;
+}
+
+
+const char *const gps_dl_link_event_name_list[GPS_DL_LINK_EVT_NUM + 1] = {
+ [GPS_DL_EVT_LINK_OPEN] = "LINK_OPEN",
+ [GPS_DL_EVT_LINK_CLOSE] = "LINK_CLOSE",
+ [GPS_DL_EVT_LINK_WRITE] = "LINK_WRITE",
+ [GPS_DL_EVT_LINK_READ] = "LINK_READ",
+ [GPS_DL_EVT_LINK_DSP_ROM_READY_TIMEOUT] = "ROM_READY_TIMEOUT",
+ [GPS_DL_EVT_LINK_DSP_FSM_TIMEOUT] = "DSP_FSM_TIMEOUT",
+ [GPS_DL_EVT_LINK_RESET_DSP] = "RESET_DSP",
+ [GPS_DL_EVT_LINK_RESET_GPS] = "RESET_GPS",
+ [GPS_DL_EVT_LINK_PRE_CONN_RESET] = "PRE_CONN_RESET",
+ [GPS_DL_EVT_LINK_POST_CONN_RESET] = "POST_CONN_RESET",
+ [GPS_DL_EVT_LINK_PRINT_HW_STATUS] = "PRINT_HW_STATUS",
+ [GPS_DL_EVT_LINK_ENTER_DPSLEEP] = "ENTER_DPSLEEP",
+ [GPS_DL_EVT_LINK_LEAVE_DPSLEEP] = "LEAVE_DPSLEEP",
+ [GPS_DL_EVT_LINK_ENTER_DPSTOP] = "ENTER_DPSTOP",
+ [GPS_DL_EVT_LINK_LEAVE_DPSTOP] = "LEAVE_DPSTOP",
+ [GPS_DL_EVT_LINK_PRINT_DATA_STATUS] = "PRINT_DATA_STATUS",
+ [GPS_DL_LINK_EVT_NUM] = "LINK_INVALID_EVT"
+};
+
+const char *gps_dl_link_event_name(enum gps_dl_link_event_id event)
+{
+ const char *retval;
+
+ RETURN_NAME_IN_LIST(gps_dl_link_event_name_list, GPS_DL_LINK_EVT_NUM, event, retval);
+ return retval;
+}
+
+const char *gps_dl_hal_event_name_list[GPD_DL_HAL_EVT_NUM + 1] = {
+ [GPS_DL_HAL_EVT_A2D_TX_DMA_DONE] = "HAL_TX_DMA_DONE",
+ [GPS_DL_HAL_EVT_D2A_RX_HAS_DATA] = "HAL_RX_HAS_DATA",
+ [GPS_DL_HAL_EVT_D2A_RX_HAS_NODATA] = "HAL_RX_HAS_NODATA",
+ [GPS_DL_HAL_EVT_D2A_RX_DMA_DONE] = "HAL_RX_DMA_DONE",
+ [GPS_DL_HAL_EVT_MCUB_HAS_IRQ] = "HAL_MCUB_HAS_FLAG",
+ [GPS_DL_HAL_EVT_DMA_ISR_PENDING] = "HAL_DMA_ISR_PENDING",
+ [GPD_DL_HAL_EVT_NUM] = "HAL_INVALID_EVT",
+};
+
+const char *gps_dl_hal_event_name(enum gps_dl_hal_event_id event)
+{
+ const char *retval;
+
+ RETURN_NAME_IN_LIST(gps_dl_hal_event_name_list, GPD_DL_HAL_EVT_NUM, event, retval);
+ return retval;
+}
+
+const char *const gps_dl_waitable_name_list[GPS_DL_WAIT_NUM + 1] = {
+ [GPS_DL_WAIT_OPEN_CLOSE] = "OPEN_OR_CLOSE",
+ [GPS_DL_WAIT_WRITE] = "WRITE",
+ [GPS_DL_WAIT_READ] = "READ",
+ [GPS_DL_WAIT_RESET] = "RESET",
+ [GPS_DL_WAIT_NUM] = "INVALID"
+};
+
+const char *gps_dl_waitable_type_name(enum gps_each_link_waitable_type type)
+{
+ const char *retval;
+
+ RETURN_NAME_IN_LIST(gps_dl_waitable_name_list, GPS_DL_WAIT_NUM, type, retval);
+ return retval;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/gps_dl_time_tick.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/gps_dl_time_tick.c
new file mode 100644
index 0000000..7b6a20d
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/gps_dl_time_tick.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+#include "gps_dl_time_tick.h"
+
+#if GPS_DL_ON_LINUX
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#elif GPS_DL_ON_CTP
+#include "kernel_to_ctp.h"
+#endif
+
+void gps_dl_wait_us(unsigned int us)
+{
+#if GPS_DL_ON_LINUX
+ udelay(us);
+#elif GPS_DL_ON_CTP
+ udelay(us); /* GPT_Delay_us(us); */
+#endif
+}
+
+unsigned long gps_dl_tick_get(void)
+{
+#if GPS_DL_ON_LINUX
+ return jiffies;
+#elif GPS_DL_ON_CTP
+ return GPT_GetTickCount(0);
+#else
+ return 0;
+#endif
+}
+
+int gps_dl_tick_delta_to_usec(unsigned int tick0, unsigned int tick1)
+{
+#if GPS_DL_ON_LINUX
+ return (int)((tick1 - tick0) * 1000 * 1000 / HZ);
+#elif GPS_DL_ON_CTP
+ return (int)((tick1 - tick0) / 13);
+#else
+ return 0;
+#endif
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/inc/gps_dl_base.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/inc/gps_dl_base.h
new file mode 100644
index 0000000..79e079d
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/inc/gps_dl_base.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_BASE_H
+#define _GPS_DL_BASE_H
+
+enum GDL_RET_STATUS {
+ GDL_OKAY = 0,
+ GDL_FAIL, /* general fail */
+ GDL_FAIL_ASSERT,
+ GDL_FAIL_BUSY,
+ GDL_FAIL_NOSPACE,
+ GDL_FAIL_NODATA,
+ GDL_FAIL_STATE_MISMATCH,
+ GDL_FAIL_SIGNALED,
+ GDL_FAIL_TIMEOUT,
+ GDL_FAIL_NOT_SUPPORT,
+ GDL_FAIL_INVAL,
+ GDL_FAIL_NOSPACE_PENDING_RX,
+ GDL_FAIL_NOENTRY,
+ GDL_FAIL_NOENTRY2,
+ GDL_FAIL_CONN_NOT_OKAY,
+ GDL_RET_NUM,
+};
+
+const char *gdl_ret_to_name(enum GDL_RET_STATUS gdl_ret);
+
+#endif /* _GPS_DL_BASE_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/inc/gps_dl_dma_buf.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/inc/gps_dl_dma_buf.h
new file mode 100644
index 0000000..b7f53de
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/inc/gps_dl_dma_buf.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_DMA_BUF_H
+#define _GPS_DL_DMA_BUF_H
+
+#include "gps_dl_config.h"
+
+#if GPS_DL_ON_LINUX
+#include "linux/semaphore.h"
+#include "linux/dma-mapping.h"
+#elif GPS_DL_ON_CTP
+#include "kernel_to_ctp.h"
+#include "gps_dl_ctp_osal.h"
+#endif
+
+#include "gps_dl_base.h"
+
+enum gps_dl_dma_dir {
+ GDL_DMA_A2D,
+ GDL_DMA_D2A,
+ GDL_DMA_DIR_NUM
+};
+
+/* for lock free structure */
+struct gdl_dma_buf_idx {
+ unsigned int rd_idx;
+ unsigned int wr_idx;
+};
+
+#if GPS_DL_ON_LINUX
+struct gdl_dma_lock {
+ struct semaphore internal_lock;
+};
+
+enum GDL_RET_STATUS gdl_dma_lock_init(struct gdl_dma_lock *p_lock);
+enum GDL_RET_STATUS gdl_dma_lock_take(struct gdl_dma_lock *p_lock);
+enum GDL_RET_STATUS gdl_dma_lock_give(struct gdl_dma_lock *p_lock);
+void gdl_dma_lock_deinit(struct gdl_dma_lock *p_lock);
+#endif
+
+struct gdl_dma_buf_entry {
+ void *vir_addr;
+#if GPS_DL_ON_LINUX
+ dma_addr_t phy_addr;
+#else
+ unsigned int phy_addr;
+#endif
+ unsigned int read_index;
+ unsigned int write_index;
+ unsigned int buf_length;
+ bool is_valid;
+ bool is_nodata;
+};
+
+#if GPS_DL_ON_LINUX
+/* if set to 2, it likes not use multi entry */
+#define GPS_DL_DMA_BUF_ENTRY_MAX (2)
+#else
+#define GPS_DL_DMA_BUF_ENTRY_MAX (4)
+#endif
+struct gps_dl_dma_buf {
+ int dev_index;
+ enum gps_dl_dma_dir dir;
+ unsigned int len;
+
+ void *vir_addr;
+#if GPS_DL_ON_LINUX
+ dma_addr_t phy_addr;
+#else
+ unsigned int phy_addr;
+#endif
+ unsigned int read_index;
+ unsigned int write_index;
+ unsigned int transfer_max;
+ bool writer_working;
+ bool reader_working;
+
+ /* TODO: better way is put it to LINK rather than dma_buf */
+ bool has_pending_rx;
+
+ struct gdl_dma_buf_entry dma_working_entry;
+ struct gdl_dma_buf_entry data_entries[GPS_DL_DMA_BUF_ENTRY_MAX];
+ unsigned int entry_r;
+ unsigned int entry_w;
+
+#if 0
+ struct gdl_dma_buf_idx reader;
+ struct gdl_dma_buf_idx writer;
+ struct gdl_dma_lock lock;
+#endif
+};
+
+
+struct gdl_hw_dma_transfer {
+ unsigned int buf_start_addr;
+ unsigned int transfer_start_addr;
+ unsigned int len_to_wrap;
+ unsigned int transfer_max_len;
+};
+
+int gps_dl_dma_buf_alloc(struct gps_dl_dma_buf *p_dma_buf, enum gps_dl_link_id_enum link_id,
+ enum gps_dl_dma_dir dir, unsigned int len);
+void gps_dma_buf_reset(struct gps_dl_dma_buf *p_dma);
+void gps_dma_buf_show(struct gps_dl_dma_buf *p_dma, bool is_warning);
+void gps_dma_buf_align_as_byte_mode(struct gps_dl_dma_buf *p_dma);
+bool gps_dma_buf_is_empty(struct gps_dl_dma_buf *p_dma);
+
+/* enum GDL_RET_STATUS gdl_dma_buf_init(struct gps_dl_dma_buf *p_dma); */
+/* enum GDL_RET_STATUS gdl_dma_buf_deinit(struct gps_dl_dma_buf *p_dma); */
+
+enum GDL_RET_STATUS gdl_dma_buf_put(struct gps_dl_dma_buf *p_dma,
+ const unsigned char *p_buf, unsigned int buf_len);
+
+enum GDL_RET_STATUS gdl_dma_buf_get(struct gps_dl_dma_buf *p_dma,
+ unsigned char *p_buf, unsigned int buf_len, unsigned int *p_data_len,
+ bool *p_is_nodata);
+
+
+enum GDL_RET_STATUS gdl_dma_buf_get_data_entry(struct gps_dl_dma_buf *p_dma,
+ struct gdl_dma_buf_entry *p_entry);
+
+enum GDL_RET_STATUS gdl_dma_buf_set_data_entry(struct gps_dl_dma_buf *p_dma,
+ struct gdl_dma_buf_entry *p_entry);
+
+enum GDL_RET_STATUS gdl_dma_buf_get_free_entry(struct gps_dl_dma_buf *p_dma,
+ struct gdl_dma_buf_entry *p_entry, bool nospace_set_pending_rx);
+
+enum GDL_RET_STATUS gdl_dma_buf_set_free_entry(struct gps_dl_dma_buf *p_dma,
+ struct gdl_dma_buf_entry *p_entry);
+
+
+enum GDL_RET_STATUS gdl_dma_buf_entry_to_buf(const struct gdl_dma_buf_entry *p_entry,
+ unsigned char *p_buf, unsigned int buf_len, unsigned int *p_data_len);
+
+enum GDL_RET_STATUS gdl_dma_buf_buf_to_entry(const struct gdl_dma_buf_entry *p_entry,
+ const unsigned char *p_buf, unsigned int data_len, unsigned int *p_write_index);
+
+enum GDL_RET_STATUS gdl_dma_buf_entry_to_transfer(
+ const struct gdl_dma_buf_entry *p_entry,
+ struct gdl_hw_dma_transfer *p_transfer, bool is_tx);
+
+enum GDL_RET_STATUS gdl_dma_buf_entry_transfer_left_to_write_index(
+ const struct gdl_dma_buf_entry *p_entry,
+ unsigned int left_len, unsigned int *p_write_index);
+
+#endif /* _GPS_DL_DMA_BUF_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/inc/gps_dl_hist_rec.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/inc/gps_dl_hist_rec.h
new file mode 100644
index 0000000..8573f87
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/inc/gps_dl_hist_rec.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef _GPS_DL_HIST_REC_H
+#define _GPS_DL_HIST_REC_H
+
+#include "gps_dl_config.h"
+
+enum gps_dl_hist_rec_rw_rec_point {
+ DRW_ENTER,
+ DRW_RETURN
+};
+
+void gps_each_link_rec_read(enum gps_dl_link_id_enum link_id, int pid, int len,
+ enum gps_dl_hist_rec_rw_rec_point rec_point);
+void gps_each_link_rec_write(enum gps_dl_link_id_enum link_id, int pid, int len,
+ enum gps_dl_hist_rec_rw_rec_point rec_point);
+void gps_each_link_rec_reset(enum gps_dl_link_id_enum link_id);
+void gps_each_link_rec_force_dump(enum gps_dl_link_id_enum link_id);
+
+#endif /* _GPS_DL_HIST_REC_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/inc/gps_dl_lib_misc.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/inc/gps_dl_lib_misc.h
new file mode 100644
index 0000000..2ee1830
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/inc/gps_dl_lib_misc.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_LIB_MISC_H
+#define _GPS_DL_LIB_MISC_H
+
+#include "gps_dl_config.h"
+#include "gps_dl_base.h"
+#if GPS_DL_ON_LINUX
+#include <linux/types.h> /* for bool */
+#endif
+
+void gps_dl_hal_show_buf(unsigned char *tag,
+ unsigned char *buf, unsigned int len);
+
+bool gps_dl_hal_comp_buf_match(unsigned char *data_buf, unsigned int data_len,
+ unsigned char *golden_buf, unsigned int golden_len, unsigned int data_shift);
+
+#endif /* _GPS_DL_LIB_MISC_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/inc/gps_dl_name_list.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/inc/gps_dl_name_list.h
new file mode 100644
index 0000000..6e8217f
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/inc/gps_dl_name_list.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_NAME_LIST_H
+#define _GPS_DL_NAME_LIST_H
+
+#include "gps_dl_config.h"
+
+#include "gps_each_link.h"
+#include "gps_dl_hal_api.h"
+#include "gps_dsp_fsm.h"
+#include "gps_dl_base.h"
+
+const char *gps_dl_dsp_state_name(enum gps_dsp_state_t state);
+const char *gps_dl_dsp_event_name(enum gps_dsp_event_t event);
+
+const char *gps_dl_link_state_name(enum gps_each_link_state_enum state);
+const char *gps_dl_link_event_name(enum gps_dl_link_event_id event);
+const char *gps_dl_hal_event_name(enum gps_dl_hal_event_id event);
+
+const char *gps_dl_waitable_type_name(enum gps_each_link_waitable_type type);
+
+#endif /* _GPS_DL_NAME_LIST_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/inc/gps_dl_time_tick.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/inc/gps_dl_time_tick.h
new file mode 100644
index 0000000..7ec941c
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/lib/inc/gps_dl_time_tick.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_TIME_TICK_H
+#define _GPS_DL_TIME_TICK_H
+
+#define GPS_DL_RW_NO_TIMEOUT (-1)
+void gps_dl_wait_us(unsigned int us);
+#define GDL_WAIT_US(Usec) gps_dl_wait_us(Usec)
+unsigned long gps_dl_tick_get(void);
+int gps_dl_tick_delta_to_usec(unsigned int tick0, unsigned int tick1);
+
+#endif /* _GPS_DL_TIME_TICK_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/link/gps_dl_subsys_reset.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/link/gps_dl_subsys_reset.c
new file mode 100644
index 0000000..b46058e
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/link/gps_dl_subsys_reset.c
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+
+#include "gps_dl_context.h"
+#include "gps_dl_subsys_reset.h"
+#include "gps_each_link.h"
+#include "gps_dl_name_list.h"
+#include "gps_dl_hw_api.h"
+
+#if GPS_DL_HAS_CONNINFRA_DRV
+#include "conninfra.h"
+#endif
+
+bool gps_dl_reset_level_is_none(enum gps_dl_link_id_enum link_id)
+{
+ struct gps_each_link *p = gps_dl_link_get(link_id);
+ enum gps_each_link_state_enum state;
+ enum gps_each_link_reset_level level;
+ bool is_none;
+
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ state = p->state_for_user;
+ level = p->reset_level;
+ is_none = (level == GPS_DL_RESET_LEVEL_NONE);
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+
+ if (!is_none)
+ GDL_LOGW("state = %s, level = %d", gps_dl_link_state_name(state), level);
+
+ return is_none;
+}
+
+enum GDL_RET_STATUS gps_dl_reset_level_set_and_trigger(
+ enum gps_each_link_reset_level level, bool wait_reset_done)
+{
+ enum gps_dl_link_id_enum link_id;
+ struct gps_each_link *p;
+ enum gps_each_link_state_enum old_state, new_state;
+ enum gps_each_link_reset_level old_level, new_level;
+ bool need_wait[GPS_DATA_LINK_NUM] = {false};
+ bool to_send_reset_event;
+ long sigval;
+ enum GDL_RET_STATUS wait_status;
+
+ if (level != GPS_DL_RESET_LEVEL_GPS_SUBSYS && level != GPS_DL_RESET_LEVEL_CONNSYS) {
+ GDL_LOGW("level = %d, do nothing and return", level);
+ return GDL_FAIL_INVAL;
+ }
+
+ if (wait_reset_done)
+ ; /* TODO: take mutex to allow pending more waiter */
+
+ for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) {
+ p = gps_dl_link_get(link_id);
+ to_send_reset_event = false;
+
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ old_state = p->state_for_user;
+ old_level = p->reset_level;
+
+ switch (old_state) {
+ case LINK_CLOSED:
+ need_wait[link_id] = false;
+ p->state_for_user = LINK_DISABLED;
+ p->reset_level = level;
+
+ /* Send reset event to ctld:
+ *
+ * for GPS_DL_RESET_LEVEL_GPS_SUBSYS ctrld do nothing but
+ * just change state from DISABLED back to CLOSED
+ *
+ * for GPS_DL_RESET_LEVEL_CONNSYS ctrld do nothing but
+ * just change state from DISABLED state back to CLOSED
+ */
+ to_send_reset_event = true;
+ break;
+
+ case LINK_OPENING:
+ case LINK_OPENED:
+ case LINK_CLOSING:
+ case LINK_RESET_DONE:
+ case LINK_RESUMING:
+ case LINK_SUSPENDING:
+ case LINK_SUSPENDED:
+ need_wait[link_id] = true;
+ p->state_for_user = LINK_RESETTING;
+ p->reset_level = level;
+ to_send_reset_event = true;
+ break;
+
+ case LINK_RESETTING:
+ need_wait[link_id] = true;
+ if (old_level < level)
+ p->reset_level = level;
+ break;
+
+ case LINK_DISABLED:
+ case LINK_UNINIT:
+ need_wait[link_id] = false;
+ break;
+
+ default:
+ need_wait[link_id] = false;
+ break;
+ }
+
+ new_state = p->state_for_user;
+ new_level = p->reset_level;
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+
+ if (to_send_reset_event) {
+ gps_dl_link_waitable_reset(link_id, GPS_DL_WAIT_RESET);
+ if (level == GPS_DL_RESET_LEVEL_CONNSYS)
+ gps_dl_link_event_send(GPS_DL_EVT_LINK_PRE_CONN_RESET, link_id);
+ else
+ gps_dl_link_event_send(GPS_DL_EVT_LINK_RESET_GPS, link_id);
+ }
+
+ GDL_LOGXE_STA(link_id,
+ "state change: %s -> %s, level = %d (%d -> %d), is_sent = %d, to_wait = %d",
+ gps_dl_link_state_name(old_state), gps_dl_link_state_name(new_state),
+ level, old_level, new_level,
+ to_send_reset_event, need_wait[link_id]);
+ }
+
+ if (!wait_reset_done) {
+ GDL_LOGE("force no wait");
+ return GDL_OKAY;
+ }
+
+ for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) {
+ if (!need_wait[link_id])
+ continue;
+
+ sigval = 0;
+ p = gps_dl_link_get(link_id);
+ wait_status = gps_dl_link_wait_on(&p->waitables[GPS_DL_WAIT_RESET], &sigval);
+ if (wait_status == GDL_FAIL_SIGNALED) {
+ GDL_LOGXE(link_id, "sigval = %ld", sigval);
+ return GDL_FAIL_SIGNALED;
+ }
+
+ GDL_LOGXE(link_id, "wait ret = %s", gdl_ret_to_name(wait_status));
+ }
+
+ if (wait_reset_done)
+ ; /* TODO: take mutex to allow pending more waiter */
+
+ return GDL_OKAY;
+}
+
+int gps_dl_trigger_gps_subsys_reset(bool wait_reset_done)
+{
+ enum GDL_RET_STATUS ret_status;
+
+ ret_status = gps_dl_reset_level_set_and_trigger(GPS_DL_RESET_LEVEL_GPS_SUBSYS, wait_reset_done);
+ if (ret_status != GDL_OKAY) {
+ GDL_LOGE("status %s is not okay, return -1", gdl_ret_to_name(ret_status));
+ return -1;
+ }
+ return 0;
+}
+
+void gps_dl_trigger_gps_print_hw_status(void)
+{
+ GDL_LOGE("");
+ gps_dl_link_event_send(GPS_DL_EVT_LINK_PRINT_HW_STATUS, GPS_DATA_LINK_ID0);
+ gps_dl_link_event_send(GPS_DL_EVT_LINK_PRINT_HW_STATUS, GPS_DATA_LINK_ID1);
+}
+
+void gps_dl_trigger_gps_print_data_status(void)
+{
+ GDL_LOGE("");
+ gps_dl_link_event_send(GPS_DL_EVT_LINK_PRINT_DATA_STATUS, GPS_DATA_LINK_ID0);
+ gps_dl_link_event_send(GPS_DL_EVT_LINK_PRINT_DATA_STATUS, GPS_DATA_LINK_ID1);
+}
+
+void gps_dl_handle_connsys_reset_done(void)
+{
+ enum gps_dl_link_id_enum link_id;
+ struct gps_each_link *p;
+ enum gps_each_link_state_enum state;
+ enum gps_each_link_reset_level level;
+ bool to_send_reset_event;
+
+ for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) {
+ p = gps_dl_link_get(link_id);
+ to_send_reset_event = false;
+
+ gps_each_link_spin_lock_take(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+ state = p->state_for_user;
+ level = p->reset_level;
+
+ if (level == GPS_DL_RESET_LEVEL_CONNSYS) {
+ if (state == LINK_DISABLED || state == LINK_RESETTING)
+ to_send_reset_event = true;
+ }
+ gps_each_link_spin_lock_give(link_id, GPS_DL_SPINLOCK_FOR_LINK_STATE);
+
+ if (to_send_reset_event)
+ gps_dl_link_event_send(GPS_DL_EVT_LINK_POST_CONN_RESET, link_id);
+
+ GDL_LOGXE_STA(link_id, "state check: %s, level = %d, is_sent = %d",
+ gps_dl_link_state_name(state), level, to_send_reset_event);
+ }
+}
+
+int gps_dl_trigger_connsys_reset(void)
+{
+#if GPS_DL_HAS_CONNINFRA_DRV
+ int ret;
+
+ GDL_LOGE("");
+ ret = conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_GPS, "GPS debug");
+ GDL_LOGE("conninfra_trigger_whole_chip_rst return = %d", ret);
+#else
+ GDL_LOGE("has no conninfra_drv");
+#endif
+ return 0;
+}
+
+#if GPS_DL_HAS_CONNINFRA_DRV
+static bool gps_dl_connsys_is_resetting;
+int gps_dl_on_pre_connsys_reset(enum consys_drv_type drv, char *reason)
+{
+ enum GDL_RET_STATUS ret_status;
+
+ GDL_LOGE("already in resetting = %d", gps_dl_connsys_is_resetting);
+ gps_dl_connsys_is_resetting = true;
+
+ ret_status = gps_dl_reset_level_set_and_trigger(GPS_DL_RESET_LEVEL_CONNSYS, true);
+
+ if (ret_status != GDL_OKAY) {
+ GDL_LOGE("status %s is not okay, return -1", gdl_ret_to_name(ret_status));
+ return -1;
+ }
+
+ return 0;
+}
+
+int gps_dl_on_post_connsys_reset(void)
+{
+ GDL_LOGE("already in resetting = %d", gps_dl_connsys_is_resetting);
+ gps_dl_connsys_is_resetting = false;
+
+ gps_dl_handle_connsys_reset_done();
+ return 0;
+}
+
+struct sub_drv_ops_cb gps_dl_conninfra_ops_cb;
+#endif
+
+void gps_dl_register_conninfra_reset_cb(void)
+{
+#if GPS_DL_HAS_CONNINFRA_DRV
+ memset(&gps_dl_conninfra_ops_cb, 0, sizeof(gps_dl_conninfra_ops_cb));
+ gps_dl_conninfra_ops_cb.rst_cb.pre_whole_chip_rst = gps_dl_on_pre_connsys_reset;
+ gps_dl_conninfra_ops_cb.rst_cb.post_whole_chip_rst = gps_dl_on_post_connsys_reset;
+
+ conninfra_sub_drv_ops_register(CONNDRV_TYPE_GPS, &gps_dl_conninfra_ops_cb);
+#endif
+}
+
+void gps_dl_unregister_conninfra_reset_cb(void)
+{
+#if GPS_DL_HAS_CONNINFRA_DRV
+ conninfra_sub_drv_ops_unregister(CONNDRV_TYPE_GPS);
+#endif
+}
+
+bool gps_dl_conninfra_is_readable(void)
+{
+#if GPS_DL_HAS_CONNINFRA_DRV
+ return (conninfra_reg_readable() != 0);
+#else
+ return true;
+#endif
+}
+
+void gps_dl_conninfra_not_readable_show_warning(unsigned int host_addr)
+{
+#if GPS_DL_HAS_CONNINFRA_DRV
+ int readable;
+ int hung_value = 0;
+
+ readable = conninfra_reg_readable();
+ if (readable)
+ return;
+
+ hung_value = conninfra_is_bus_hang();
+ GDL_LOGW("readable = %d, hung_value = %d, before access 0x%08x",
+ readable, hung_value, host_addr);
+#endif
+}
+
+bool gps_dl_conninfra_is_okay_or_handle_it(int *p_hung_value, bool dump_on_hung_value_zero)
+{
+#if GPS_DL_HAS_CONNINFRA_DRV
+ int readable;
+ int hung_value = 0;
+ bool trigger = false;
+ int trigger_ret = 0;
+ bool check_again;
+ int check_cnt = 0;
+
+ do {
+ check_again = false;
+ readable = conninfra_reg_readable();
+ if (readable) {
+ GDL_LOGD("readable = %d, okay", readable);
+ return true;
+ }
+
+ hung_value = conninfra_is_bus_hang();
+ if (p_hung_value != NULL)
+ *p_hung_value = hung_value;
+
+ /* hung_value > 0, need to trigger reset
+ * hung_value < 0, already in reset status
+ * hung_value = 0, connsys may not in proper status (such as conn_top_off is in sleep)
+ */
+ if (hung_value > 0) {
+ /* it's safe to cump gps host csr even hang value > 0 */
+ gps_dl_hw_dump_host_csr_gps_info(true);
+
+ trigger = true;
+ trigger_ret = conninfra_trigger_whole_chip_rst(
+ CONNDRV_TYPE_GPS, "GPS detect hung - case1");
+ } else if (hung_value == 0) {
+ if (dump_on_hung_value_zero)
+ gps_dl_hw_dump_host_csr_gps_info(true);
+ if (check_cnt < 1) {
+ /* readable = 0 and hung_value = 0 may not be a stable state,
+ * check again to double confirm
+ */
+ check_again = true;
+ } else {
+ /* trigger connsys reset if same result of checking again */
+ trigger = true;
+ trigger_ret = conninfra_trigger_whole_chip_rst(
+ CONNDRV_TYPE_GPS, "GPS detect hung - case2");
+ }
+ } else {
+ /* alreay in connsys resetting
+ * do nothing
+ */
+ }
+
+ check_cnt++;
+ GDL_LOGE("cnt=%d, readable=%d, hung_value=0x%x, trigger_reset=%d(%d,%d)",
+ check_cnt, readable, hung_value, trigger, trigger_ret, dump_on_hung_value_zero);
+ } while (check_again);
+ return false;
+#else
+ return true;
+#endif
+}
+
+
+bool g_gps_dl_test_mask_mcub_irq_on_open_flag[GPS_DATA_LINK_NUM];
+bool g_gps_dl_test_mask_hasdata_irq_flag[GPS_DATA_LINK_NUM];
+
+void gps_dl_test_mask_mcub_irq_on_open_set(enum gps_dl_link_id_enum link_id, bool mask)
+{
+ ASSERT_LINK_ID(link_id, GDL_VOIDF());
+
+ g_gps_dl_test_mask_mcub_irq_on_open_flag[link_id] = mask;
+}
+
+bool gps_dl_test_mask_mcub_irq_on_open_get(enum gps_dl_link_id_enum link_id)
+{
+ ASSERT_LINK_ID(link_id, false);
+
+ return g_gps_dl_test_mask_mcub_irq_on_open_flag[link_id];
+}
+
+void gps_dl_test_mask_hasdata_irq_set(enum gps_dl_link_id_enum link_id, bool mask)
+{
+ ASSERT_LINK_ID(link_id, GDL_VOIDF());
+
+ g_gps_dl_test_mask_hasdata_irq_flag[link_id] = mask;
+}
+
+bool gps_dl_test_mask_hasdata_irq_get(enum gps_dl_link_id_enum link_id)
+{
+ ASSERT_LINK_ID(link_id, false);
+
+ return g_gps_dl_test_mask_hasdata_irq_flag[link_id];
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/link/inc/gps_dl_subsys_reset.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/link/inc/gps_dl_subsys_reset.h
new file mode 100644
index 0000000..1727444
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/link/inc/gps_dl_subsys_reset.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_SUBSYS_RESET_H
+#define _GPS_DL_SUBSYS_RESET_H
+
+#include "gps_dl_base.h"
+
+enum gps_each_link_reset_level {
+ GPS_DL_RESET_LEVEL_NONE,
+ GPS_DL_RESET_LEVEL_GPS_SINGLE_LINK,
+ GPS_DL_RESET_LEVEL_GPS_SUBSYS,
+ GPS_DL_RESET_LEVEL_CONNSYS,
+ GPS_DL_RESET_LEVEL_NUM
+};
+
+enum GDL_RET_STATUS gps_dl_reset_level_set_and_trigger(
+ enum gps_each_link_reset_level level, bool wait_reset_done);
+
+bool gps_dl_reset_level_is_none(enum gps_dl_link_id_enum link_id);
+bool gps_dl_reset_level_is_single(void);
+bool gps_dl_reset_level_gt_single(void);
+
+void gps_dl_trigger_gps_print_hw_status(void);
+void gps_dl_trigger_gps_print_data_status(void);
+int gps_dl_trigger_gps_subsys_reset(bool wait_reset_done);
+int gps_dl_trigger_connsys_reset(void);
+void gps_dl_handle_connsys_reset_done(void);
+
+void gps_dl_register_conninfra_reset_cb(void);
+void gps_dl_unregister_conninfra_reset_cb(void);
+
+bool gps_dl_conninfra_is_readable(void);
+void gps_dl_conninfra_not_readable_show_warning(unsigned int host_addr);
+bool gps_dl_conninfra_is_okay_or_handle_it(int *p_hung_value, bool dump_on_hung_value_zero);
+
+void gps_dl_test_mask_mcub_irq_on_open_set(enum gps_dl_link_id_enum link_id, bool mask);
+bool gps_dl_test_mask_mcub_irq_on_open_get(enum gps_dl_link_id_enum link_id);
+
+void gps_dl_test_mask_hasdata_irq_set(enum gps_dl_link_id_enum link_id, bool mask);
+bool gps_dl_test_mask_hasdata_irq_get(enum gps_dl_link_id_enum link_id);
+
+#endif /* _GPS_DL_SUBSYS_RESET_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_data_link_devices.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_data_link_devices.c
new file mode 100644
index 0000000..c9b7533
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_data_link_devices.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include <linux/dma-mapping.h>
+#include <linux/of_device.h>
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
+#include "gps_dl_config.h"
+#include "gps_dl_context.h"
+#include "gps_dl_hw_api.h"
+#include "gps_dl_isr.h"
+#include "gps_data_link_devices.h"
+#include "gps_each_link.h"
+#if GPS_DL_HAS_PLAT_DRV
+#include "gps_dl_linux_plat_drv.h"
+#include "gps_dl_linux_reserved_mem.h"
+#endif
+#if GPS_DL_MOCK_HAL
+#include "gps_mock_hal.h"
+#endif
+#include "gps_dl_procfs.h"
+#include "gps_dl_subsys_reset.h"
+
+#define GPS_DATA_LINK_DEV_NAME "gps_data_link_cdev"
+int gps_dl_devno_major;
+int gps_dl_devno_minor;
+
+void gps_dl_dma_buf_free(struct gps_dl_dma_buf *p_dma_buf, enum gps_dl_link_id_enum link_id)
+{
+ struct gps_each_device *p_dev;
+
+ p_dev = gps_dl_device_get(link_id);
+ if (p_dev == NULL) {
+ GDL_LOGXE_INI(link_id, "gps_dl_device_get return null");
+ return;
+ }
+
+ if (p_dma_buf->vir_addr)
+ dma_free_coherent(p_dev->dev,
+ p_dma_buf->len, p_dma_buf->vir_addr, p_dma_buf->phy_addr);
+
+ memset(p_dma_buf, 0, sizeof(*p_dma_buf));
+}
+
+int gps_dl_dma_buf_alloc(struct gps_dl_dma_buf *p_dma_buf, enum gps_dl_link_id_enum link_id,
+ enum gps_dl_dma_dir dir, unsigned int len)
+{
+ struct gps_each_device *p_dev;
+ struct device *p_linux_plat_dev;
+
+ p_dev = gps_dl_device_get(link_id);
+ if (p_dev == NULL) {
+ GDL_LOGXE_INI(link_id, "gps_dl_device_get return null");
+ return -1;
+ }
+
+ p_linux_plat_dev = (struct device *)p_dev->private_data;
+
+ memset(p_dma_buf, 0, sizeof(*p_dma_buf));
+ p_dma_buf->dev_index = link_id;
+ p_dma_buf->dir = dir;
+ p_dma_buf->len = len;
+
+ GDL_LOGI_INI("p_linux_plat_dev = 0x%p", p_linux_plat_dev);
+ if (p_linux_plat_dev == NULL) {
+ p_dma_buf->vir_addr = dma_zalloc_coherent(
+ p_dev->dev, len, &p_dma_buf->phy_addr, GFP_DMA | GFP_DMA32);
+ } else {
+ p_dma_buf->vir_addr = dma_zalloc_coherent(
+ p_linux_plat_dev, len, &p_dma_buf->phy_addr, GFP_DMA);/* | GFP_DMA32); */
+ }
+
+ GDL_LOGI_INI(
+#if GPS_DL_ON_LINUX
+ "alloc gps dl dma buf(%d,%d), addr: vir=0x%p, phy=0x%llx, len=%u",
+#else
+ "alloc gps dl dma buf(%d,%d), addr: vir=0x%p, phy=0x%08x, len=%u",
+#endif
+ p_dma_buf->dev_index, p_dma_buf->dir,
+ p_dma_buf->vir_addr, p_dma_buf->phy_addr, p_dma_buf->len);
+
+ if (NULL == p_dma_buf->vir_addr) {
+ GDL_LOGXE_INI(link_id,
+ "alloc gps dl dma buf(%d,%d)(len = %u) fail", link_id, dir, len);
+ /* force move forward even fail */
+ /* return -ENOMEM; */
+ }
+
+ return 0;
+}
+
+int gps_dl_dma_buf_alloc2(enum gps_dl_link_id_enum link_id)
+{
+ int retval;
+ struct gps_each_device *p_dev;
+ struct gps_each_link *p_link;
+
+ p_dev = gps_dl_device_get(link_id);
+ p_link = gps_dl_link_get(link_id);
+ if (p_dev == NULL) {
+ GDL_LOGXE_INI(link_id, "gps_dl_device_get return null");
+ return -1;
+ }
+
+ of_dma_configure(p_dev->dev, p_dev->dev->of_node, false);
+
+ if (!p_dev->dev->coherent_dma_mask)
+ p_dev->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+ if (!p_dev->dev->dma_mask)
+ p_dev->dev->dma_mask = &p_dev->dev->coherent_dma_mask;
+
+
+ retval = gps_dl_dma_buf_alloc(
+ &p_link->tx_dma_buf, link_id, GDL_DMA_A2D, p_link->cfg.tx_buf_size);
+
+ if (retval)
+ return retval;
+
+ retval = gps_dl_dma_buf_alloc(
+ &p_link->rx_dma_buf, link_id, GDL_DMA_D2A, p_link->cfg.rx_buf_size);
+
+ if (retval)
+ return retval;
+
+ return 0;
+}
+
+void gps_dl_ctx_links_deinit(void)
+{
+ enum gps_dl_link_id_enum link_id;
+
+ struct gps_each_device *p_dev;
+ struct gps_each_link *p_link;
+
+ for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) {
+ p_dev = gps_dl_device_get(link_id);
+ p_link = gps_dl_link_get(link_id);
+
+ if (gps_dl_reserved_mem_is_ready()) {
+ gps_dl_reserved_mem_dma_buf_deinit(&p_link->tx_dma_buf);
+ gps_dl_reserved_mem_dma_buf_deinit(&p_link->rx_dma_buf);
+
+ } else {
+ gps_dl_dma_buf_free(&p_link->tx_dma_buf, link_id);
+ gps_dl_dma_buf_free(&p_link->rx_dma_buf, link_id);
+ }
+
+ /* un-binding each device and link */
+ p_link->p_device = NULL;
+ p_dev->p_link = NULL;
+ gps_each_link_deinit(link_id);
+ }
+}
+
+int gps_dl_ctx_links_init(void)
+{
+ int retval;
+ enum gps_dl_link_id_enum link_id;
+ struct gps_each_device *p_dev;
+ struct gps_each_link *p_link;
+ enum gps_each_link_waitable_type j;
+
+ for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) {
+ p_dev = gps_dl_device_get(link_id);
+ p_link = gps_dl_link_get(link_id);
+
+ if (gps_dl_reserved_mem_is_ready()) {
+ gps_dl_reserved_mem_dma_buf_init(&p_link->tx_dma_buf,
+ link_id, GDL_DMA_A2D, p_link->cfg.tx_buf_size);
+
+ gps_dl_reserved_mem_dma_buf_init(&p_link->rx_dma_buf,
+ link_id, GDL_DMA_D2A, p_link->cfg.rx_buf_size);
+ } else {
+ retval = gps_dl_dma_buf_alloc2(link_id);
+ if (retval)
+ return retval;
+ }
+
+ for (j = 0; j < GPS_DL_WAIT_NUM; j++)
+ gps_dl_link_waitable_init(&p_link->waitables[j], j);
+
+ /* binding each device and link */
+ p_link->p_device = p_dev;
+ p_dev->p_link = p_link;
+
+ /* Todo: MNL read buf is 512, here is work-around */
+ /* the solution should be make on gdl_dma_buf_get */
+ gps_dl_set_rx_transfer_max(link_id, GPS_LIBMNL_READ_MAX);
+ gps_each_link_init(link_id);
+ }
+
+ return 0;
+}
+
+static void gps_dl_devices_exit(void)
+{
+ enum gps_dl_link_id_enum link_id;
+ dev_t devno = MKDEV(gps_dl_devno_major, gps_dl_devno_minor);
+ struct gps_each_device *p_dev;
+
+ gps_dl_device_context_deinit();
+
+#if GPS_DL_HAS_PLAT_DRV
+ gps_dl_linux_plat_drv_unregister();
+#endif
+
+ for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) {
+ p_dev = gps_dl_device_get(link_id);
+ gps_dl_cdev_cleanup(p_dev, link_id);
+ }
+
+ unregister_chrdev_region(devno, GPS_DATA_LINK_NUM);
+}
+
+void gps_dl_device_context_deinit(void)
+{
+ gps_dl_procfs_remove();
+
+ gps_dl_unregister_conninfra_reset_cb();
+
+ gps_dl_irq_deinit();
+
+#if GPS_DL_HAS_CTRLD
+ gps_dl_ctrld_deinit();
+#endif
+
+#if GPS_DL_MOCK_HAL
+ gps_dl_mock_deinit();
+#endif
+
+ gps_dl_ctx_links_deinit();
+ gps_dl_reserved_mem_deinit();
+}
+
+int gps_dl_irq_init(void)
+{
+#if 0
+ enum gps_dl_irq_index_enum irq_idx;
+
+ for (irq_idx = 0; irq_idx < GPS_DL_IRQ_NUM; irq_idx++)
+ ;
+#endif
+
+ gps_dl_linux_irqs_register(gps_dl_irq_get(0), GPS_DL_IRQ_NUM);
+
+ return 0;
+}
+
+int gps_dl_irq_deinit(void)
+{
+ gps_dl_linux_irqs_unregister(gps_dl_irq_get(0), GPS_DL_IRQ_NUM);
+ return 0;
+}
+
+static int gps_dl_devices_init(void)
+{
+ int result;
+ enum gps_dl_link_id_enum link_id;
+ dev_t devno = 0;
+ struct gps_each_device *p_dev;
+
+ result = alloc_chrdev_region(&devno, gps_dl_devno_minor,
+ GPS_DATA_LINK_NUM, GPS_DATA_LINK_DEV_NAME);
+
+ gps_dl_devno_major = MAJOR(devno);
+
+ if (result < 0) {
+ GDL_LOGE_INI("fail to get major %d\n", gps_dl_devno_major);
+ return result;
+ }
+
+ GDL_LOGW_INI("success to get major %d\n", gps_dl_devno_major);
+
+ for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) {
+ devno = MKDEV(gps_dl_devno_major, gps_dl_devno_minor + link_id);
+ p_dev = gps_dl_device_get(link_id);
+ p_dev->devno = devno;
+ result = gps_dl_cdev_setup(p_dev, link_id);
+ if (result) {
+ /* error happened */
+ gps_dl_devices_exit();
+ return result;
+ }
+ }
+
+
+#if GPS_DL_HAS_PLAT_DRV
+ gps_dl_linux_plat_drv_register();
+#else
+ gps_dl_device_context_init();
+#endif
+
+ return 0;
+}
+
+void gps_dl_device_context_init(void)
+{
+ gps_dl_reserved_mem_init();
+ gps_dl_ctx_links_init();
+
+#if GPS_DL_MOCK_HAL
+ gps_dl_mock_init();
+#endif
+
+#if GPS_DL_HAS_CTRLD
+ gps_dl_ctrld_init();
+#endif
+
+#if (!(GPS_DL_NO_USE_IRQ || GPS_DL_HW_IS_MOCK))
+ /* must after gps_dl_ctx_links_init */
+ gps_dl_irq_init();
+#endif
+ gps_dl_register_conninfra_reset_cb();
+
+ gps_dl_procfs_setup();
+}
+
+void mtk_gps_data_link_devices_exit(void)
+{
+ GDL_LOGI_INI("mtk_gps_data_link_devices_exit");
+ gps_dl_devices_exit();
+}
+
+int mtk_gps_data_link_devices_init(void)
+{
+ GDL_LOGI_INI("mtk_gps_data_link_devices_init");
+ gps_dl_devices_init();
+ /* GDL_ASSERT(false, 0, "test assert"); */
+ return 0;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_ctrld.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_ctrld.c
new file mode 100644
index 0000000..d540325
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_ctrld.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_ctrld.h"
+#include "gps_each_device.h"
+#if GPS_DL_MOCK_HAL
+#include "gps_mock_mvcd.h"
+#endif
+#include "gps_data_link_devices.h"
+#include "gps_dl_hal_api.h"
+
+struct gps_dl_ctrld_context gps_dl_ctrld;
+
+static int gps_dl_opfunc_link_event_proc(struct gps_dl_osal_op_dat *pOpDat);
+static int gps_dl_opfunc_hal_event_proc(struct gps_dl_osal_op_dat *pOpDat);
+static struct gps_dl_osal_lxop *gps_dl_get_op(struct gps_dl_osal_lxop_q *pOpQ);
+static int gps_dl_put_op(struct gps_dl_osal_lxop_q *pOpQ, struct gps_dl_osal_lxop *pOp);
+
+static const GPS_DL_OPID_FUNC gps_dl_core_opfunc[] = {
+ [GPS_DL_OPID_LINK_EVENT_PROC] = gps_dl_opfunc_link_event_proc,
+ [GPS_DL_OPID_HAL_EVENT_PROC] = gps_dl_opfunc_hal_event_proc,
+};
+
+static int gps_dl_opfunc_link_event_proc(struct gps_dl_osal_op_dat *pOpDat)
+{
+ enum gps_dl_link_event_id evt;
+ enum gps_dl_link_id_enum link_id;
+
+ link_id = (enum gps_dl_link_id_enum)pOpDat->au4OpData[0];
+ evt = (enum gps_dl_link_event_id)pOpDat->au4OpData[1];
+ gps_dl_link_event_proc(evt, link_id);
+
+ return 0;
+}
+
+static int gps_dl_opfunc_hal_event_proc(struct gps_dl_osal_op_dat *pOpDat)
+{
+ enum gps_dl_hal_event_id evt;
+ enum gps_dl_link_id_enum link_id;
+ int sid_on_evt;
+
+ link_id = (enum gps_dl_link_id_enum)pOpDat->au4OpData[0];
+ evt = (enum gps_dl_hal_event_id)pOpDat->au4OpData[1];
+ sid_on_evt = (int)pOpDat->au4OpData[2];
+ gps_dl_hal_event_proc(evt, link_id, sid_on_evt);
+
+ return 0;
+}
+
+unsigned int gps_dl_wait_event_checker(struct gps_dl_osal_thread *pThread)
+{
+ struct gps_dl_ctrld_context *pgps_dl_ctrld;
+
+ if (pThread) {
+ pgps_dl_ctrld = (struct gps_dl_ctrld_context *) (pThread->pThreadData);
+ return !RB_EMPTY(&pgps_dl_ctrld->rOpQ);
+ }
+ GDL_LOGE_EVT("pThread null");
+ return 0;
+}
+
+static int gps_dl_core_opid(struct gps_dl_osal_op_dat *pOpDat)
+{
+ int ret;
+
+ if (pOpDat == NULL) {
+ GDL_LOGE_EVT("null operation data");
+ /*print some message with error info */
+ return -1;
+ }
+
+ if (pOpDat->opId >= GPS_DL_OPID_MAX) {
+ GDL_LOGE_EVT("Invalid OPID(%d)", pOpDat->opId);
+ return -2;
+ }
+
+ if (gps_dl_core_opfunc[pOpDat->opId]) {
+ GDL_LOGD_EVT("GPS data link: operation id(%d)", pOpDat->opId);
+ ret = (*(gps_dl_core_opfunc[pOpDat->opId])) (pOpDat);
+ return ret;
+ }
+
+ GDL_LOGE_EVT("GPS data link: null handler (%d)", pOpDat->opId);
+
+ return -2;
+}
+
+static int gps_dl_put_op(struct gps_dl_osal_lxop_q *pOpQ, struct gps_dl_osal_lxop *pOp)
+{
+ int iRet;
+
+ if (!pOpQ || !pOp) {
+ GDL_LOGW_EVT("invalid input param: pOpQ(0x%p), pLxOp(0x%p)", pOpQ, pOp);
+ gps_dl_osal_assert(pOpQ);
+ gps_dl_osal_assert(pOp);
+ return -1;
+ }
+
+ iRet = gps_dl_osal_lock_sleepable_lock(&pOpQ->sLock);
+ if (iRet) {
+ GDL_LOGW_EVT("gps_dl_osal_lock_sleepable_lock iRet(%d)", iRet);
+ return -1;
+ }
+
+ /* acquire lock success */
+ if (!RB_FULL(pOpQ))
+ RB_PUT(pOpQ, pOp);
+ else {
+ GDL_LOGW("RB_FULL(%p -> %p)", pOp, pOpQ);
+ iRet = -1;
+ }
+
+ gps_dl_osal_unlock_sleepable_lock(&pOpQ->sLock);
+
+ if (iRet)
+ return -1;
+ return 0;
+}
+
+int gps_dl_put_act_op(struct gps_dl_osal_lxop *pOp)
+{
+ struct gps_dl_ctrld_context *pgps_dl_ctrld = &gps_dl_ctrld;
+ struct gps_dl_osal_signal *pSignal = NULL;
+ int waitRet = -1;
+ int bRet = 0;
+
+ gps_dl_osal_assert(pgps_dl_ctrld);
+ gps_dl_osal_assert(pOp);
+
+ do {
+ if (!pgps_dl_ctrld || !pOp) {
+ GDL_LOGE("pgps_dl_ctx(0x%p), pOp(0x%p)", pgps_dl_ctrld, pOp);
+ break;
+ }
+
+ /* Init ref_count to 1 indicating that current thread holds a ref to it */
+ atomic_set(&pOp->ref_count, 1);
+
+ pSignal = &pOp->signal;
+ if (pSignal->timeoutValue) {
+ pOp->result = -9;
+ gps_dl_osal_signal_init(pSignal);
+ }
+
+ /* Increment ref_count by 1 as gps control thread will hold a reference also,
+ * this must be done here instead of on target thread, because
+ * target thread might not be scheduled until a much later time,
+ * allowing current thread to decrement ref_count at the end of function,
+ * putting op back to free queue before target thread has a chance to process.
+ */
+ atomic_inc(&pOp->ref_count);
+
+ /* put to active Q */
+ bRet = gps_dl_put_op(&pgps_dl_ctrld->rOpQ, pOp);
+ if (bRet == -1) {
+ GDL_LOGE("put to active queue fail");
+ atomic_dec(&pOp->ref_count);
+ break;
+ }
+
+ /* wake up gps control thread */
+ gps_dl_osal_trigger_event(&pgps_dl_ctrld->rgpsdlWq);
+
+ if (pSignal->timeoutValue == 0) {
+ bRet = -1;
+ break;
+ }
+
+ /* check result */
+ waitRet = gps_dl_osal_wait_for_signal_timeout(pSignal, &pgps_dl_ctrld->thread);
+
+ if (waitRet == 0)
+ GDL_LOGE("opId(%d) completion timeout", pOp->op.opId);
+ else if (pOp->result)
+ GDL_LOGW("opId(%d) result:%d", pOp->op.opId, pOp->result);
+
+ /* op completes, check result */
+ bRet = (pOp->result) ? -1 : 0;
+ } while (0);
+
+ if (pOp && atomic_dec_and_test(&pOp->ref_count)) {
+ /* put Op back to freeQ */
+ gps_dl_put_op(&pgps_dl_ctrld->rFreeOpQ, pOp);
+ }
+
+ return bRet;
+}
+
+struct gps_dl_osal_lxop *gps_dl_get_free_op(void)
+{
+ struct gps_dl_osal_lxop *pOp = NULL;
+ struct gps_dl_ctrld_context *pgps_dl_ctrld = &gps_dl_ctrld;
+
+ gps_dl_osal_assert(pgps_dl_ctrld);
+ pOp = gps_dl_get_op(&pgps_dl_ctrld->rFreeOpQ);
+ if (pOp)
+ gps_dl_osal_memset(pOp, 0, sizeof(struct gps_dl_osal_lxop));
+ return pOp;
+}
+
+static struct gps_dl_osal_lxop *gps_dl_get_op(struct gps_dl_osal_lxop_q *pOpQ)
+{
+ struct gps_dl_osal_lxop *pOp;
+ int iRet;
+
+ if (pOpQ == NULL) {
+ GDL_LOGE("pOpQ = NULL");
+ gps_dl_osal_assert(pOpQ);
+ return NULL;
+ }
+
+ iRet = gps_dl_osal_lock_sleepable_lock(&pOpQ->sLock);
+ if (iRet) {
+ GDL_LOGE("gps_dl_osal_lock_sleepable_lock iRet(%d)", iRet);
+ return NULL;
+ }
+
+ /* acquire lock success */
+ RB_GET(pOpQ, pOp);
+ gps_dl_osal_unlock_sleepable_lock(&pOpQ->sLock);
+
+ if (pOp == NULL) {
+ GDL_LOGW("RB_GET(%p) return NULL", pOpQ);
+ gps_dl_osal_assert(pOp);
+ return NULL;
+ }
+
+ return pOp;
+}
+
+int gps_dl_put_op_to_free_queue(struct gps_dl_osal_lxop *pOp)
+{
+ struct gps_dl_ctrld_context *pgps_dl_ctrld = &gps_dl_ctrld;
+
+ if (gps_dl_put_op(&pgps_dl_ctrld->rFreeOpQ, pOp) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int gps_dl_ctrl_thread(void *pData)
+{
+ struct gps_dl_ctrld_context *pgps_dl_ctrld = (struct gps_dl_ctrld_context *) pData;
+ struct gps_dl_osal_event *pEvent = NULL;
+ struct gps_dl_osal_lxop *pOp;
+ int iResult;
+
+ if (pgps_dl_ctrld == NULL) {
+ GDL_LOGE("pgps_dl_ctx is NULL");
+ return -1;
+ }
+
+ GDL_LOGI("gps control thread starts");
+
+ pEvent = &(pgps_dl_ctrld->rgpsdlWq);
+
+ for (;;) {
+ pOp = NULL;
+ pEvent->timeoutValue = 0;
+
+ gps_dl_osal_thread_wait_for_event(&pgps_dl_ctrld->thread, pEvent, gps_dl_wait_event_checker);
+
+ if (gps_dl_osal_thread_should_stop(&pgps_dl_ctrld->thread)) {
+ GDL_LOGW(" thread should stop now...");
+ /* TODO: clean up active opQ */
+ break;
+ }
+
+ /* get Op from Queue */
+ pOp = gps_dl_get_op(&pgps_dl_ctrld->rOpQ);
+ if (!pOp) {
+ GDL_LOGW("get_lxop activeQ fail");
+ continue;
+ }
+
+ /*Execute operation*/
+ iResult = gps_dl_core_opid(&pOp->op);
+
+ if (atomic_dec_and_test(&pOp->ref_count))
+ gps_dl_put_op(&pgps_dl_ctrld->rFreeOpQ, pOp);
+ else if (gps_dl_osal_op_is_wait_for_signal(pOp))
+ gps_dl_osal_op_raise_signal(pOp, iResult);
+
+ if (iResult)
+ GDL_LOGW("opid (0x%x) failed, iRet(%d)", pOp->op.opId, iResult);
+
+ }
+
+ GDL_LOGI("gps control thread exits succeed");
+
+ return 0;
+}
+
+int gps_dl_ctrld_init(void)
+{
+ struct gps_dl_ctrld_context *pgps_dl_ctrld;
+ struct gps_dl_osal_thread *pThread;
+ int iRet;
+ int i;
+
+ pgps_dl_ctrld = &gps_dl_ctrld;
+ gps_dl_osal_memset(&gps_dl_ctrld, 0, sizeof(gps_dl_ctrld));
+
+ /* Create gps data link control thread */
+ pThread = &gps_dl_ctrld.thread;
+ gps_dl_osal_strncpy(pThread->threadName, "gps_kctrld", sizeof(pThread->threadName));
+ pThread->pThreadData = (void *)pgps_dl_ctrld;
+ pThread->pThreadFunc = (void *)gps_dl_ctrl_thread;
+
+ iRet = gps_dl_osal_thread_create(pThread);
+ if (iRet) {
+ GDL_LOGE("Create gps data link control thread fail:%d", iRet);
+ return -1;
+ }
+
+ /* Initialize gps control Thread Information: Thread */
+ gps_dl_osal_event_init(&pgps_dl_ctrld->rgpsdlWq);
+ gps_dl_osal_sleepable_lock_init(&pgps_dl_ctrld->rOpQ.sLock);
+ gps_dl_osal_sleepable_lock_init(&pgps_dl_ctrld->rFreeOpQ.sLock);
+ /* Initialize op queue */
+ RB_INIT(&pgps_dl_ctrld->rOpQ, GPS_DL_OP_BUF_SIZE);
+ RB_INIT(&pgps_dl_ctrld->rFreeOpQ, GPS_DL_OP_BUF_SIZE);
+
+ /* Put all to free Q */
+ for (i = 0; i < GPS_DL_OP_BUF_SIZE; i++) {
+ gps_dl_osal_signal_init(&(pgps_dl_ctrld->arQue[i].signal));
+ gps_dl_put_op(&pgps_dl_ctrld->rFreeOpQ, &(pgps_dl_ctrld->arQue[i]));
+ }
+
+ iRet = gps_dl_osal_thread_run(pThread);
+ if (iRet) {
+ GDL_LOGE("gps data link ontrol thread run fail:%d", iRet);
+ return -1;
+ }
+
+ return 0;
+}
+
+int gps_dl_ctrld_deinit(void)
+{
+ struct gps_dl_osal_thread *pThread;
+ int iRet;
+
+ pThread = &gps_dl_ctrld.thread;
+
+ iRet = gps_dl_osal_thread_destroy(pThread);
+ if (iRet) {
+ GDL_LOGE("gps data link ontrol thread destroy fail:%d", iRet);
+ return -1;
+ }
+
+ GDL_LOGI("gps data link ontrol thread destroy okay:%d\n", iRet);
+ gps_dl_osal_event_deinit(&gps_dl_ctrld.rgpsdlWq);
+ return 0;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_emi.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_emi.c
new file mode 100644
index 0000000..ddef332
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_emi.c
@@ -0,0 +1,228 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#include "gps_dl_config.h"
+
+#if GPS_DL_HAS_PLAT_DRV
+/*******************************************************************************
+* Dependency
+*******************************************************************************/
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/cdev.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/printk.h>
+#include <linux/version.h>
+
+#include "gps_dl_log.h"
+#include "gps_dl_linux_reserved_mem.h"
+#include "gps_dl_emi.h"
+
+/******************************************************************************
+ * Definition
+******************************************************************************/
+/* device name and major number */
+#define GPS_DL_EMI_DEVNAME "gps_emi"
+#define IOCTL_EMI_MEMORY_INIT 1
+#define IOCTL_MNL_NVRAM_FILE_TO_MEM 2
+#define IOCTL_MNL_NVRAM_MEM_TO_FILE 3
+#define IOCTL_ADC_CAPTURE_ADDR_GET 4
+
+
+/*******************************************************************************
+* structure & enumeration
+*******************************************************************************/
+/*---------------------------------------------------------------------------*/
+struct gps_icap_dev {
+ struct class *cls;
+ struct device *dev;
+ dev_t devno;
+ struct cdev chdev;
+};
+
+struct gps_icap_dev *gps_icap_dev_ptr;
+
+char gps_icap_local_buf[GPS_ICAP_BUF_SIZE];
+
+
+/*---------------------------------------------------------------------------*/
+long gps_icap_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int retval = 0;
+#if 0
+ unsigned int *tmp;
+#endif
+
+ GDL_LOGI("cmd (%d),arg(%ld)\n", cmd, arg);
+
+ switch (cmd) {
+ case IOCTL_EMI_MEMORY_INIT:
+ GDL_LOGW("IOCTL_EMI_MEMORY_INIT");
+ break;
+
+ case IOCTL_MNL_NVRAM_FILE_TO_MEM:
+ GDL_LOGW("IOCTL_MNL_NVRAM_FILE_TO_MEM");
+ break;
+
+ case IOCTL_MNL_NVRAM_MEM_TO_FILE:
+ GDL_LOGW("IOCTL_MNL_NVRAM_MEM_TO_FILE");
+ break;
+
+ case IOCTL_ADC_CAPTURE_ADDR_GET:
+#if 0
+ tmp = (unsigned int *)&gGpsIcapPhyBase;
+ GPS_DBG("gps_emi:gGpsIcapPhyBase (%x)\n", &gGpsIcapPhyBase);
+ GPS_DBG("gps_emi:tmp (%x)\n", tmp);
+ if (copy_to_user((unsigned int __user *)arg, tmp, sizeof(unsigned int)))
+ retval = -1;
+#endif
+ GDL_LOGW("IOCTL_ADC_CAPTURE_ADDR_GET,(%d)", retval);
+ break;
+
+ default:
+ GDL_LOGW("unknown cmd (%d)", cmd);
+ retval = 0;
+ break;
+ }
+ return retval;
+
+}
+
+/******************************************************************************/
+long gps_icap_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ return gps_icap_unlocked_ioctl(filp, cmd, arg);
+}
+
+/*****************************************************************************/
+static int gps_icap_open(struct inode *inode, struct file *file)
+{
+ return nonseekable_open(inode, file);
+}
+
+/*****************************************************************************/
+
+
+/*****************************************************************************/
+static int gps_icap_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+/******************************************************************************/
+static ssize_t gps_icap_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+ void *p_src;
+
+ GDL_LOGI("begin");
+
+ if (count > GPS_ICAP_BUF_SIZE)
+ count = GPS_ICAP_BUF_SIZE;
+
+ p_src = gps_dl_reserved_mem_icap_buf_get_vir_addr();
+
+ if (p_src == NULL) {
+ GDL_LOGW("src is null, return");
+ return 0;
+ }
+
+ memcpy_fromio(&gps_icap_local_buf[0], p_src, GPS_ICAP_BUF_SIZE);
+
+ if (copy_to_user(buf, (char *)&gps_icap_local_buf[0], count)) {
+ GDL_LOGW("copy to user fail, return");
+ return 0;
+ }
+
+ GDL_LOGI("finish, count = %ld", count);
+ return count;
+}
+
+/******************************************************************************/
+static ssize_t gps_icap_write(struct file *file, const char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ ssize_t ret = 0;
+
+ GDL_LOGW("count = %ld", count);
+
+ return ret;
+}
+
+/*****************************************************************************/
+/* Kernel interface */
+static const struct file_operations gps_icap_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = gps_icap_unlocked_ioctl,
+ .compat_ioctl = gps_icap_compat_ioctl,
+ .open = gps_icap_open,
+ .read = gps_icap_read,
+ .write = gps_icap_write,
+ .release = gps_icap_release,
+};
+
+/*****************************************************************************/
+void gps_icap_probe(void)
+{
+ int ret = 0, err = 0;
+
+ GDL_LOGI("start");
+
+ gps_icap_dev_ptr = kzalloc(sizeof(*gps_icap_dev_ptr), GFP_KERNEL);
+ if (gps_icap_dev_ptr == NULL) {
+ err = -ENOMEM;
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ GDL_LOGD("registering chardev");
+ ret = alloc_chrdev_region(&gps_icap_dev_ptr->devno, 0, 1, GPS_DL_EMI_DEVNAME);
+ if (ret) {
+ GDL_LOGE("alloc_chrdev_region fail: %d", ret);
+ err = -ENOMEM;
+ goto err_out;
+ } else
+ GDL_LOGI("major: %d, minor: %d",
+ MAJOR(gps_icap_dev_ptr->devno), MINOR(gps_icap_dev_ptr->devno));
+
+ cdev_init(&gps_icap_dev_ptr->chdev, &gps_icap_fops);
+ gps_icap_dev_ptr->chdev.owner = THIS_MODULE;
+ err = cdev_add(&gps_icap_dev_ptr->chdev, gps_icap_dev_ptr->devno, 1);
+ if (err) {
+ GDL_LOGE("cdev_add fail: %d", err);
+ goto err_out;
+ }
+
+ gps_icap_dev_ptr->cls = class_create(THIS_MODULE, "gpsemi");
+ if (IS_ERR(gps_icap_dev_ptr->cls)) {
+ GDL_LOGE("unable to create class, err = %d\n", (int)PTR_ERR(gps_icap_dev_ptr->cls));
+ goto err_out;
+ }
+ gps_icap_dev_ptr->dev = device_create(gps_icap_dev_ptr->cls,
+ NULL, gps_icap_dev_ptr->devno, gps_icap_dev_ptr, "gps_emi");
+
+ GDL_LOGI("done");
+ return;
+
+err_out:
+ if (gps_icap_dev_ptr != NULL) {
+ if (err == 0)
+ cdev_del(&gps_icap_dev_ptr->chdev);
+ if (ret == 0)
+ unregister_chrdev_region(gps_icap_dev_ptr->devno, 1);
+
+ kfree(gps_icap_dev_ptr);
+ gps_icap_dev_ptr = NULL;
+ }
+}
+
+#endif /* GPS_DL_HAS_PLAT_DRV */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_linux.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_linux.c
new file mode 100644
index 0000000..183decb
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_linux.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_linux.h"
+#include "gps_dl_hal.h"
+#include "gps_dl_log.h"
+
+void gps_dl_irq_mask(int irq_id, enum gps_dl_irq_ctrl_from from)
+{
+ /* TODO: */
+ /* threaded_irq thread_fn still need to call disable_irq_nosync,
+ * otherwise it might be hung.
+ */
+ if (from == GPS_DL_IRQ_CTRL_FROM_ISR)
+ disable_irq_nosync(irq_id);
+ else
+ /* It returns until irq done */
+ disable_irq(irq_id);
+}
+
+void gps_dl_irq_unmask(int irq_id, enum gps_dl_irq_ctrl_from from)
+{
+ /* TODO: */
+ enable_irq(irq_id);
+}
+
+static int gps_dl_linux_irq_index_to_id(enum gps_dl_irq_index_enum index)
+{
+ /* TODO: fill the real number or the value from dts */
+ return gps_dl_irq_index_to_id(index);
+}
+
+/* TODO: call it when module init */
+int gps_dl_linux_irqs_register(struct gps_each_irq *p_irqs, int irq_num)
+{
+ int irq_id, i_ret, i;
+ unsigned long sys_irq_flags;
+
+ for (i = 0; i < irq_num; i++) {
+ irq_id = gps_dl_linux_irq_index_to_id(p_irqs[i].cfg.index);
+
+ if (irq_id == 0) {
+ GDL_LOGE_INI("i = %d, irq_id = %d, name = %s, bypass",
+ i, irq_id, p_irqs[i].cfg.name);
+ continue;
+ }
+
+ if (p_irqs[i].cfg.trig_type == GPS_DL_IRQ_TRIG_LEVEL_HIGH)
+ sys_irq_flags = IRQF_TRIGGER_HIGH;
+ else if (p_irqs[i].cfg.trig_type == GPS_DL_IRQ_TRIG_EDGE_RISING)
+ sys_irq_flags = IRQF_TRIGGER_RISING;
+ else
+ return -1;
+
+ /* TODO: Use the dts to auto request the irqs */
+#if GPS_DL_USE_THREADED_IRQ
+ /* IRQF_ONESHOT is required for threaded irq */
+ sys_irq_flags |= IRQF_ONESHOT;
+ i_ret = request_threaded_irq(irq_id, NULL,
+ (irq_handler_t)p_irqs[i].cfg.isr,
+ sys_irq_flags, p_irqs[i].cfg.name, &p_irqs[i]);
+#else
+ i_ret = request_irq(irq_id,
+ (irq_handler_t)p_irqs[i].cfg.isr, /* gps_dl_linux_irq_dispatcher */
+ sys_irq_flags, p_irqs[i].cfg.name, &p_irqs[i]);
+#endif
+ GDL_LOGW_INI("i = %d, irq_id = %d, name = %s, flags = 0x%lx, ret = %d",
+ i, irq_id, p_irqs[i].cfg.name, sys_irq_flags, i_ret);
+ if (i_ret) {
+ /* show error log */
+ /* return i_ret; */
+ continue; /* not stop even fail */
+ }
+
+ /* The init status is unmask, mask them here */
+ gps_dl_irq_mask(irq_id, GPS_DL_IRQ_CTRL_FROM_THREAD);
+ p_irqs[i].register_done = true;
+ p_irqs[i].reg_irq_id = irq_id;
+ }
+
+ return 0;
+}
+
+int gps_dl_linux_irqs_unregister(struct gps_each_irq *p_irqs, int irq_num)
+{
+ int irq_id, i;
+
+ for (i = 0; i < irq_num; i++) {
+ if (p_irqs[i].register_done) {
+ irq_id = gps_dl_linux_irq_index_to_id(p_irqs[i].cfg.index);
+ /* assert irq_id = p_irqs[i].reg_irq_id */
+ free_irq(irq_id, &p_irqs[i]);
+
+ p_irqs[i].register_done = false;
+ p_irqs[i].reg_irq_id = 0;
+ }
+ }
+
+ return 0;
+}
+
+irqreturn_t gps_dl_linux_irq_dispatcher(int irq, void *data)
+{
+ struct gps_each_irq *p_irq;
+
+ p_irq = (struct gps_each_irq *)data;
+
+ switch (p_irq->cfg.index) {
+ case GPS_DL_IRQ_LINK0_DATA:
+ gps_dl_isr_usrt_has_data(GPS_DATA_LINK_ID0);
+ break;
+ case GPS_DL_IRQ_LINK0_NODATA:
+ gps_dl_isr_usrt_has_nodata(GPS_DATA_LINK_ID0);
+ break;
+ case GPS_DL_IRQ_LINK0_MCUB:
+ gps_dl_isr_mcub(GPS_DATA_LINK_ID0);
+ break;
+
+ case GPS_DL_IRQ_LINK1_DATA:
+ gps_dl_isr_usrt_has_data(GPS_DATA_LINK_ID1);
+ break;
+ case GPS_DL_IRQ_LINK1_NODATA:
+ gps_dl_isr_usrt_has_nodata(GPS_DATA_LINK_ID1);
+ break;
+ case GPS_DL_IRQ_LINK1_MCUB:
+ gps_dl_isr_mcub(GPS_DATA_LINK_ID1);
+ break;
+
+ case GPS_DL_IRQ_DMA:
+ gps_dl_isr_dma_done();
+ break;
+
+ default:
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_linux_plat_drv.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_linux_plat_drv.c
new file mode 100644
index 0000000..bee8643
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_linux_plat_drv.c
@@ -0,0 +1,636 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+
+#if GPS_DL_HAS_PLAT_DRV
+#include <linux/pinctrl/consumer.h>
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/poll.h>
+
+#include <linux/io.h>
+#include <asm/io.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/platform_device.h>
+#include <linux/pm_wakeup.h>
+#include <linux/mfd/mt6397/core.h>
+#include <linux/regmap.h>
+#include <linux/mfd/mt6330/registers.h>
+
+
+#include "gps_dl_linux.h"
+#include "gps_dl_linux_plat_drv.h"
+#include "gps_dl_linux_reserved_mem.h"
+#include "gps_dl_isr.h"
+#include "gps_each_device.h"
+
+
+
+
+/* #ifdef CONFIG_OF */
+const struct of_device_id gps_dl_of_ids[] = {
+ { .compatible = "mediatek,connac2-gps", },
+ {}
+};
+/* #endif */
+#define GPS_DL_IOMEM_NUM 2
+
+struct gps_dl_iomem_addr_map_entry g_gps_dl_iomem_arrary[GPS_DL_IOMEM_NUM];
+struct gps_dl_iomem_addr_map_entry g_gps_dl_status_dummy_cr;
+struct gps_dl_iomem_addr_map_entry g_gps_dl_tia1_gps;
+struct gps_dl_iomem_addr_map_entry g_gps_dl_tia2_gps_on;
+struct gps_dl_iomem_addr_map_entry g_gps_dl_tia2_gps_rc_sel;
+
+static struct regmap *g_gps_dl_pmic_regmap_ptr;
+void __iomem *gps_dl_host_addr_to_virt(unsigned int host_addr)
+{
+ int i;
+ int offset;
+ struct gps_dl_iomem_addr_map_entry *p;
+
+ for (i = 0; i < GPS_DL_IOMEM_NUM; i++) {
+ p = &g_gps_dl_iomem_arrary[i];
+
+ if (p->length == 0)
+ continue;
+
+ offset = host_addr - p->host_phys_addr;
+ if (offset >= 0 && offset < p->length)
+ return p->host_virt_addr + offset;
+ }
+
+ return (void __iomem *)0;
+}
+
+void gps_dl_update_status_for_md_blanking(bool gps_is_on)
+{
+ void __iomem *p = g_gps_dl_status_dummy_cr.host_virt_addr;
+ unsigned int val = (gps_is_on ? 1 : 0);
+ unsigned int val_old, val_new;
+
+ if (p != NULL) {
+ val_old = __raw_readl(p);
+ gps_dl_linux_sync_writel(val, p);
+ val_new = __raw_readl(p);
+ GDL_LOGI_INI("dummy cr updated: %d -> %d, due to on = %d",
+ val_old, val_new, gps_is_on);
+ } else
+ GDL_LOGW_INI("dummy cr addr is invalid, can not update (on = %d)", gps_is_on);
+}
+
+void gps_dl_tia1_gps_ctrl(bool gps_is_on)
+{
+ void __iomem *p = g_gps_dl_tia1_gps.host_virt_addr;
+ unsigned int tia_gps_on, tia_gps_ctrl, tia_temp;
+ unsigned int tia_gps_on1, tia_gps_ctrl1, tia_temp1;
+
+ if (p == NULL) {
+ GDL_LOGW_INI("on = %d, tia_gps addr is null", gps_is_on);
+ return;
+ }
+
+ tia_gps_on = __raw_readl(p);
+ tia_gps_ctrl = __raw_readl(p + 4);
+ tia_temp = __raw_readl(p + 8);
+
+ if (gps_is_on) {
+ /* 0x1001C018[0] = 1 (GPS on) */
+ gps_dl_linux_sync_writel(tia_gps_on | 1UL, p);
+
+ /* 0x1001C01C[11:0] = 100 (~3ms update period, 1/32k = 0.03125ms)
+ * 0x1001C01C[12] = 1 (enable TSX)
+ * 0x1001C01C[13] = 1 (enable DCXO)
+ */
+ /* 20190923 period changed to 196 (0xC4, 6ms) */
+ gps_dl_linux_sync_writel((196UL | (1UL << 12) | (1UL << 13)), p + 4);
+ } else {
+ /* 0x1001C018[0] = 0 (GPS off) */
+ gps_dl_linux_sync_writel(tia_gps_on & ~1UL, p);
+ }
+
+ tia_gps_on1 = __raw_readl(p);
+ tia_gps_ctrl1 = __raw_readl(p + 4);
+ tia_temp1 = __raw_readl(p + 8);
+
+ GDL_LOGI_INI(
+ "on = %d, tia_gps_on = 0x%08x/0x%08x, ctrl = 0x%08x/0x%08x, temp = 0x%08x/0x%08x",
+ gps_is_on, tia_gps_on, tia_gps_on1,
+ tia_gps_ctrl, tia_gps_ctrl1,
+ tia_temp, tia_temp1);
+}
+
+void gps_dl_tia2_gps_ctrl(bool gps_is_on)
+{
+ void __iomem *p_gps_on = g_gps_dl_tia2_gps_on.host_virt_addr;
+ void __iomem *p_gps_rc_sel = g_gps_dl_tia2_gps_rc_sel.host_virt_addr;
+ unsigned int tia2_gps_on_old = 0, tia2_gps_rc_sel_old = 0;
+ unsigned int tia2_gps_on_new = 0, tia2_gps_rc_sel_new = 0;
+
+ if (p_gps_on == NULL) {
+ GDL_LOGW_INI("on = %d, tia2_gps_on addr is null", gps_is_on);
+ return;
+ }
+
+ tia2_gps_on_old = __raw_readl(p_gps_on);
+ if (gps_is_on) {
+ /* 0x1001C000[5] = 1 (GPS on) */
+ gps_dl_linux_sync_writel(tia2_gps_on_old | (1UL << 5), p_gps_on);
+
+ if (p_gps_rc_sel == NULL)
+ GDL_LOGW_INI("on = %d, p_gps_rc_sel addr is null", gps_is_on);
+ else {
+ /* 0x1001C030[ 1: 0] = 0
+ * 0x1001C030[ 5: 4] = 0
+ * 0x1001C030[ 9: 8] = 0
+ * 0x1001C030[13:12] = 0
+ * 0x1001C030[17:16] = 0
+ */
+ tia2_gps_rc_sel_old = __raw_readl(p_gps_rc_sel);
+ gps_dl_linux_sync_writel(tia2_gps_rc_sel_old & ~(0x00033333), p_gps_rc_sel);
+ tia2_gps_rc_sel_new = __raw_readl(p_gps_rc_sel);
+ }
+ } else {
+ tia2_gps_rc_sel_old = __raw_readl(p_gps_rc_sel);
+
+ /* 0x1001C000[5] = 0 (GPS off) */
+ gps_dl_linux_sync_writel(tia2_gps_on_old & ~(1UL << 5), p_gps_on);
+ }
+ tia2_gps_on_new = __raw_readl(p_gps_on);
+ GDL_LOGI_INI(
+ "on = %d, tia2_gps_on = 0x%08x/0x%08x, rc_sel = 0x%08x/0x%08x",
+ gps_is_on,
+ tia2_gps_on_old, tia2_gps_on_new,
+ tia2_gps_rc_sel_old, tia2_gps_rc_sel_new);
+}
+
+void gps_dl_tia_gps_ctrl(bool gps_is_on)
+{
+ if (g_gps_dl_tia2_gps_on.host_virt_addr != NULL)
+ gps_dl_tia2_gps_ctrl(gps_is_on);
+ else if (g_gps_dl_tia1_gps.host_virt_addr != NULL)
+ gps_dl_tia1_gps_ctrl(gps_is_on);
+ else
+ GDL_LOGE("tia reg not found, bypass!");
+}
+
+enum gps_dl_pinctrl_state_enum {
+ GPS_DL_L1_LNA_DISABLE,
+ GPS_DL_L1_LNA_DSP_CTRL,
+ GPS_DL_L1_LNA_ENABLE,
+ GPS_DL_L5_LNA_DISABLE,
+ GPS_DL_L5_LNA_DSP_CTRL,
+ GPS_DL_L5_LNA_ENABLE,
+ GPS_DL_PINCTRL_STATE_CNT
+};
+
+const char *const gps_dl_pinctrl_state_name_list[GPS_DL_PINCTRL_STATE_CNT] = {
+ "gps_l1_lna_disable",
+ "gps_l1_lna_dsp_ctrl",
+ "gps_l1_lna_enable",
+ "gps_l5_lna_disable",
+ "gps_l5_lna_dsp_ctrl",
+ "gps_l5_lna_enable",
+};
+
+struct pinctrl_state *g_gps_dl_pinctrl_state_struct_list[GPS_DL_PINCTRL_STATE_CNT];
+struct pinctrl *g_gps_dl_pinctrl_ptr;
+
+void gps_dl_pinctrl_show_info(void)
+{
+ enum gps_dl_pinctrl_state_enum state_id;
+ const char *p_name;
+ struct pinctrl_state *p_state;
+
+ GDL_LOGD_INI("pinctrl_ptr = 0x%p", g_gps_dl_pinctrl_ptr);
+
+ for (state_id = 0; state_id < GPS_DL_PINCTRL_STATE_CNT; state_id++) {
+ p_name = gps_dl_pinctrl_state_name_list[state_id];
+ p_state = g_gps_dl_pinctrl_state_struct_list[state_id];
+ GDL_LOGD_INI("state id = %d, ptr = 0x%p, name = %s",
+ state_id, p_state, p_name);
+ }
+}
+
+void gps_dl_pinctrl_context_init(void)
+{
+ enum gps_dl_pinctrl_state_enum state_id;
+ const char *p_name;
+ struct pinctrl_state *p_state;
+
+ if (IS_ERR(g_gps_dl_pinctrl_ptr)) {
+ GDL_LOGE_INI("pinctrl is error");
+ return;
+ }
+
+ for (state_id = 0; state_id < GPS_DL_PINCTRL_STATE_CNT; state_id++) {
+ p_name = gps_dl_pinctrl_state_name_list[state_id];
+ p_state = pinctrl_lookup_state(g_gps_dl_pinctrl_ptr, p_name);
+
+ if (IS_ERR(p_state)) {
+ GDL_LOGE_INI("lookup fail: state id = %d, name = %s", state_id, p_name);
+ g_gps_dl_pinctrl_state_struct_list[state_id] = NULL;
+ continue;
+ }
+
+ g_gps_dl_pinctrl_state_struct_list[state_id] = p_state;
+ GDL_LOGW_INI("lookup okay: state id = %d, name = %s", state_id, p_name);
+ }
+}
+
+void gps_dl_lna_pin_ctrl(enum gps_dl_link_id_enum link_id, bool dsp_is_on, bool force_en)
+{
+ struct pinctrl_state *p_state = NULL;
+ int ret;
+
+ ASSERT_LINK_ID(link_id, GDL_VOIDF());
+
+ if (GPS_DATA_LINK_ID0 == link_id) {
+ if (dsp_is_on && force_en)
+ p_state = g_gps_dl_pinctrl_state_struct_list[GPS_DL_L1_LNA_ENABLE];
+ else if (dsp_is_on)
+ p_state = g_gps_dl_pinctrl_state_struct_list[GPS_DL_L1_LNA_DSP_CTRL];
+ else {
+ /* Here is the case GPS L1 is turned off, LNA pin state can still be in "DSP_CTRL",
+ * due to the pin will become low automatically when GPS L1 is turned off
+ * under this mode.
+ * If need to set it to be low explicitly, GPS_DL_L1_LNA_DISABLE can be used to
+ * replace GPS_DL_L1_LNA_DSP_CTRL.
+ */
+ p_state = g_gps_dl_pinctrl_state_struct_list[GPS_DL_L1_LNA_DSP_CTRL];
+ }
+ }
+
+ if (GPS_DATA_LINK_ID1 == link_id) {
+ if (dsp_is_on && force_en)
+ p_state = g_gps_dl_pinctrl_state_struct_list[GPS_DL_L5_LNA_ENABLE];
+ else if (dsp_is_on)
+ p_state = g_gps_dl_pinctrl_state_struct_list[GPS_DL_L5_LNA_DSP_CTRL];
+ else {
+ /* Here is the case GPS L5 is turned off, LNA pin state can still be in "DSP_CTRL",
+ * due to the pin will become low automatically when GPS L5 is turned off
+ * under this mode.
+ * If need to set it to be low explicitly, GPS_DL_L5_LNA_DISABLE can be used to
+ * replace GPS_DL_L5_LNA_DSP_CTRL.
+ */
+ p_state = g_gps_dl_pinctrl_state_struct_list[GPS_DL_L5_LNA_DSP_CTRL];
+ }
+ }
+
+ if (p_state == NULL) {
+ GDL_LOGXW(link_id, "on = %d, force = %d, state is null", dsp_is_on, force_en);
+ return;
+ }
+
+ ret = pinctrl_select_state(g_gps_dl_pinctrl_ptr, p_state);
+ if (ret != 0)
+ GDL_LOGXW(link_id, "on = %d, force = %d, select ret = %d", dsp_is_on, force_en, ret);
+ else
+ GDL_LOGXD(link_id, "on = %d, force = %d, select ret = %d", dsp_is_on, force_en, ret);
+}
+
+bool gps_dl_get_iomem_by_name(struct platform_device *pdev, const char *p_name,
+ struct gps_dl_iomem_addr_map_entry *p_entry)
+{
+ struct resource *regs;
+ bool okay;
+
+ regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, p_name);
+ if (regs != NULL) {
+ p_entry->length = resource_size(regs);
+ p_entry->host_phys_addr = regs->start;
+ p_entry->host_virt_addr = devm_ioremap(&pdev->dev, p_entry->host_phys_addr, p_entry->length);
+ okay = true;
+ } else {
+ p_entry->length = 0;
+ p_entry->host_phys_addr = 0;
+ p_entry->host_virt_addr = 0;
+ okay = false;
+ }
+
+ GDL_LOGW_INI("phy_addr = 0x%08x, vir_addr = 0x%p, ok = %d, size = 0x%x, name = %s",
+ p_entry->host_phys_addr, p_entry->host_virt_addr, okay, p_entry->length, p_name);
+
+ return okay;
+}
+
+#if (GPS_DL_GET_RSV_MEM_IN_MODULE)
+phys_addr_t gGpsRsvMemPhyBase;
+unsigned long long gGpsRsvMemSize;
+static int gps_dl_get_reserved_memory(struct device *dev)
+{
+ struct device_node *np;
+ struct reserved_mem *rmem;
+
+ np = of_parse_phandle(dev->of_node, "memory-region", 0);
+ if (!np) {
+ GDL_LOGE_INI("no memory-region 1");
+ return -EINVAL;
+ }
+ rmem = of_reserved_mem_lookup(np);
+ of_node_put(np);
+ if (!rmem) {
+ GDL_LOGE_INI("no memory-region 2");
+ return -EINVAL;
+ }
+ GDL_LOGW_INI("resource base=%pa, size=%pa", &rmem->base, &rmem->size);
+ gGpsRsvMemPhyBase = (phys_addr_t)rmem->base;
+ gGpsRsvMemSize = (unsigned long long)rmem->size;
+ return 0;
+}
+#endif
+bool gps_dl_read_pmic_efuse_reg(unsigned int reg, unsigned int *val)
+{
+
+ int ret;
+
+ if (!g_gps_dl_pmic_regmap_ptr)
+ return false;
+
+ ret = regmap_read(g_gps_dl_pmic_regmap_ptr, reg, val);
+ return ret < 0?false:true;
+}
+
+static struct regmap *gps_dl_get_pmic_regmap(struct device *pdev)
+{
+
+ struct device_node *pmic_node;
+ struct platform_device *pmic_pdev;
+ struct mt6397_chip *chip;
+ struct regmap *regmap;
+ int retval;
+
+ pmic_node = of_parse_phandle(pdev->of_node, "pmic", 0);
+
+ if (!pmic_node) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ pmic_pdev = of_find_device_by_node(pmic_node);
+ if (!pmic_pdev) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ chip = dev_get_drvdata(&(pmic_pdev->dev));
+ if (!chip) {
+ retval = -ENODEV;
+ goto error;
+ }
+
+ regmap = chip->regmap;
+ if (!regmap) {
+ retval = -ENODEV;
+ goto error;
+ }
+ return regmap;
+
+error:
+ return ERR_PTR(retval);
+}
+
+static int gps_dl_probe(struct platform_device *pdev)
+{
+ struct resource *irq;
+ struct gps_each_device *p_each_dev0 = gps_dl_device_get(GPS_DATA_LINK_ID0);
+ struct gps_each_device *p_each_dev1 = gps_dl_device_get(GPS_DATA_LINK_ID1);
+ struct regmap *pmic_regmap_ptr;
+ int i;
+ bool okay;
+
+#if (GPS_DL_GET_RSV_MEM_IN_MODULE)
+ gps_dl_get_reserved_memory(&pdev->dev);
+#endif
+ gps_dl_get_iomem_by_name(pdev, "conn_infra_base", &g_gps_dl_iomem_arrary[0]);
+ gps_dl_get_iomem_by_name(pdev, "conn_gps_base", &g_gps_dl_iomem_arrary[1]);
+
+ okay = gps_dl_get_iomem_by_name(pdev, "status_dummy_cr", &g_gps_dl_status_dummy_cr);
+ if (okay)
+ gps_dl_update_status_for_md_blanking(false);
+
+ /* TIA 1 */
+ gps_dl_get_iomem_by_name(pdev, "tia_gps", &g_gps_dl_tia1_gps);
+
+ /* TIA 2 */
+ gps_dl_get_iomem_by_name(pdev, "tia2_gps_on", &g_gps_dl_tia2_gps_on);
+ gps_dl_get_iomem_by_name(pdev, "tia2_gps_rc_sel", &g_gps_dl_tia2_gps_rc_sel);
+
+ for (i = 0; i < GPS_DL_IRQ_NUM; i++) {
+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+ if (irq == NULL) {
+ GDL_LOGE_INI("irq idx = %d, ptr = NULL!", i);
+ continue;
+ }
+
+ GDL_LOGW_INI("irq idx = %d, start = %lld, end = %lld, name = %s, flag = 0x%lx",
+ i, irq->start, irq->end, irq->name, irq->flags);
+ gps_dl_irq_set_id(i, irq->start);
+ }
+
+ g_gps_dl_pinctrl_ptr = devm_pinctrl_get(&pdev->dev);
+ if (IS_ERR(g_gps_dl_pinctrl_ptr))
+ GDL_LOGE_INI("devm_pinctrl_get fail");
+ else {
+ gps_dl_pinctrl_context_init();
+ gps_dl_pinctrl_show_info();
+ }
+ pmic_regmap_ptr = gps_dl_get_pmic_regmap(&pdev->dev);
+ if (IS_ERR(pmic_regmap_ptr)) {
+ g_gps_dl_pmic_regmap_ptr = NULL;
+ GDL_LOGE_INI("GPS get regmap fail\n");
+ }
+ else {
+ g_gps_dl_pmic_regmap_ptr = pmic_regmap_ptr;
+ GDL_LOGW_INI("GPS get regmap successfully\n");
+ }
+
+ GDL_LOGW_INI("do gps_dl_probe");
+ platform_set_drvdata(pdev, p_each_dev0);
+ p_each_dev0->private_data = (struct device *)&pdev->dev;
+ p_each_dev1->private_data = (struct device *)&pdev->dev;
+
+ gps_dl_device_context_init();
+
+ return 0;
+}
+
+static int gps_dl_remove(struct platform_device *pdev)
+{
+ struct gps_each_device *p_each_dev = gps_dl_device_get(GPS_DATA_LINK_ID0);
+
+ GDL_LOGW_INI("do gps_dl_remove");
+ platform_set_drvdata(pdev, NULL);
+ p_each_dev->private_data = NULL;
+ return 0;
+}
+
+static int gps_dl_drv_suspend(struct device *dev)
+{
+#if 0
+ struct platform_device *pdev = to_platform_device(dev);
+ pm_message_t state = PMSG_SUSPEND;
+
+ return mtk_btif_suspend(pdev, state);
+#endif
+ return 0;
+}
+
+static int gps_dl_drv_resume(struct device *dev)
+{
+#if 0
+ struct platform_device *pdev = to_platform_device(dev);
+
+ return mtk_btif_resume(pdev);
+#endif
+ return 0;
+}
+
+static int gps_dl_plat_suspend(struct platform_device *pdev, pm_message_t state)
+{
+#if 0
+ int i_ret = 0;
+ struct _mtk_btif_ *p_btif = NULL;
+
+ BTIF_DBG_FUNC("++\n");
+ p_btif = platform_get_drvdata(pdev);
+ i_ret = _btif_suspend(p_btif);
+ BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret);
+ return i_ret;
+#endif
+ return 0;
+}
+
+static int gps_dl_plat_resume(struct platform_device *pdev)
+{
+#if 0
+ int i_ret = 0;
+ struct _mtk_btif_ *p_btif = NULL;
+
+ BTIF_DBG_FUNC("++\n");
+ p_btif = platform_get_drvdata(pdev);
+ i_ret = _btif_resume(p_btif);
+ BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret);
+ return i_ret;
+#endif
+ return 0;
+}
+
+
+const struct dev_pm_ops gps_dl_drv_pm_ops = {
+ .suspend = gps_dl_drv_suspend,
+ .resume = gps_dl_drv_resume,
+};
+
+struct platform_driver gps_dl_dev_drv = {
+ .probe = gps_dl_probe,
+ .remove = gps_dl_remove,
+/* #ifdef CONFIG_PM */
+ .suspend = gps_dl_plat_suspend,
+ .resume = gps_dl_plat_resume,
+/* #endif */
+ .driver = {
+ .name = "gps", /* mediatek,gps */
+ .owner = THIS_MODULE,
+/* #ifdef CONFIG_PM */
+ .pm = &gps_dl_drv_pm_ops,
+/* #endif */
+/* #ifdef CONFIG_OF */
+ .of_match_table = gps_dl_of_ids,
+/* #endif */
+ }
+};
+
+static ssize_t driver_flag_read(struct device_driver *drv, char *buf)
+{
+ return sprintf(buf, "gps dl driver debug level:%d\n", 1);
+}
+
+static ssize_t driver_flag_set(struct device_driver *drv,
+ const char *buffer, size_t count)
+{
+ GDL_LOGW_INI("buffer = %s, count = %zd", buffer, count);
+ return count;
+}
+
+#define DRIVER_ATTR(_name, _mode, _show, _store) \
+ struct driver_attribute driver_attr_##_name = \
+ __ATTR(_name, _mode, _show, _store)
+static DRIVER_ATTR(flag, 0644, driver_flag_read, driver_flag_set);
+
+
+int gps_dl_linux_plat_drv_register(void)
+{
+ int result;
+ gps_dl_wake_lock_init();
+
+ result = platform_driver_register(&gps_dl_dev_drv);
+ /* if (result) */
+ GDL_LOGW_INI("platform_driver_register, ret(%d)\n", result);
+
+ result = driver_create_file(&gps_dl_dev_drv.driver, &driver_attr_flag);
+ /* if (result) */
+ GDL_LOGW_INI("driver_create_file, ret(%d)\n", result);
+
+ return 0;
+}
+
+int gps_dl_linux_plat_drv_unregister(void)
+{
+ driver_remove_file(&gps_dl_dev_drv.driver, &driver_attr_flag);
+ platform_driver_unregister(&gps_dl_dev_drv);
+ gps_dl_wake_lock_deinit();
+
+ return 0;
+}
+
+static struct wakeup_source *g_gps_dl_wake_lock_ptr;
+const char c_gps_dl_wake_lock_name[] = "gpsdl_wakelock";
+void gps_dl_wake_lock_init(void)
+{
+ GDL_LOGD_INI("");
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 149)
+ g_gps_dl_wake_lock_ptr = wakeup_source_register(NULL, c_gps_dl_wake_lock_name);
+#else
+ g_gps_dl_wake_lock_ptr = wakeup_source_register(c_gps_dl_wake_lock_name);
+#endif
+}
+
+void gps_dl_wake_lock_deinit(void)
+{
+ GDL_LOGD_INI("");
+ wakeup_source_unregister(g_gps_dl_wake_lock_ptr);
+}
+
+void gps_dl_wake_lock_hold(bool hold)
+{
+ GDL_LOGD_ONF("hold = %d", hold);
+ if (hold)
+ __pm_stay_awake(g_gps_dl_wake_lock_ptr);
+ else
+ __pm_relax(g_gps_dl_wake_lock_ptr);
+}
+
+#endif /* GPS_DL_HAS_PLAT_DRV */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_linux_reserved_mem.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_linux_reserved_mem.c
new file mode 100644
index 0000000..f131982
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_linux_reserved_mem.c
@@ -0,0 +1,206 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#include "gps_dl_config.h"
+
+#if GPS_DL_HAS_PLAT_DRV
+#include "gps_dl_context.h"
+#include "gps_dl_linux_plat_drv.h"
+#include "gps_dl_linux_reserved_mem.h"
+#include "gps_dl_emi.h"
+
+#include <linux/of_reserved_mem.h>
+
+#if (GPS_DL_SET_EMI_MPU_CFG)
+#include <memory/mediatek/emi.h>
+#define GPS_DL_EMI_MPU_DOMAIN_AP 0
+#define GPS_DL_EMI_MPU_DOMAIN_CONN 2
+#define GPS_DL_EMI_MPU_REGION_NUM 29
+#endif
+
+#define GPS_ICAP_MEM_SIZE (GPS_ICAP_BUF_SIZE)
+#define GPS_RESERVED_MEM_PADDING_SIZE (4*1024)
+
+struct gps_dl_reserved_mem_layout {
+ unsigned char icap_buf[GPS_ICAP_MEM_SIZE];
+ unsigned char padding1[GPS_RESERVED_MEM_PADDING_SIZE];
+ unsigned char tx_dma_buf[GPS_DATA_LINK_NUM][GPS_DL_RX_BUF_SIZE + GPS_RESERVED_MEM_PADDING_SIZE];
+ unsigned char rx_dma_buf[GPS_DATA_LINK_NUM][GPS_DL_RX_BUF_SIZE + GPS_RESERVED_MEM_PADDING_SIZE];
+};
+
+struct gps_dl_iomem_addr_map_entry g_gps_dl_res_emi;
+
+void gps_dl_reserved_mem_init(void)
+{
+ void __iomem *host_virt_addr = NULL;
+#if (GPS_DL_SET_EMI_MPU_CFG)
+ struct emimpu_region_t region;
+ int emimpu_ret1, emimpu_ret2, emimpu_ret3, emimpu_ret4, emimpu_ret5, emimpu_ret6;
+#endif
+ unsigned int min_size = sizeof(struct gps_dl_reserved_mem_layout);
+
+ if (gGpsRsvMemPhyBase == (phys_addr_t)NULL || gGpsRsvMemSize < min_size) {
+ GDL_LOGE_INI("res_mem: base = 0x%llx, size = 0x%llx, min_size = %d, not enough",
+ (unsigned long long)gGpsRsvMemPhyBase,
+ (unsigned long long)gGpsRsvMemSize, min_size);
+ return;
+ }
+
+ host_virt_addr = ioremap_nocache(gGpsRsvMemPhyBase, gGpsRsvMemSize);
+ if (host_virt_addr == NULL) {
+ GDL_LOGE_INI("res_mem: base = 0x%llx, size = 0x%llx, ioremap fail",
+ (unsigned long long)gGpsRsvMemPhyBase, (unsigned long long)gGpsRsvMemSize);
+ return;
+ }
+
+ /* Set EMI MPU permission */
+#if (GPS_DL_SET_EMI_MPU_CFG)
+ GDL_LOGI_INI("emi mpu cfg: region = %d, no protection domain = %d, %d",
+ GPS_DL_EMI_MPU_REGION_NUM, GPS_DL_EMI_MPU_DOMAIN_AP, GPS_DL_EMI_MPU_DOMAIN_CONN);
+ emimpu_ret1 = mtk_emimpu_init_region(®ion, GPS_DL_EMI_MPU_REGION_NUM);
+ emimpu_ret2 = mtk_emimpu_set_addr(®ion, gGpsRsvMemPhyBase, gGpsRsvMemPhyBase + gGpsRsvMemSize - 1);
+ emimpu_ret3 = mtk_emimpu_set_apc(®ion, GPS_DL_EMI_MPU_DOMAIN_AP, MTK_EMIMPU_NO_PROTECTION);
+ emimpu_ret4 = mtk_emimpu_set_apc(®ion, GPS_DL_EMI_MPU_DOMAIN_CONN, MTK_EMIMPU_NO_PROTECTION);
+ emimpu_ret5 = mtk_emimpu_set_protection(®ion);
+
+ GDL_LOGI_INI("[mpu_debug]emi mpu cfg: ret = %d, %d, %d, %d, %d",
+ emimpu_ret1, emimpu_ret2, emimpu_ret3, emimpu_ret4, emimpu_ret5);
+
+ emimpu_ret6 = mtk_emimpu_free_region(®ion);
+ GDL_LOGI_INI("emi mpu cfg: ret = %d, %d, %d, %d, %d, %d",
+ emimpu_ret1, emimpu_ret2, emimpu_ret3, emimpu_ret4, emimpu_ret5, emimpu_ret6);
+#endif
+
+ g_gps_dl_res_emi.host_phys_addr = gGpsRsvMemPhyBase;
+ g_gps_dl_res_emi.host_virt_addr = host_virt_addr;
+ g_gps_dl_res_emi.length = gGpsRsvMemSize;
+
+ GDL_LOGI_INI("phy_addr = 0x%08x, vir_addr = 0x%p, size = 0x%x, min_size = 0x%x",
+ g_gps_dl_res_emi.host_phys_addr,
+ g_gps_dl_res_emi.host_virt_addr,
+ g_gps_dl_res_emi.length, min_size);
+ gps_dl_reserved_mem_show_info();
+ gps_icap_probe();
+}
+
+void gps_dl_reserved_mem_deinit(void)
+{
+ GDL_LOGI_INI("phy_addr = 0x%08x, vir_addr = 0x%p, size = 0x%x",
+ g_gps_dl_res_emi.host_phys_addr,
+ g_gps_dl_res_emi.host_virt_addr,
+ g_gps_dl_res_emi.length);
+
+ if (g_gps_dl_res_emi.host_virt_addr != NULL)
+ iounmap(g_gps_dl_res_emi.host_virt_addr);
+ else
+ GDL_LOGW_INI("host_virt_addr already null, not do iounmap");
+
+ g_gps_dl_res_emi.host_phys_addr = (dma_addr_t)NULL;
+ g_gps_dl_res_emi.host_virt_addr = (void *)NULL;
+ g_gps_dl_res_emi.length = 0;
+}
+
+bool gps_dl_reserved_mem_is_ready(void)
+{
+ return (g_gps_dl_res_emi.host_virt_addr != NULL);
+}
+
+void gps_dl_reserved_mem_get_range(unsigned int *p_min, unsigned int *p_max)
+{
+ *p_min = g_gps_dl_res_emi.host_phys_addr;
+ *p_max = g_gps_dl_res_emi.host_phys_addr + g_gps_dl_res_emi.length;
+}
+
+void gps_dl_reserved_mem_show_info(void)
+{
+ unsigned int min_size = sizeof(struct gps_dl_reserved_mem_layout);
+ struct gps_dl_reserved_mem_layout *p_mem_vir;
+ unsigned int p_mem_phy;
+ unsigned int p_buf_phy, offset;
+ enum gps_dl_link_id_enum link_id;
+
+ p_mem_phy = g_gps_dl_res_emi.host_phys_addr;
+ p_mem_vir = (struct gps_dl_reserved_mem_layout *)g_gps_dl_res_emi.host_virt_addr;
+
+ GDL_LOGI_INI("phy_addr = 0x%08x, vir_addr = 0x%p, size = 0x%x, min_size = 0x%x",
+ g_gps_dl_res_emi.host_phys_addr,
+ g_gps_dl_res_emi.host_virt_addr,
+ g_gps_dl_res_emi.length, min_size);
+
+ offset = (unsigned int)((void *)&p_mem_vir->icap_buf[0] - (void *)p_mem_vir);
+ GDL_LOGD_INI("icap_buf: phy_addr = 0x%08x, vir_addr = 0x%p, size = 0x%x",
+ p_mem_phy + offset, &p_mem_vir->icap_buf[0], GPS_ICAP_MEM_SIZE);
+
+ for (link_id = 0; link_id < GPS_DATA_LINK_NUM; link_id++) {
+ offset = (unsigned int)((void *)&p_mem_vir->tx_dma_buf[link_id][0] - (void *)p_mem_vir);
+ p_buf_phy = p_mem_phy + offset;
+ GDL_LOGXD_INI(link_id, "tx_dma_buf: phy_addr = 0x%08x, vir_addr = 0x%p, size = 0x%x",
+ p_buf_phy, &p_mem_vir->tx_dma_buf[link_id][0], GPS_DL_TX_BUF_SIZE);
+
+ offset = (unsigned int)((void *)&p_mem_vir->rx_dma_buf[link_id][0] - (void *)p_mem_vir);
+ p_buf_phy = p_mem_phy + offset;
+ GDL_LOGXD_INI(link_id, "rx_dma_buf: phy_addr = 0x%08x, vir_addr = 0x%p, size = 0x%x",
+ p_buf_phy, &p_mem_vir->rx_dma_buf[link_id][0], GPS_DL_RX_BUF_SIZE);
+ }
+}
+
+void gps_dl_reserved_mem_dma_buf_init(struct gps_dl_dma_buf *p_dma_buf,
+ enum gps_dl_link_id_enum link_id, enum gps_dl_dma_dir dir, unsigned int len)
+{
+ struct gps_dl_reserved_mem_layout *p_mem_vir;
+ unsigned int p_mem_phy, offset;
+
+ p_mem_vir = (struct gps_dl_reserved_mem_layout *)g_gps_dl_res_emi.host_virt_addr;
+ p_mem_phy = g_gps_dl_res_emi.host_phys_addr;
+
+ memset(p_dma_buf, 0, sizeof(*p_dma_buf));
+ p_dma_buf->dev_index = link_id;
+ p_dma_buf->dir = dir;
+ p_dma_buf->len = len;
+
+ if (dir == GDL_DMA_A2D) {
+ p_dma_buf->vir_addr = (void *)&p_mem_vir->tx_dma_buf[link_id][0];
+ } else if (dir == GDL_DMA_D2A) {
+ p_dma_buf->vir_addr = (void *)&p_mem_vir->rx_dma_buf[link_id][0];
+ } else {
+ GDL_LOGXE(link_id, "");
+ return;
+ }
+
+ offset = (unsigned int)((void *)p_dma_buf->vir_addr - (void *)p_mem_vir);
+ p_dma_buf->phy_addr = p_mem_phy + offset;
+
+ GDL_LOGI_INI("init gps dl dma buf(%d,%d) in arch64, addr: vir=0x%p, phy=0x%llx, len=%u\n",
+ p_dma_buf->dev_index, p_dma_buf->dir,
+ p_dma_buf->vir_addr,
+ p_dma_buf->phy_addr, p_dma_buf->len);
+}
+
+void gps_dl_reserved_mem_dma_buf_deinit(struct gps_dl_dma_buf *p_dma_buf)
+{
+ memset(p_dma_buf, 0, sizeof(*p_dma_buf));
+}
+
+void *gps_dl_reserved_mem_icap_buf_get_vir_addr(void)
+{
+ struct gps_dl_reserved_mem_layout *p_mem_vir;
+ unsigned int p_mem_phy, offset;
+
+ p_mem_phy = g_gps_dl_res_emi.host_phys_addr;
+ p_mem_vir = (struct gps_dl_reserved_mem_layout *)g_gps_dl_res_emi.host_virt_addr;
+
+ if (p_mem_vir == NULL) {
+ GDL_LOGE("gps_icap_buf: null");
+ return NULL;
+ }
+
+ offset = (unsigned int)((void *)&p_mem_vir->icap_buf[0] - (void *)p_mem_vir);
+ GDL_LOGI("gps_icap_buf: phy_addr = 0x%08x, vir_addr = 0x%p, size = 0x%x",
+ p_mem_phy + offset, &p_mem_vir->icap_buf[0], GPS_ICAP_MEM_SIZE);
+
+ return (void *)&p_mem_vir->icap_buf[0];
+}
+
+#endif /* GPS_DL_HAS_PLAT_DRV */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_osal.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_osal.c
new file mode 100644
index 0000000..2dc57d6
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_osal.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+
+#include "gps_dl_osal.h"
+#include "gps_dl_log.h"
+
+
+char *gps_dl_osal_strncpy(char *dst, const char *src, unsigned int len)
+{
+ return strncpy(dst, src, len);
+}
+
+char *gps_dl_osal_strsep(char **str, const char *c)
+{
+ return strsep(str, c);
+}
+
+int gps_dl_osal_strtol(const char *str, unsigned int adecimal, long *res)
+{
+ if (sizeof(long) == 4)
+ return kstrtou32(str, adecimal, (unsigned int *) res);
+ else
+ return kstrtol(str, adecimal, res);
+}
+
+void *gps_dl_osal_memset(void *buf, int i, unsigned int len)
+{
+ return memset(buf, i, len);
+}
+
+int gps_dl_osal_thread_create(struct gps_dl_osal_thread *pThread)
+{
+ if (!pThread)
+ return -1;
+
+ pThread->pThread = kthread_create(pThread->pThreadFunc, pThread->pThreadData, pThread->threadName);
+ if (pThread->pThread == NULL)
+ return -1;
+
+ return 0;
+}
+
+int gps_dl_osal_thread_run(struct gps_dl_osal_thread *pThread)
+{
+ if ((pThread) && (pThread->pThread)) {
+ wake_up_process(pThread->pThread);
+ return 0;
+ } else
+ return -1;
+}
+
+int gps_dl_osal_thread_stop(struct gps_dl_osal_thread *pThread)
+{
+ int iRet;
+
+ if ((pThread) && (pThread->pThread)) {
+ iRet = kthread_stop(pThread->pThread);
+ /* pThread->pThread = NULL; */
+ return iRet;
+ }
+ return -1;
+}
+
+int gps_dl_osal_thread_should_stop(struct gps_dl_osal_thread *pThread)
+{
+ if ((pThread) && (pThread->pThread))
+ return kthread_should_stop();
+ else
+ return 1;
+
+}
+
+int gps_dl_osal_thread_destroy(struct gps_dl_osal_thread *pThread)
+{
+ if (pThread && (pThread->pThread)) {
+ kthread_stop(pThread->pThread);
+ pThread->pThread = NULL;
+ }
+ return 0;
+}
+
+int gps_dl_osal_thread_wait_for_event(struct gps_dl_osal_thread *pThread,
+ struct gps_dl_osal_event *pEvent, OSAL_EVENT_CHECKER pChecker)
+{
+ if ((pThread) && (pThread->pThread) && (pEvent) && (pChecker)) {
+ return wait_event_interruptible(pEvent->waitQueue, (
+ gps_dl_osal_thread_should_stop(pThread)
+ || (*pChecker) (pThread)));
+ }
+ return -1;
+}
+
+int gps_dl_osal_signal_init(struct gps_dl_osal_signal *pSignal)
+{
+ if (pSignal) {
+ init_completion(&pSignal->comp);
+ return 0;
+ } else
+ return -1;
+}
+
+int gps_dl_osal_wait_for_signal(struct gps_dl_osal_signal *pSignal)
+{
+ if (pSignal) {
+ wait_for_completion_interruptible(&pSignal->comp);
+ return 0;
+ } else
+ return -1;
+}
+
+/*
+ * gps_dl_osal_wait_for_signal_timeout
+ *
+ * Wait for a signal to be triggered by the corresponding thread, within the
+ * expected timeout specified by the signal's timeoutValue.
+ * When the pThread parameter is specified, the thread's scheduling ability is
+ * considered, the timeout will be extended when thread cannot acquire CPU
+ * resource, and will only extend for a number of times specified by the
+ * signal's timeoutExtension should the situation continues.
+ *
+ * Return value:
+ * 0 : timeout
+ * >0 : signal triggered
+ */
+int gps_dl_osal_wait_for_signal_timeout(struct gps_dl_osal_signal *pSignal, struct gps_dl_osal_thread *pThread)
+{
+ /* struct gps_dl_osal_thread_schedstats schedstats; */
+ /* int waitRet; */
+
+ /* return wait_for_completion_interruptible_timeout(&pSignal->comp, msecs_to_jiffies(pSignal->timeoutValue)); */
+ /* [ChangeFeature][George] gps driver may be closed by -ERESTARTSYS.
+ * Avoid using *interruptible" version in order to complete our jobs, such
+ * as function off gracefully.
+ */
+ if (!pThread || !pThread->pThread)
+ return wait_for_completion_timeout(&pSignal->comp, msecs_to_jiffies(pSignal->timeoutValue));
+#if 0
+ do {
+ osal_thread_sched_mark(pThread, &schedstats);
+ waitRet = wait_for_completion_timeout(&pSignal->comp, msecs_to_jiffies(pSignal->timeoutValue));
+ osal_thread_sched_unmark(pThread, &schedstats);
+
+ if (waitRet > 0)
+ break;
+
+ if (schedstats.runnable > schedstats.exec) {
+ gps_dl_osal_err_print(
+ "[E]%s:wait completion timeout, %s cannot get CPU, extension(%d), show backtrace:\n",
+ __func__,
+ pThread->threadName,
+ pSignal->timeoutExtension);
+ } else {
+ gps_dl_osal_err_print("[E]%s:wait completion timeout, show %s backtrace:\n",
+ __func__,
+ pThread->threadName);
+ pSignal->timeoutExtension = 0;
+ }
+ gps_dl_osal_err_print("[E]%s:\tduration:%llums, sched(x%llu/r%llu/i%llu)\n",
+ __func__,
+ schedstats.time,
+ schedstats.exec,
+ schedstats.runnable,
+ schedstats.iowait);
+ /*
+ * no need to disginguish combo or A/D die projects
+ * osal_dump_thread_state will just return if target thread does not exist
+ */
+ osal_dump_thread_state("mtk_wmtd");
+ osal_dump_thread_state("btif_rxd");
+ osal_dump_thread_state("mtk_stp_psm");
+ osal_dump_thread_state("mtk_stp_btm");
+ osal_dump_thread_state("stp_sdio_tx_rx");
+ } while (pSignal->timeoutExtension--);
+ return waitRet;
+#endif
+ return 1;
+}
+
+int gps_dl_osal_raise_signal(struct gps_dl_osal_signal *pSignal)
+{
+ if (pSignal) {
+ complete(&pSignal->comp);
+ return 0;
+ } else
+ return -1;
+}
+
+int gps_dl_osal_signal_active_state(struct gps_dl_osal_signal *pSignal)
+{
+ if (pSignal)
+ return pSignal->timeoutValue;
+ else
+ return -1;
+}
+
+int gps_dl_osal_op_is_wait_for_signal(struct gps_dl_osal_lxop *pOp)
+{
+ return (pOp && pOp->signal.timeoutValue) ? 1 : 0;
+}
+
+void gps_dl_osal_op_raise_signal(struct gps_dl_osal_lxop *pOp, int result)
+{
+ if (pOp) {
+ pOp->result = result;
+ gps_dl_osal_raise_signal(&pOp->signal);
+ }
+}
+
+int gps_dl_osal_signal_deinit(struct gps_dl_osal_signal *pSignal)
+{
+ if (pSignal) {
+ pSignal->timeoutValue = 0;
+ return 0;
+ } else
+ return -1;
+}
+
+/*
+ *OSAL layer Event Opeartion related APIs
+ *initialization
+ *wait for signal
+ *wait for signal timerout
+ *raise signal
+ *destroy a signal
+ *
+*/
+
+int gps_dl_osal_event_init(struct gps_dl_osal_event *pEvent)
+{
+ if (pEvent) {
+ init_waitqueue_head(&pEvent->waitQueue);
+ return 0;
+ }
+ return -1;
+}
+
+int gps_dl_osal_trigger_event(struct gps_dl_osal_event *pEvent)
+{
+ int ret = 0;
+
+ if (pEvent) {
+ wake_up_interruptible(&pEvent->waitQueue);
+ return ret;
+ }
+ return -1;
+}
+
+int gps_dl_osal_wait_for_event(struct gps_dl_osal_event *pEvent, int (*condition)(void *), void *cond_pa)
+{
+ if (pEvent)
+ return wait_event_interruptible(pEvent->waitQueue, condition(cond_pa));
+ else
+ return -1;
+}
+
+int gps_dl_osal_wait_for_event_timeout(struct gps_dl_osal_event *pEvent, int (*condition)(void *), void *cond_pa)
+{
+ if (pEvent)
+ return wait_event_interruptible_timeout(pEvent->waitQueue,
+ condition(cond_pa),
+ msecs_to_jiffies(pEvent->timeoutValue));
+ return -1;
+}
+
+int gps_dl_osal_event_deinit(struct gps_dl_osal_event *pEvent)
+{
+ return 0;
+}
+
+int gps_dl_osal_sleepable_lock_init(struct gps_dl_osal_sleepable_lock *pSL)
+{
+ mutex_init(&pSL->lock);
+ return 0;
+}
+
+int gps_dl_osal_lock_sleepable_lock(struct gps_dl_osal_sleepable_lock *pSL)
+{
+ return mutex_lock_killable(&pSL->lock);
+}
+
+int gps_dl_osal_unlock_sleepable_lock(struct gps_dl_osal_sleepable_lock *pSL)
+{
+ mutex_unlock(&pSL->lock);
+ return 0;
+}
+
+int gps_dl_osal_trylock_sleepable_lock(struct gps_dl_osal_sleepable_lock *pSL)
+{
+ return mutex_trylock(&pSL->lock);
+}
+
+int gps_dl_osal_sleepable_lock_deinit(struct gps_dl_osal_sleepable_lock *pSL)
+{
+ mutex_destroy(&pSL->lock);
+ return 0;
+}
+
+int gps_dl_osal_unsleepable_lock_init(struct gps_dl_osal_unsleepable_lock *pUSL)
+{
+ spin_lock_init(&(pUSL->lock));
+ return 0;
+}
+
+int gps_dl_osal_lock_unsleepable_lock(struct gps_dl_osal_unsleepable_lock *pUSL)
+{
+ spin_lock_irqsave(&(pUSL->lock), pUSL->flag);
+ return 0;
+}
+
+int gps_dl_osal_unlock_unsleepable_lock(struct gps_dl_osal_unsleepable_lock *pUSL)
+{
+ spin_unlock_irqrestore(&(pUSL->lock), pUSL->flag);
+ return 0;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_procfs.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_procfs.c
new file mode 100644
index 0000000..95902ac
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_dl_procfs.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_dl_config.h"
+
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+
+#include "gps_dl_osal.h"
+#include "gps_dl_procfs.h"
+#include "gps_each_link.h"
+#include "gps_dl_subsys_reset.h"
+#include "gps_dl_linux_plat_drv.h"
+#include "gps_each_device.h"
+
+int gps_dl_procfs_dummy_op(int y, int z)
+{
+ GDL_LOGW("do nothing: y = %d, z = %d", y, z);
+ return 0;
+}
+
+int gps_dl_procfs_set_opt(int y, int z)
+{
+ if (y == 0)
+ gps_dl_log_info_show();
+ else if (y == 1) {
+ enum gps_dl_log_level_enum level_old, level_new;
+
+ level_old = gps_dl_log_level_get();
+ gps_dl_log_level_set(z);
+ level_new = gps_dl_log_level_get();
+ GDL_LOGW("log level change: %d to %d", level_old, level_new);
+ } else if (y == 2) {
+ unsigned int mod_old, mod_new;
+
+ mod_old = gps_dl_log_mod_bitmask_get();
+ gps_dl_log_mod_bitmask_set(z);
+ mod_new = gps_dl_log_level_get();
+ GDL_LOGW("log modules change: 0x%x to 0x%x", mod_old, mod_new);
+ } else if (y == 3) {
+ unsigned int mod_old, mod_new;
+
+ mod_old = gps_dl_log_mod_bitmask_get();
+ gps_dl_log_mod_on(z);
+ mod_new = gps_dl_log_level_get();
+ GDL_LOGW("log modules change: 0x%x to 0x%x", mod_old, mod_new);
+ } else if (y == 4) {
+ unsigned int mod_old, mod_new;
+
+ mod_old = gps_dl_log_mod_bitmask_get();
+ gps_dl_log_mod_off(z);
+ mod_new = gps_dl_log_level_get();
+ GDL_LOGW("log modules change: 0x%x to 0x%x", mod_old, mod_new);
+ }
+
+ return 0;
+}
+
+int gps_dl_procfs_trigger_reset(int y, int z)
+{
+ if (y == 0)
+ gps_dl_trigger_connsys_reset();
+ else if (y == 1)
+ gps_dl_trigger_gps_subsys_reset((bool)z);
+ else if (y == 2 && (z >= 0 && z <= GPS_DATA_LINK_NUM))
+ gps_each_link_reset(z);
+ else if (y == 3)
+ gps_dl_trigger_gps_print_hw_status();
+ else if (y == 4 && (z >= 0 && z <= GPS_DATA_LINK_NUM))
+ gps_dl_test_mask_hasdata_irq_set(z, true);
+ else if (y == 6 && (z >= 0 && z <= GPS_DATA_LINK_NUM))
+ gps_dl_test_mask_mcub_irq_on_open_set(z, true);
+ else if (y == 7)
+ gps_dl_trigger_gps_print_data_status();
+ return 0;
+}
+
+int gps_dl_procfs_set_vcore_power(int y, int z)
+{
+
+ if (y > GPS_PROC_VCORE_REQUIRE_OFF) {
+ GDL_LOGE("GPS procfs set voltage fail, y=0x%x out of range, z=0x%x", y, z);
+ return 0;
+ }
+
+ GDL_LOGW("GPS procfs set voltage success, y=0x%x, z=0x%x", y, z);
+ gps_dl_procfs_vcore_action = y;
+ return 0;
+}
+
+int gps_dl_procfs_show_pmic_efuse_reg(int y, int z)
+{
+ unsigned int pmic_reg_val = 0;
+
+ if (true == gps_dl_read_pmic_efuse_reg((unsigned int)y, &pmic_reg_val))
+ GDL_LOGW("read efuse reg, y=0x%x, z=0x%x, value=0x%x", y, z, pmic_reg_val);
+ else
+ GDL_LOGW("read efuse reg fail, y=0x%x,z=0x%x", y, z);
+ return 0;
+}
+
+
+gps_dl_procfs_test_func_type g_gps_dl_proc_test_func_list[] = {
+ [0x00] = gps_dl_procfs_dummy_op,
+ /* [0x01] = TODO: reg read */
+ /* [0x02] = TODO: reg write */
+ [0x03] = gps_dl_procfs_set_opt,
+ [0x04] = gps_dl_procfs_trigger_reset,
+ [0x05] = gps_dl_procfs_show_pmic_efuse_reg,
+ [0x06] = gps_dl_procfs_set_vcore_power,
+};
+
+#define UNLOCK_MAGIC 0xDB9DB9
+#define PROCFS_WR_BUF_SIZE 256
+ssize_t gps_dl_procfs_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos)
+{
+ size_t len = count, sub_len;
+ char buf[PROCFS_WR_BUF_SIZE];
+ char *pBuf;
+ int x = 0, y = 0, z = 0;
+ char *pToken = NULL;
+ long res;
+ static bool gpsdl_dbg_enabled;
+
+ GDL_LOGD("write parameter len = %d", (int)len);
+ if (len >= PROCFS_WR_BUF_SIZE) {
+ GDL_LOGE("input handling fail!");
+ return -1;
+ }
+
+ if (copy_from_user(buf, buffer, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+ pBuf = buf;
+ do {
+ if (!pBuf) {
+ GDL_LOGW("x,y,z use default value - case0");
+ break;
+ }
+ res = 0;
+ sub_len = strlen(pBuf);
+ GDL_LOGD("write parameter data = %s, len = %ld", pBuf, sub_len);
+ if (sub_len != 0)
+ pToken = gps_dl_osal_strsep(&pBuf, "\t\n\r ");
+ if (sub_len != 0 && pToken != NULL) {
+ gps_dl_osal_strtol(pToken, 16, &res);
+ x = (int)res;
+ } else {
+ GDL_LOGW("x use default value");
+ break;
+ }
+
+ if (!pBuf) {
+ GDL_LOGW("y use default value - case1");
+ break;
+ }
+ res = 0;
+ sub_len = strlen(pBuf);
+ GDL_LOGD("write parameter data = %s, len = %ld", pBuf, sub_len);
+ if (sub_len != 0)
+ pToken = gps_dl_osal_strsep(&pBuf, "\t\n\r ");
+ if (sub_len != 0 && pToken != NULL) {
+ gps_dl_osal_strtol(pToken, 16, &res);
+ y = (int)res;
+ } else {
+ GDL_LOGW("y use default value - case2");
+ break;
+ }
+
+ if (!pBuf) {
+ GDL_LOGW("z use default value - case1");
+ break;
+ }
+ res = 0;
+ sub_len = strlen(pBuf);
+ GDL_LOGD("write parameter data = %s, len = %ld", pBuf, sub_len);
+ if (sub_len != 0)
+ pToken = gps_dl_osal_strsep(&pBuf, "\t\n\r ");
+ if (sub_len != 0 && pToken != NULL) {
+ gps_dl_osal_strtol(pToken, 16, &res);
+ z = (int)res;
+ } else {
+ GDL_LOGW("z use default value - case2");
+ break;
+ }
+ } while (0);
+ GDL_LOGW("x = 0x%08x, y = 0x%08x, z = 0x%08x", x, y, z);
+
+ /* For eng and userdebug load, have to enable gpsdl_dbg by
+ * writing 0xDB9DB9 to * "/proc/driver/gpsdl_dbg" to avoid
+ * some malicious use
+ */
+ if (x == UNLOCK_MAGIC) {
+ gpsdl_dbg_enabled = true;
+ return len;
+ }
+
+ if (!gpsdl_dbg_enabled) {
+ GDL_LOGW("please enable gpsdl_dbg firstly");
+ return len;
+ }
+
+ if (ARRAY_SIZE(g_gps_dl_proc_test_func_list) > x && NULL != g_gps_dl_proc_test_func_list[x])
+ (*g_gps_dl_proc_test_func_list[x])(y, z);
+ else
+ GDL_LOGW("no handler defined for command id, x = 0x%08x", x);
+
+ return len;
+}
+
+ssize_t gps_dl_procfs_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
+{
+ return 0;
+}
+
+static const struct file_operations gps_dl_procfs_fops = {
+ .owner = THIS_MODULE,
+ .read = gps_dl_procfs_read,
+ .write = gps_dl_procfs_write,
+};
+
+static struct proc_dir_entry *g_gps_dl_procfs_entry;
+#define GPS_DL_PROCFS_NAME "driver/gpsdl_dbg"
+
+int gps_dl_procfs_setup(void)
+{
+
+ int i_ret = 0;
+
+ g_gps_dl_procfs_entry = proc_create(GPS_DL_PROCFS_NAME,
+ 0664, NULL, &gps_dl_procfs_fops);
+
+ if (g_gps_dl_procfs_entry == NULL) {
+ GDL_LOGE("Unable to create gps proc entry");
+ i_ret = -1;
+ }
+
+ return i_ret;
+}
+
+int gps_dl_procfs_remove(void)
+{
+ if (g_gps_dl_procfs_entry != NULL)
+ proc_remove(g_gps_dl_procfs_entry);
+ return 0;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_each_device.c b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_each_device.c
new file mode 100644
index 0000000..50ce3c6
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/gps_each_device.c
@@ -0,0 +1,600 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include "gps_each_device.h"
+#include "gps_each_link.h"
+#include "gps_dsp_fsm.h"
+#if GPS_DL_MOCK_HAL
+#include "gps_mock_mvcd.h"
+#endif
+#include "gps_dl_hal.h"
+#include "gps_dl_ctrld.h"
+#include "gps_data_link_devices.h"
+#include "gps_dl_subsys_reset.h"
+#include "gps_dl_hist_rec.h"
+#include "gps_dl_linux_plat_drv.h"
+
+#ifdef GPS_DL_HAS_PLAT_DRV
+struct gps_dl_vcore_context g_gps_dl_vcore_context;
+enum gps_dl_procfs_vcore_enum gps_dl_procfs_vcore_action;
+#endif
+
+static ssize_t gps_each_device_read(struct file *filp,
+ char __user *buf, size_t count, loff_t *f_pos)
+{
+ int retval;
+ int retlen;
+ int pid;
+ struct gps_each_device *dev;
+ enum gps_dl_link_id_enum link_id;
+ bool print_log = false;
+
+ dev = (struct gps_each_device *)filp->private_data;
+ pid = current->pid;
+ link_id = (enum gps_dl_link_id_enum)dev->index;
+
+ /* show read log after ram code downloading to avoid print too much */
+ if (gps_dsp_state_get(link_id) != GPS_DSP_ST_RESET_DONE) {
+ GDL_LOGXI_DRW(link_id, "buf_len = %ld, pid = %d", count, pid);
+ print_log = true;
+ } else {
+ GDL_LOGXD_DRW(link_id, "buf_len = %ld, pid = %d", count, pid);
+ }
+ gps_each_link_rec_read(link_id, pid, count, DRW_ENTER);
+
+ retlen = gps_each_link_read(link_id, &dev->i_buf[0], count);
+ if (retlen > 0) {
+ retval = copy_to_user(buf, &dev->i_buf[0], retlen);
+ if (retval != 0) {
+ GDL_LOGXW_DRW(link_id, "copy to user len = %d, retval = %d",
+ retlen, retval);
+ retlen = -EFAULT;
+ }
+ }
+ if (print_log)
+ GDL_LOGXI_DRW(link_id, "ret_len = %d", retlen);
+ else
+ GDL_LOGXD_DRW(link_id, "ret_len = %d", retlen);
+ gps_each_link_rec_read(link_id, pid, retlen, DRW_RETURN);
+ return retlen;
+}
+
+static ssize_t gps_each_device_write(struct file *filp,
+ const char __user *buf, size_t count, loff_t *f_pos)
+{
+ int retval;
+ int retlen = 0;
+ int copy_size;
+ int pid;
+ struct gps_each_device *dev;
+ enum gps_dl_link_id_enum link_id;
+ bool print_log = false;
+
+ dev = (struct gps_each_device *)filp->private_data;
+ pid = current->pid;
+ link_id = (enum gps_dl_link_id_enum)dev->index;
+
+ /* show write log after ram code downloading to avoid print too much */
+ if (gps_dsp_state_get(link_id) != GPS_DSP_ST_RESET_DONE) {
+ GDL_LOGXI_DRW(link_id, "len = %ld, pid = %d", count, pid);
+ print_log = true;
+ } else {
+ GDL_LOGXD_DRW(link_id, "len = %ld, pid = %d", count, pid);
+ }
+ gps_each_link_rec_write(link_id, pid, count, DRW_ENTER);
+
+ if (count > 0) {
+ if (count > GPS_DATA_PATH_BUF_MAX) {
+ GDL_LOGXW_DRW(link_id, "len = %ld is too long", count);
+ copy_size = GPS_DATA_PATH_BUF_MAX;
+ } else
+ copy_size = count;
+
+ retval = copy_from_user(&dev->o_buf[0], &buf[0], copy_size);
+ if (retval != 0) {
+ GDL_LOGXW_DRW(link_id, "copy from user len = %d, retval = %d",
+ copy_size, retval);
+ retlen = -EFAULT;
+ } else {
+ retval = gps_each_link_write(link_id, &dev->o_buf[0], copy_size);
+ if (retval == 0)
+ retlen = copy_size;
+ else
+ retlen = 0;
+ }
+ }
+
+ if (print_log)
+ GDL_LOGXI_DRW(link_id, "ret_len = %d", retlen);
+ else
+ GDL_LOGXD_DRW(link_id, "ret_len = %d", retlen);
+ gps_each_link_rec_write(link_id, pid, retlen, DRW_RETURN);
+ return retlen;
+}
+
+#if 0
+void gps_each_device_data_submit(unsigned char *buf, unsigned int len, int index)
+{
+ struct gps_each_device *dev;
+
+ dev = gps_dl_device_get(index);
+
+ GDL_LOGI("gps_each_device_data_submit len = %d, index = %d, dev = %p",
+ len, index, dev);
+
+ if (!dev)
+ return;
+
+ if (!dev->is_open)
+ return;
+
+#if GPS_DL_CTRLD_MOCK_LINK_LAYER
+ /* TODO: using mutex, len check */
+ memcpy(&dev->i_buf[0], buf, len);
+ dev->i_len = len;
+ wake_up(&dev->r_wq);
+#else
+ gps_dl_add_to_rx_queue(buf, len, index);
+ /* wake_up(&dev->r_wq); */
+#endif
+
+ GDL_LOGI("gps_each_device_data_submit copy and wakeup done");
+}
+#endif
+
+static int gps_each_device_open(struct inode *inode, struct file *filp)
+{
+ struct gps_each_device *dev; /* device information */
+ int retval;
+
+ dev = container_of(inode->i_cdev, struct gps_each_device, cdev);
+ filp->private_data = dev; /* for other methods */
+
+ GDL_LOGXW(dev->index, "major = %d, minor = %d, pid = %d",
+ imajor(inode), iminor(inode), current->pid);
+
+ if (!dev->is_open) {
+ retval = gps_each_link_open((enum gps_dl_link_id_enum)dev->index);
+
+ if (0 == retval) {
+ dev->is_open = true;
+ gps_each_link_rec_reset(dev->index);
+ } else
+ return retval;
+ }
+
+ return 0;
+}
+
+static int gps_each_device_hw_resume(enum gps_dl_link_id_enum link_id)
+{
+ int pid;
+ int retval;
+
+ pid = current->pid;
+ GDL_LOGXW(link_id, "pid = %d", pid);
+
+ retval = gps_each_link_hw_resume(link_id);
+
+ /* device read may arrive before resume, not reset the recording here
+ * gps_each_link_rec_reset(link_id);
+ */
+
+ return retval;
+}
+
+static int gps_each_device_release(struct inode *inode, struct file *filp)
+{
+ struct gps_each_device *dev;
+
+ dev = (struct gps_each_device *)filp->private_data;
+ dev->is_open = false;
+
+ GDL_LOGXW(dev->index, "major = %d, minor = %d, pid = %d",
+ imajor(inode), iminor(inode), current->pid);
+
+ gps_each_link_close((enum gps_dl_link_id_enum)dev->index);
+ gps_each_link_rec_force_dump(dev->index);
+
+ return 0;
+}
+
+static int gps_each_device_hw_suspend(enum gps_dl_link_id_enum link_id, bool need_clk_ext)
+{
+ int pid;
+ int retval;
+
+ pid = current->pid;
+ GDL_LOGXW(link_id, "pid = %d, clk_ext = %d", pid, need_clk_ext);
+
+ retval = gps_each_link_hw_suspend(link_id, need_clk_ext);
+ gps_each_link_rec_force_dump(link_id);
+
+ return retval;
+}
+
+#define GPSDL_IOC_GPS_HWVER 6
+#define GPSDL_IOC_GPS_IC_HW_VERSION 7
+#define GPSDL_IOC_GPS_IC_FW_VERSION 8
+#define GPSDL_IOC_D1_EFUSE_GET 9
+#define GPSDL_IOC_RTC_FLAG 10
+#define GPSDL_IOC_CO_CLOCK_FLAG 11
+#define GPSDL_IOC_TRIGGER_ASSERT 12
+#define GPSDL_IOC_QUERY_STATUS 13
+#define GPSDL_IOC_TAKE_GPS_WAKELOCK 14
+#define GPSDL_IOC_GIVE_GPS_WAKELOCK 15
+#define GPSDL_IOC_GET_GPS_LNA_PIN 16
+#define GPSDL_IOC_GPS_FWCTL 17
+#define GPSDL_IOC_GPS_HW_SUSPEND 18
+#define GPSDL_IOC_GPS_HW_RESUME 19
+#define GPSDL_IOC_GPS_LISTEN_RST_EVT 20
+#define GPSDL_IOC_GPS_READ_PMIC_REG 22
+
+static int gps_each_device_ioctl_inner(struct file *filp, unsigned int cmd, unsigned long arg, bool is_compat)
+{
+ struct gps_each_device *dev; /* device information */
+ int retval = -EFAULT;
+ unsigned int pmic_reg_val = 0;
+
+#if 0
+ dev = container_of(inode->i_cdev, struct gps_each_device, cdev);
+ filp->private_data = dev; /* for other methods */
+#endif
+ dev = (struct gps_each_device *)(filp->private_data);
+
+ GDL_LOGXD(dev->index, "cmd = %d, is_compat = %d", cmd, is_compat);
+#if 0
+ int retval = 0;
+ ENUM_WMTHWVER_TYPE_T hw_ver_sym = WMTHWVER_INVALID;
+ UINT32 hw_version = 0;
+ UINT32 fw_version = 0;
+ UINT32 gps_lna_pin = 0;
+#endif
+ switch (cmd) {
+ case GPSDL_IOC_TRIGGER_ASSERT:
+ /* Trigger FW assert for debug */
+ GDL_LOGXW_DRW(dev->index, "GPSDL_IOC_TRIGGER_ASSERT, reason = %ld", arg);
+
+ /* TODO: assert dev->is_open */
+ if (dev->index == GPS_DATA_LINK_ID0)
+ retval = gps_dl_trigger_gps_subsys_reset(false);
+ else
+ retval = gps_each_link_reset(dev->index);
+ break;
+ case GPSDL_IOC_QUERY_STATUS:
+ retval = gps_each_link_check(dev->index, arg);
+ gps_each_link_rec_force_dump(dev->index);
+ GDL_LOGXW_DRW(dev->index, "GPSDL_IOC_QUERY_STATUS, reason = %ld, ret = %d", arg, retval);
+ break;
+ case GPSDL_IOC_CO_CLOCK_FLAG:
+ retval = gps_dl_link_get_clock_flag();
+ GDL_LOGXD_ONF(dev->index, "gps clock flag = 0x%x", retval);
+ break;
+#if 0
+ case GPSDL_IOC_GPS_HWVER:
+ /*get combo hw version */
+ /* hw_ver_sym = mtk_wcn_wmt_hwver_get(); */
+
+ GPS_DBG_FUNC("GPS_ioctl(): get hw version = %d, sizeof(hw_ver_sym) = %zd\n",
+ hw_ver_sym, sizeof(hw_ver_sym));
+ if (copy_to_user((int __user *)arg, &hw_ver_sym, sizeof(hw_ver_sym)))
+ retval = -EFAULT;
+
+ break;
+ case GPSDL_IOC_GPS_IC_HW_VERSION:
+ /*get combo hw version from ic, without wmt mapping */
+ hw_version = mtk_wcn_wmt_ic_info_get(WMTCHIN_HWVER);
+
+ GPS_DBG_FUNC("GPS_ioctl(): get hw version = 0x%x\n", hw_version);
+ if (copy_to_user((int __user *)arg, &hw_version, sizeof(hw_version)))
+ retval = -EFAULT;
+
+ break;
+
+ case GPSDL_IOC_GPS_IC_FW_VERSION:
+ /*get combo fw version from ic, without wmt mapping */
+ fw_version = mtk_wcn_wmt_ic_info_get(WMTCHIN_FWVER);
+
+ GPS_DBG_FUNC("GPS_ioctl(): get fw version = 0x%x\n", fw_version);
+ if (copy_to_user((int __user *)arg, &fw_version, sizeof(fw_version)))
+ retval = -EFAULT;
+
+ break;
+ case GPSDL_IOC_RTC_FLAG:
+
+ retval = rtc_GPS_low_power_detected();
+
+ GPS_DBG_FUNC("low power flag (%d)\n", retval);
+ break;
+ case GPSDL_IOC_CO_CLOCK_FLAG:
+#if SOC_CO_CLOCK_FLAG
+ retval = mtk_wcn_wmt_co_clock_flag_get();
+#endif
+ GPS_DBG_FUNC("GPS co_clock_flag (%d)\n", retval);
+ break;
+ case GPSDL_IOC_D1_EFUSE_GET:
+#if defined(CONFIG_MACH_MT6735)
+ do {
+ char *addr = ioremap(0x10206198, 0x4);
+
+ retval = *(unsigned int *)addr;
+ GPS_DBG_FUNC("D1 efuse (0x%x)\n", retval);
+ iounmap(addr);
+ } while (0);
+#elif defined(CONFIG_MACH_MT6763)
+ do {
+ char *addr = ioremap(0x11f10048, 0x4);
+
+ retval = *(unsigned int *)addr;
+ GPS_DBG_FUNC("MT6763 efuse (0x%x)\n", retval);
+ iounmap(addr);
+ } while (0);
+#else
+ GPS_ERR_FUNC("Read Efuse not supported in this platform\n");
+#endif
+ break;
+
+ case GPSDL_IOC_TAKE_GPS_WAKELOCK:
+ GPS_INFO_FUNC("Ioctl to take gps wakelock\n");
+ gps_hold_wake_lock(1);
+ if (wake_lock_acquired == 1)
+ retval = 0;
+ else
+ retval = -EAGAIN;
+ break;
+ case GPSDL_IOC_GIVE_GPS_WAKELOCK:
+ GPS_INFO_FUNC("Ioctl to give gps wakelock\n");
+ gps_hold_wake_lock(0);
+ if (wake_lock_acquired == 0)
+ retval = 0;
+ else
+ retval = -EAGAIN;
+ break;
+#ifdef GPS_FWCTL_SUPPORT
+ case GPSDL_IOC_GPS_FWCTL:
+ GPS_INFO_FUNC("GPSDL_IOC_GPS_FWCTL\n");
+ retval = GPS_fwctl((struct gps_fwctl_data *)arg);
+ break;
+#endif
+ case GPSDL_IOC_GET_GPS_LNA_PIN:
+ gps_lna_pin = mtk_wmt_get_gps_lna_pin_num();
+ GPS_DBG_FUNC("GPS_ioctl(): get gps lna pin = %d\n", gps_lna_pin);
+ if (copy_to_user((int __user *)arg, &gps_lna_pin, sizeof(gps_lna_pin)))
+ retval = -EFAULT;
+ break;
+#endif
+ case GPSDL_IOC_GPS_HW_SUSPEND:
+ /* arg == 1 stand for need clk extension, otherwise is normal deep sotp mode */
+ retval = gps_each_device_hw_suspend(dev->index, (arg == 1));
+ GDL_LOGXI_ONF(dev->index,
+ "GPSDL_IOC_GPS_HW_SUSPEND: arg = %ld, ret = %d", arg, retval);
+ break;
+ case GPSDL_IOC_GPS_HW_RESUME:
+ retval = gps_each_device_hw_resume(dev->index);
+ GDL_LOGXI_ONF(dev->index,
+ "GPSDL_IOC_GPS_HW_RESUME: arg = %ld, ret = %d", arg, retval);
+ break;
+ case GPSDL_IOC_GPS_LISTEN_RST_EVT:
+ retval = -EINVAL;
+ GDL_LOGXI_ONF(dev->index,
+ "GPSDL_IOC_GPS_LISTEN_RST_EVT retval = %d", retval);
+ break;
+
+ case GPSDL_IOC_GPS_READ_PMIC_REG:
+
+ /*to be confirm 1. IOCTL CMD ID, 2. PMIC REG addr*/
+
+ if (true == gps_dl_read_pmic_efuse_reg((unsigned int)arg, &pmic_reg_val))
+ retval = (int)pmic_reg_val;
+ else
+ retval = -EFAULT;
+ break;
+
+ case 21505:
+ case 21506:
+ case 21515:
+ /* known unsupported cmd */
+ retval = -EFAULT;
+ GDL_LOGXD_DRW(dev->index, "cmd = %d, not support", cmd);
+ break;
+ default:
+ retval = -EFAULT;
+ GDL_LOGXI_DRW(dev->index, "cmd = %d, not support", cmd);
+ break;
+ }
+
+ return retval;
+}
+
+
+static long gps_each_device_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ return gps_each_device_ioctl_inner(filp, cmd, arg, false);
+}
+
+static long gps_each_device_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ return gps_each_device_ioctl_inner(filp, cmd, arg, true);
+}
+
+static const struct file_operations gps_each_device_fops = {
+ .owner = THIS_MODULE,
+ .open = gps_each_device_open,
+ .read = gps_each_device_read,
+ .write = gps_each_device_write,
+ .release = gps_each_device_release,
+ .unlocked_ioctl = gps_each_device_unlocked_ioctl,
+ .compat_ioctl = gps_each_device_compat_ioctl,
+};
+
+int gps_dl_cdev_setup(struct gps_each_device *dev, int index)
+{
+ int result;
+
+ init_waitqueue_head(&dev->r_wq);
+ dev->i_len = 0;
+
+ dev->index = index;
+ /* assert dev->index == dev->cfg.index */
+
+ cdev_init(&dev->cdev, &gps_each_device_fops);
+ dev->cdev.owner = THIS_MODULE;
+ dev->cdev.ops = &gps_each_device_fops;
+
+ result = cdev_add(&dev->cdev, dev->devno, 1);
+ if (result) {
+ GDL_LOGE("cdev_add error %d on index %d", result, index);
+ return result;
+ }
+
+ dev->cls = class_create(THIS_MODULE, dev->cfg.dev_name);
+ if (IS_ERR(dev->cls)) {
+ GDL_LOGE("class_create fail on %s", dev->cfg.dev_name);
+ return -1;
+ }
+
+ dev->dev = device_create(dev->cls, NULL, dev->devno, NULL, dev->cfg.dev_name);
+ if (IS_ERR(dev->dev)) {
+ GDL_LOGE("device_create fail on %s", dev->cfg.dev_name);
+ return -1;
+ }
+
+ return 0;
+}
+
+void gps_dl_cdev_cleanup(struct gps_each_device *dev, int index)
+{
+ if (dev->dev) {
+ device_destroy(dev->cls, dev->devno);
+ dev->dev = NULL;
+ }
+
+ if (dev->cls) {
+ class_destroy(dev->cls);
+ dev->cls = NULL;
+ }
+
+ cdev_del(&dev->cdev);
+}
+#ifdef GPS_DL_HAS_PLAT_DRV
+static struct regulator *__gps_dl_get_vcore_power(void)
+{
+ struct regulator *dvfsrc_vcore_power = NULL;
+ struct gps_each_device *p_each_dev;
+ struct device *dev;
+ int vcore_uV = 600000;
+ int ret = 0;
+
+ p_each_dev = gps_dl_device_get(GPS_DATA_LINK_ID0);
+ if (!p_each_dev) {
+ GDL_LOGE_INI("GPS gps_dl_device_get fail\n");
+ return NULL;
+ }
+
+ dev = (struct device *)(p_each_dev->private_data);
+ if (!dev) {
+ GDL_LOGE_INI("GPS get dev fail\n");
+ return NULL;
+ }
+
+ dvfsrc_vcore_power = regulator_get(dev, "mtk-vcore");
+ if (!dvfsrc_vcore_power)
+ GDL_LOGE_INI("regulator_get fail");
+ else {
+ ret = regulator_set_voltage(dvfsrc_vcore_power, vcore_uV, INT_MAX);
+ if (ret < 0)
+ GDL_LOGE_INI("regulator_set_voltage fail");
+ }
+
+ return dvfsrc_vcore_power;
+}
+
+int gps_dl_get_vcore_power(void)
+{
+
+ struct regulator *dvfsrc_vcore_power = NULL;
+ unsigned int flag = 0;
+ struct gps_dl_vcore_context *p_gps_dl_vcore_context = NULL;
+
+ p_gps_dl_vcore_context = &g_gps_dl_vcore_context;
+ flag = p_gps_dl_vcore_context->flag;
+
+ GDL_LOGE_INI("gps_dl_get_vcore_power, flag = %x\n", flag);
+ if (GPS_DL_VCORE_HOLD_ON(flag))
+ return GPS_DL_VCORE_REQUIRE_SUCCESS;
+ if (GPS_DL_VCORE_CAN_NOT_REQUIRE(flag))
+ return GPS_DL_VCORE_REQUIRE_FORBIDDEN;
+
+ dvfsrc_vcore_power = __gps_dl_get_vcore_power();
+ if (dvfsrc_vcore_power == NULL)
+ return GPS_DL_VCORE_REQUIRE_FAIL;
+ p_gps_dl_vcore_context->p_regulator = dvfsrc_vcore_power;
+ p_gps_dl_vcore_context->flag |= GPS_DL_VCORE_STATUS_SETED;
+
+ return GPS_DL_VCORE_REQUIRE_SUCCESS;
+}
+
+int gps_dl_put_vcore_power(int forced)
+{
+
+ unsigned int flag = 0;
+ struct gps_dl_vcore_context *p_gps_dl_vcore_context = NULL;
+
+ p_gps_dl_vcore_context = &g_gps_dl_vcore_context;
+ flag = p_gps_dl_vcore_context->flag;
+
+ GDL_LOGE_INI("gps_dl_put_vcore_power, flag = %x, forced = %d\n", flag, forced);
+
+ if (!GPS_DL_VCORE_HOLD_ON(flag))
+ return GPS_DL_VCORE_RELEASE_SUCCESS;
+ if (GPS_DL_VCORE_CAN_NOT_RELEASE(flag, forced))
+ return GPS_DL_VCORE_RELEASE_FORBIDDEN;
+
+ if (!p_gps_dl_vcore_context->p_regulator)
+ return GPS_DL_VCORE_RELEASE_FAIL;
+
+ regulator_put(p_gps_dl_vcore_context->p_regulator);
+ p_gps_dl_vcore_context->p_regulator = NULL;
+ p_gps_dl_vcore_context->flag &= (~GPS_DL_VCORE_STATUS_SETED);
+ return GPS_DL_VCORE_RELEASE_SUCCESS;
+}
+
+#else
+int gps_dl_get_vcore_power(void)
+{
+ return 0;
+}
+
+int gps_dl_put_vcore_power(int forced)
+{
+ return 0;
+}
+#endif
+void gps_dl_set_vcore_flag(unsigned int *flag, enum gps_dl_procfs_vcore_enum action)
+{
+
+ switch (action) {
+ case GPS_PROC_VCORE_REQUIRE_NONE:
+ break;
+ case GPS_PROC_VCORE_REQUIRE_ON:
+ *flag &= GPS_DL_VCORE_PROCFS_MASK;
+ *flag |= GPS_DL_VCORE_ALWAYS_ON;
+ break;
+ case GPS_PROC_VCORE_REQUIRE_OFF:
+ *flag &= GPS_DL_VCORE_PROCFS_MASK;
+ *flag |= GPS_DL_VCORE_ALWAYS_OFF;
+ break;
+ default:
+ break;
+ }
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_data_link_devices.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_data_link_devices.h
new file mode 100644
index 0000000..d23e0eb
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_data_link_devices.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DATA_LINK_DEVICES_H
+#define _GPS_DATA_LINK_DEVICES_H
+
+#include "gps_dl_config.h"
+
+int mtk_gps_data_link_devices_init(void);
+void mtk_gps_data_link_devices_exit(void);
+
+#endif /* _GPS_DATA_LINK_DEVICES_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_ctrld.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_ctrld.h
new file mode 100644
index 0000000..6f95e8f
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_ctrld.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_CTRLD_H
+#define _GPS_DL_CTRLD_H
+#include "gps_dl_osal.h"
+#include "gps_dl_config.h"
+
+#define GPS_DL_OP_BUF_SIZE (16)
+
+enum gps_dl_ctrld_opid {
+ GPS_DL_OPID_LINK_EVENT_PROC,
+ GPS_DL_OPID_HAL_EVENT_PROC,
+ GPS_DL_OPID_MAX
+};
+
+struct gps_dl_ctrld_context {
+ struct gps_dl_osal_event rgpsdlWq; /* rename */
+ struct gps_dl_osal_lxop_q rOpQ; /* active op queue */
+ struct gps_dl_osal_lxop_q rFreeOpQ; /* free op queue */
+ struct gps_dl_osal_lxop arQue[GPS_DL_OP_BUF_SIZE]; /* real op instances */
+ struct gps_dl_osal_thread thread;
+};
+
+typedef int(*GPS_DL_OPID_FUNC) (struct gps_dl_osal_op_dat *);
+
+unsigned int gps_dl_wait_event_checker(struct gps_dl_osal_thread *pThread);
+int gps_dl_put_act_op(struct gps_dl_osal_lxop *pOp);
+struct gps_dl_osal_lxop *gps_dl_get_free_op(void);
+int gps_dl_put_op_to_free_queue(struct gps_dl_osal_lxop *pOp);
+int gps_dl_ctrld_init(void);
+int gps_dl_ctrld_deinit(void);
+
+#endif /* _GPS_DL_CTRLD_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_emi.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_emi.h
new file mode 100644
index 0000000..0ff6f65
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_emi.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef _GPS_GPS_DL_EMI_H
+#define _GPS_GPS_DL_EMI_H
+
+#include "gps_dl_config.h"
+
+#if GPS_DL_HAS_PLAT_DRV
+#define GPS_ICAP_BUF_SIZE 0x50000 /* 320KB */
+
+void gps_icap_probe(void);
+#endif
+
+#endif /* _GPS_GPS_DL_EMI_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_linux.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_linux.h
new file mode 100644
index 0000000..8a1948b
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_linux.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_LINUX_H
+#define _GPS_DL_LINUX_H
+
+#include "gps_dl_config.h"
+
+#include <linux/io.h>
+#include <linux/interrupt.h>
+
+#if (GPS_DL_USE_MTK_SYNC_WRITE)
+#include <sync_write.h>
+#define gps_dl_linux_sync_writel(v, a) mt_reg_sync_writel(v, a)
+#else
+/* Add mb after writel to make sure it takes effect before next operation */
+#define gps_dl_mb() mb()
+#define gps_dl_linux_sync_writel(v, a) \
+ do { \
+ writel((v), (void __force __iomem *)((a))); \
+ gps_dl_mb(); \
+ } while (0)
+#endif
+
+#include "gps_dl_isr.h"
+#include "gps_each_link.h"
+
+/* put linux proprietary items here otherwise put into gps_dl_osal.h */
+irqreturn_t gps_dl_linux_irq_dispatcher(int irq, void *data);
+int gps_dl_linux_irqs_register(struct gps_each_irq *p_irqs, int irq_num);
+int gps_dl_linux_irqs_unregister(struct gps_each_irq *p_irqs, int irq_num);
+
+#endif /* _GPS_DL_LINUX_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_linux_plat_drv.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_linux_plat_drv.h
new file mode 100644
index 0000000..3574040
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_linux_plat_drv.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_LINUX_PLAT_DRV_H
+#define _GPS_DL_LINUX_PLAT_DRV_H
+
+#include <linux/regulator/consumer.h>
+#include "gps_dl_config.h"
+
+#if GPS_DL_HAS_PLAT_DRV
+#include <linux/io.h>
+struct gps_dl_iomem_addr_map_entry {
+ void __iomem *host_virt_addr;
+ unsigned int host_phys_addr;
+ unsigned int length;
+};
+#endif
+
+
+#define GPS_DL_VCORE_ALWAYS_ON (0x1<<0)
+#define GPS_DL_VCORE_ALWAYS_OFF (0x1<<1)
+#define GPS_DL_VCORE_STATUS_SETED (0x1<<2)
+#define GPS_DL_VCORE_PROCFS_MASK (~(GPS_DL_VCORE_ALWAYS_ON|GPS_DL_VCORE_ALWAYS_OFF))
+
+#define GPS_DL_VCORE_HOLD_ON(flag) ((flag) & GPS_DL_VCORE_STATUS_SETED)
+#define GPS_DL_VCORE_CAN_NOT_RELEASE(flag, forced) \
+ (((flag) & GPS_DL_VCORE_ALWAYS_ON) && !(forced))
+#define GPS_DL_VCORE_CAN_NOT_REQUIRE(flag) ((flag) & GPS_DL_VCORE_ALWAYS_OFF)
+
+#define GPS_DL_VCORE_REQUIRE_SUCCESS (0)
+#define GPS_DL_VCORE_REQUIRE_FORBIDDEN (-1)
+#define GPS_DL_VCORE_REQUIRE_FAIL (-2)
+
+#define GPS_DL_VCORE_RELEASE_SUCCESS (0)
+#define GPS_DL_VCORE_RELEASE_FORBIDDEN (-1)
+#define GPS_DL_VCORE_RELEASE_FAIL (-2)
+
+
+struct gps_dl_vcore_context {
+ struct regulator *p_regulator;
+ unsigned int flag;
+};
+
+#if GPS_DL_HAS_PLAT_DRV
+bool gps_dl_read_pmic_efuse_reg(unsigned int reg, unsigned int *val);
+int gps_dl_linux_plat_drv_register(void);
+int gps_dl_linux_plat_drv_unregister(void);
+void __iomem *gps_dl_host_addr_to_virt(unsigned int host_addr);
+void gps_dl_update_status_for_md_blanking(bool gps_is_on);
+void gps_dl_tia_gps_ctrl(bool gps_is_on);
+void gps_dl_lna_pin_ctrl(enum gps_dl_link_id_enum link_id, bool dsp_is_on, bool force_en);
+void gps_dl_reserved_mem_show_info(void);
+void gps_dl_wake_lock_init(void);
+void gps_dl_wake_lock_deinit(void);
+void gps_dl_wake_lock_hold(bool hold);
+
+
+extern struct gps_dl_vcore_context g_gps_dl_vcore_context;
+extern enum gps_dl_procfs_vcore_enum gps_dl_procfs_vcore_action;
+#endif
+
+#endif /* _GPS_DL_LINUX_PLAT_DRV_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_linux_reserved_mem.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_linux_reserved_mem.h
new file mode 100644
index 0000000..b1e6ec8
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_linux_reserved_mem.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef _GPS_DL_LINUX_RESERVED_MEM_H
+#define _GPS_DL_LINUX_RESERVED_MEM_H
+
+#include "gps_dl_config.h"
+
+#ifdef GPS_DL_HAS_PLAT_DRV
+#include "gps_dl_dma_buf.h"
+
+extern phys_addr_t gGpsRsvMemPhyBase;
+extern unsigned long long gGpsRsvMemSize;
+
+void gps_dl_reserved_mem_init(void);
+void gps_dl_reserved_mem_deinit(void);
+bool gps_dl_reserved_mem_is_ready(void);
+void gps_dl_reserved_mem_get_range(unsigned int *p_min, unsigned int *p_max);
+void gps_dl_reserved_mem_show_info(void);
+
+void gps_dl_reserved_mem_dma_buf_init(struct gps_dl_dma_buf *p_dma_buf,
+ enum gps_dl_link_id_enum link_id, enum gps_dl_dma_dir dir, unsigned int len);
+void gps_dl_reserved_mem_dma_buf_deinit(struct gps_dl_dma_buf *p_dma_buf);
+void *gps_dl_reserved_mem_icap_buf_get_vir_addr(void);
+#endif
+
+#endif /* _GPS_DL_LINUX_RESERVED_MEM_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_osal.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_osal.h
new file mode 100644
index 0000000..72beb97
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_osal.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_OSAL_H
+#define _GPS_DL_OSAL_H
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <asm/current.h>
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/workqueue.h>
+#include <linux/wait.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+#include <linux/kthread.h>
+#include <linux/jiffies.h>
+#include <linux/slab.h>
+#include <linux/kfifo.h>
+#include <linux/device.h>
+#include <linux/pm_wakeup.h>
+#include <linux/log2.h>
+#include <linux/atomic.h>
+#include <linux/ratelimit.h>
+
+#define DBG_LOG_STR_SIZE 256
+
+#define RB_LATEST(prb) ((prb)->write - 1)
+#define RB_SIZE(prb) ((prb)->size)
+#define RB_MASK(prb) (RB_SIZE(prb) - 1)
+#define RB_COUNT(prb) ((prb)->write - (prb)->read)
+#define RB_FULL(prb) (RB_COUNT(prb) >= RB_SIZE(prb))
+#define RB_EMPTY(prb) ((prb)->write == (prb)->read)
+
+#define RB_INIT(prb, qsize) \
+do { \
+ (prb)->read = (prb)->write = 0; \
+ (prb)->size = (qsize); \
+} while (0)
+
+#define RB_PUT(prb, value) \
+do { \
+ if (!RB_FULL(prb)) { \
+ (prb)->queue[(prb)->write & RB_MASK(prb)] = value; \
+ ++((prb)->write); \
+ } \
+ else { \
+ gps_dl_osal_assert(!RB_FULL(prb)); \
+ } \
+} while (0)
+
+#define RB_GET(prb, value) \
+do { \
+ if (!RB_EMPTY(prb)) { \
+ value = (prb)->queue[(prb)->read & RB_MASK(prb)]; \
+ ++((prb)->read); \
+ if (RB_EMPTY(prb)) { \
+ (prb)->read = (prb)->write = 0; \
+ } \
+ } \
+ else { \
+ value = NULL; \
+ gps_dl_osal_assert(!RB_EMPTY(prb)); \
+ } \
+} while (0)
+
+#define RB_GET_LATEST(prb, value) \
+do { \
+ if (!RB_EMPTY(prb)) { \
+ value = (prb)->queue[RB_LATEST(prb) & RB_MASK(prb)]; \
+ if (RB_EMPTY(prb)) { \
+ (prb)->read = (prb)->write = 0; \
+ } \
+ } \
+ else { \
+ value = NULL; \
+ } \
+} while (0)
+
+#define MAX_THREAD_NAME_LEN 128
+#define OSAL_OP_DATA_SIZE 32
+#define OSAL_OP_BUF_SIZE 16
+
+typedef void(*P_TIMEOUT_HANDLER) (unsigned long);
+typedef int(*P_COND) (void *);
+
+struct gps_dl_osal_timer {
+ struct timer_list timer;
+ P_TIMEOUT_HANDLER timeoutHandler;
+ unsigned long timeroutHandlerData;
+};
+
+struct gps_dl_osal_unsleepable_lock {
+ spinlock_t lock;
+ unsigned long flag;
+};
+
+struct gps_dl_osal_sleepable_lock {
+ struct mutex lock;
+};
+
+struct gps_dl_osal_signal {
+ struct completion comp;
+ unsigned int timeoutValue;
+ unsigned int timeoutExtension; /* max number of timeout caused by thread not able to acquire CPU */
+};
+
+struct gps_dl_osal_event {
+ wait_queue_head_t waitQueue;
+ unsigned int timeoutValue;
+ int waitFlag;
+};
+
+struct gps_dl_osal_op_dat {
+ unsigned int opId; /* Event ID */
+ unsigned int u4InfoBit; /* Reserved */
+ unsigned long au4OpData[OSAL_OP_DATA_SIZE]; /* OP Data */
+};
+
+struct gps_dl_osal_lxop {
+ struct gps_dl_osal_op_dat op;
+ struct gps_dl_osal_signal signal;
+ int result;
+ atomic_t ref_count;
+};
+
+struct gps_dl_osal_lxop_q {
+ struct gps_dl_osal_sleepable_lock sLock;
+ unsigned int write;
+ unsigned int read;
+ unsigned int size;
+ struct gps_dl_osal_lxop *queue[OSAL_OP_BUF_SIZE];
+};
+
+struct gps_dl_osal_thread {
+ struct task_struct *pThread;
+ void *pThreadFunc;
+ void *pThreadData;
+ char threadName[MAX_THREAD_NAME_LEN];
+};
+
+typedef unsigned int(*OSAL_EVENT_CHECKER) (struct gps_dl_osal_thread *pThread);
+
+char *gps_dl_osal_strncpy(char *dst, const char *src, unsigned int len);
+char *gps_dl_osal_strsep(char **str, const char *c);
+int gps_dl_osal_strtol(const char *str, unsigned int adecimal, long *res);
+void *gps_dl_osal_memset(void *buf, int i, unsigned int len);
+int gps_dl_osal_thread_create(struct gps_dl_osal_thread *pThread);
+int gps_dl_osal_thread_run(struct gps_dl_osal_thread *pThread);
+int gps_dl_osal_thread_stop(struct gps_dl_osal_thread *pThread);
+int gps_dl_osal_thread_should_stop(struct gps_dl_osal_thread *pThread);
+int gps_dl_osal_thread_destroy(struct gps_dl_osal_thread *pThread);
+int gps_dl_osal_thread_wait_for_event(struct gps_dl_osal_thread *pThread,
+ struct gps_dl_osal_event *pEvent, OSAL_EVENT_CHECKER pChecker);
+int gps_dl_osal_signal_init(struct gps_dl_osal_signal *pSignal);
+int gps_dl_osal_wait_for_signal(struct gps_dl_osal_signal *pSignal);
+int gps_dl_osal_wait_for_signal_timeout(struct gps_dl_osal_signal *pSignal, struct gps_dl_osal_thread *pThread);
+int gps_dl_osal_raise_signal(struct gps_dl_osal_signal *pSignal);
+int gps_dl_osal_signal_active_state(struct gps_dl_osal_signal *pSignal);
+int gps_dl_osal_op_is_wait_for_signal(struct gps_dl_osal_lxop *pOp);
+void gps_dl_osal_op_raise_signal(struct gps_dl_osal_lxop *pOp, int result);
+int gps_dl_osal_signal_deinit(struct gps_dl_osal_signal *pSignal);
+int gps_dl_osal_event_init(struct gps_dl_osal_event *pEvent);
+int gps_dl_osal_trigger_event(struct gps_dl_osal_event *pEvent);
+int gps_dl_osal_wait_for_event(struct gps_dl_osal_event *pEvent, int (*condition)(void *), void *cond_pa);
+int gps_dl_osal_wait_for_event_timeout(struct gps_dl_osal_event *pEvent, int (*condition)(void *), void *cond_pa);
+int gps_dl_osal_event_deinit(struct gps_dl_osal_event *pEvent);
+int gps_dl_osal_sleepable_lock_init(struct gps_dl_osal_sleepable_lock *pSL);
+int gps_dl_osal_lock_sleepable_lock(struct gps_dl_osal_sleepable_lock *pSL);
+int gps_dl_osal_unlock_sleepable_lock(struct gps_dl_osal_sleepable_lock *pSL);
+int gps_dl_osal_trylock_sleepable_lock(struct gps_dl_osal_sleepable_lock *pSL);
+int gps_dl_osal_sleepable_lock_deinit(struct gps_dl_osal_sleepable_lock *pSL);
+int gps_dl_osal_unsleepable_lock_init(struct gps_dl_osal_unsleepable_lock *pUSL);
+int gps_dl_osal_lock_unsleepable_lock(struct gps_dl_osal_unsleepable_lock *pUSL);
+int gps_dl_osal_unlock_unsleepable_lock(struct gps_dl_osal_unsleepable_lock *pUSL);
+
+#define gps_dl_osal_assert(condition) \
+do { \
+ if (!(condition)) { \
+ GDL_LOGE("ASSERT: (%s)", #condition); \
+ } \
+} while (0)
+
+#endif /* _GPS_DL_OSAL_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_procfs.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_procfs.h
new file mode 100644
index 0000000..479172e
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_dl_procfs.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_DL_PROCFS_H
+#define _GPS_DL_PROCFS_H
+
+int gps_dl_procfs_setup(void);
+int gps_dl_procfs_remove(void);
+
+typedef int(*gps_dl_procfs_test_func_type)(int y, int z);
+extern enum gps_dl_procfs_vcore_enum gps_dl_procfs_vcore_action;
+
+
+#endif /* _GPS_DL_PROCFS_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_each_device.h b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_each_device.h
new file mode 100644
index 0000000..a2e6655
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/data_link/linux/inc/gps_each_device.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#ifndef _GPS_EACH_DEVICE_H
+#define _GPS_EACH_DEVICE_H
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/cdev.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/printk.h>
+#include <linux/version.h>
+#include <asm/memblock.h>
+#include <linux/wait.h>
+
+#include "gps_each_link.h"
+#include "gps_dl_dma_buf.h"
+
+#define GPS_DATA_PATH_BUF_MAX 2048
+
+/* Todo: should not use this const, currently it's a work-around */
+#define GPS_LIBMNL_READ_MAX 512
+
+struct gps_each_device_cfg {
+ char *dev_name;
+ int index;
+};
+
+struct gps_each_device {
+ struct gps_each_device_cfg cfg;
+ struct gps_each_link *p_link;
+ int index;
+ dev_t devno;
+ struct class *cls;
+ struct device *dev;
+ struct cdev cdev;
+ bool is_open;
+ unsigned char i_buf[GPS_DATA_PATH_BUF_MAX];
+ unsigned char o_buf[GPS_DATA_PATH_BUF_MAX];
+ unsigned int i_len;
+ wait_queue_head_t r_wq;
+ void *private_data;
+};
+
+enum gps_dl_procfs_vcore_enum {
+ GPS_PROC_VCORE_REQUIRE_NONE = 0,
+ GPS_PROC_VCORE_REQUIRE_ON = 1,
+ GPS_PROC_VCORE_REQUIRE_OFF = 2,
+};
+
+int gps_dl_cdev_setup(struct gps_each_device *dev, int index);
+void gps_dl_cdev_cleanup(struct gps_each_device *dev, int index);
+struct gps_each_device *gps_dl_device_get(enum gps_dl_link_id_enum link_id);
+
+void gps_each_device_data_submit(unsigned char *buf, unsigned int len, int index);
+
+void gps_dl_device_context_init(void);
+void gps_dl_device_context_deinit(void);
+int gps_dl_get_vcore_power(void);
+int gps_dl_put_vcore_power(int forced);
+void gps_dl_set_vcore_flag(unsigned int *flag, enum gps_dl_procfs_vcore_enum action);
+
+#endif /* _GPS_EACH_DEVICE_H */
+
diff --git a/src/kernel/modules/connectivity/2.0/gps_driver/gps_dl_module.c b/src/kernel/modules/connectivity/2.0/gps_driver/gps_dl_module.c
new file mode 100644
index 0000000..df5152d
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/gps_driver/gps_dl_module.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include "gps_dl_config.h"
+
+#if GPS_DL_IS_MODULE
+#include "gps_data_link_devices.h"
+
+/*****************************************************************************/
+static int gps_dl_mod_init(void)
+{
+ int ret = 0;
+
+ mtk_gps_data_link_devices_init();
+
+ return ret;
+}
+
+/*****************************************************************************/
+static void gps_dl_mod_exit(void)
+{
+ mtk_gps_data_link_devices_exit();
+}
+
+#ifdef MTK_WCN_REMOVE_KERNEL_MODULE
+int mtk_wcn_gpsdl_drv_init(void)
+{
+ return gps_dl_mod_init();
+}
+EXPORT_SYMBOL(mtk_wcn_gpsdl_drv_init);
+
+void mtk_wcn_gpsdl_drv_exit(void)
+{
+ return gps_dl_mod_exit();
+}
+EXPORT_SYMBOL(mtk_wcn_gpsdl_drv_exit);
+
+#else
+module_init(gps_dl_mod_init);
+module_exit(gps_dl_mod_exit);
+
+#endif
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Hua Fu");
+#endif
+