[Feature] add GA346 baseline version
Change-Id: Ic62933698569507dcf98240cdf5d9931ae34348f
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/Android.mk b/src/kernel/modules/connectivity/2.0/conninfra_driver/Android.mk
new file mode 100755
index 0000000..6f3f05a
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/Android.mk
@@ -0,0 +1,24 @@
+LOCAL_PATH := $(call my-dir)
+
+ifneq ($(filter yes,$(sort $(MTK_WLAN_SUPPORT) $(MTK_BT_SUPPORT) $(MTK_GPS_SUPPORT) $(MTK_FM_SUPPORT))),)
+
+ifneq (true,$(strip $(TARGET_NO_KERNEL)))
+ifneq ($(filter yes,$(MTK_COMBO_SUPPORT)),)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := conninfra.ko
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+
+LOCAL_INIT_RC := init.conninfra.rc
+LOCAL_SRC_FILES := $(patsubst $(LOCAL_PATH)/%,%,$(shell find $(LOCAL_PATH) -type f -name '*.[cho]')) Makefile
+LOCAL_REQUIRED_MODULES :=
+
+include $(MTK_KERNEL_MODULE)
+
+else
+ $(warning wmt_drv-MTK_COMBO_SUPPORT: [$(MTK_COMBO_SUPPORT)])
+endif
+endif
+
+endif
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/Makefile b/src/kernel/modules/connectivity/2.0/conninfra_driver/Makefile
new file mode 100755
index 0000000..74d255c7
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/Makefile
@@ -0,0 +1,190 @@
+###############################################################################
+# Necessary Check
+
+#ifeq ($(AUTOCONF_H),)
+ #$(error AUTOCONF_H is not defined)
+#endif
+
+
+
+#ccflags-y += -imacros $(AUTOCONF_H)
+
+ifeq ($(CONFIG_MTK_COMBO_CHIP),)
+ $(error CONFIG_MTK_COMBO_CHIP not defined)
+endif
+
+$(info $$CONFIG_MTK_COMBO_CHIP is [${CONFIG_MTK_COMBO_CHIP}])
+
+
+# Force build fail on modpost warning
+KBUILD_MODPOST_FAIL_ON_WARNINGS := y
+###############################################################################
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/include
+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/include/mt-plat
+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/misc/mediatek/eccci
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/eccci/$(MTK_PLATFORM)
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/eemcs
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/mach/$(MTK_PLATFORM)/include/mach
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/submodule
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/emi/$(MTK_PLATFORM)
+ccflags-y += -I$(srctree)/drivers/mmc/core
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/connectivity/common
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/pmic/include/
+###############################################################################
+
+ccflags-y += -Werror
+ccflags-y += -Wno-error=format
+ccflags-y += -Wno-error=format-extra-args
+
+###############################################################################
+MODULE_NAME := conninfra
+ifeq ($(CONFIG_WLAN_DRV_BUILD_IN),y)
+$(warning $(MODULE_NAME) build-in boot.img)
+obj-y += $(MODULE_NAME).o
+else
+$(warning $(MODULE_NAME) is kernel module)
+obj-m += $(MODULE_NAME).o
+endif
+
+# Local config
+ccflags-y += -D MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE=1
+ccflags-y += -D CONFIG_CONNINFRA_UT_SUPPORT=1
+ccflags-y += -D CONFIG_CONNINFRA_DBG_SUPPORT=1
+ccflags-y += -D CONFIG_CONNINFRA_DEVAPC_SUPPORT=0
+ccflags-y += -D CONFIG_CONNINFRA_COREDUMP_SUPPORT=0
+ccflags-y += -D CONFIG_CONNINFRA_FW_LOG_SUPPORT=0
+ccflags-y += -D CONFIG_CONNINFRA_STEP_SUPPORT=0
+ccflags-y += -D CONFIG_CONNINFRA_POWER_STATUS_SUPPORT=1
+ccflags-y += -D CONFIG_CONNINFRA_BUS_HANG_DEBUG_SUPPORT=1
+ccflags-y += -D CONFIG_CONNINFRA_EMI_SUPPORT=0
+ccflags-y += -D CONFIG_CONNINFRA_PRE_CAL_BLOCKING=0
+ccflags-y += -D CONFIG_CONNINFRA_PRE_CAL_SUPPORT=0
+
+ifneq (,$(filter fpga%,$(SUBTARGET)))
+ccflags-y += -D CONFIG_CONNINFRA_PMIC_SUPPORT=0
+ccflags-y += -D CONFIG_CONNINFRA_THERMAL_SUPPORT=0
+else
+ccflags-y += -D CONFIG_CONNINFRA_PMIC_SUPPORT=1
+ccflags-y += -D CONFIG_CONNINFRA_THERMAL_SUPPORT=1
+endif
+
+$(patsubst CONFIG_%, -DCFG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \
+$(patsubst CONFIG_%, -DCFG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \
+$(patsubst CONFIG_%, -DCFG_%=0, $(patsubst %=n,%,$(filter %=n,$(EXTRA_KCONFIG)))) \
+
+
+# Local config
+EXTRA_KCONFIG:= \
+ CONFIG_CONNINFRA_UT_SUPPORT=y \
+ CONFIG_CONNINFRA_DBG_SUPPORT=y \
+ CONFIG_CONNINFRA_DEVAPC_SUPPORT=n \
+ CONFIG_CONNINFRA_COREDUMP_SUPPORT=n \
+ CONFIG_CONNINFRA_FW_LOG_SUPPORT=n \
+ CONFIG_CONNINFRA_STEP_SUPPORT=n \
+ CONFIG_CONNINFRA_POWER_STATUS_SUPPORT=y \
+ CONFIG_CONNINFRA_BUS_HANG_DEBUG_SUPPORT=y \
+ CONFIG_CONNINFRA_EMI_SUPPORT=n \
+ CONFIG_CONNINFRA_PRE_CAL_BLOCKING=n \
+ CONFIG_CONNINFRA_PRE_CAL_SUPPORT=n
+
+ifneq (,$(filter fpga%,$(SUBTARGET)))
+EXTRA_KCONFIG += \
+ CONFIG_CONNINFRA_PMIC_SUPPORT=n \
+ CONFIG_CONNINFRA_THERMAL_SUPPORT=n
+else
+EXTRA_KCONFIG += \
+ CONFIG_CONNINFRA_PMIC_SUPPORT=y \
+ CONFIG_CONNINFRA_THERMAL_SUPPORT=y
+endif
+
+# Transfer local kernel config to compile option
+EXTRA_CFLAGS:= \
+ $(patsubst CONFIG_%, -DCFG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \
+ $(patsubst CONFIG_%, -DCFG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \
+ $(patsubst CONFIG_%, -DCFG_%=0, $(patsubst %=n,%,$(filter %=n,$(EXTRA_KCONFIG)))) \
+
+$(info $$EXTRA_CFLAGS is [${EXTRA_CFLAGS}])
+
+###############################################################################
+# common_main
+###############################################################################
+ccflags-y += -I$(src)/include
+ccflags-y += -I$(src)/base/include
+ccflags-y += -I$(src)/core/include
+ccflags-y += -I$(src)/conf/include
+ccflags-y += -I$(src)/platform/include
+ccflags-y += -I$(src)/debug_utility
+ccflags-y += -I$(src)/debug_utility/include
+ccflags-y += -I$(src)/debug_utility/connsyslog
+ccflags-y += -I$(src)/debug_utility/connsyslog/platform/include
+ccflags-y += -I$(src)/debug_utility/coredump
+ccflags-y += -I$(src)/debug_utility/coredump/platform/include
+ccflags-y += -I$(src)/debug_utility/step/include
+ccflags-y += -I$(src)/test/include
+
+# By Plaftfrom
+ccflags-y += -I$(src)/platform/mt6880/include
+
+# Temp for FPGA
+ccflags-y += -D MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE=1
+
+# Temp for kernel config
+ifneq (,$(filter fpga%,$(SUBTARGET)))
+ccflags-y += -D CONFIG_FPGA_EARLY_PORTING
+endif
+
+ifneq ($(TARGET_BUILD_VARIANT), user)
+ ccflags-y += -D CONNINFRA_DBG_SUPPORT=1
+else
+ ccflags-y += -D CONNINFRA_DBG_SUPPORT=0
+endif
+
+$(MODULE_NAME)-objs += base/ring.o
+$(MODULE_NAME)-objs += base/osal.o
+$(MODULE_NAME)-objs += base/msg_thread.o
+$(MODULE_NAME)-objs += core/conninfra_core.o
+$(MODULE_NAME)-objs += src/conninfra_dev.o
+$(MODULE_NAME)-objs += src/conninfra.o
+$(MODULE_NAME)-objs += conf/conninfra_conf.o
+$(MODULE_NAME)-objs += platform/consys_hw.o
+$(MODULE_NAME)-objs += platform/consys_hw_plat_data.o
+$(MODULE_NAME)-objs += platform/clock_mng.o
+$(MODULE_NAME)-objs += platform/pmic_mng.o
+$(MODULE_NAME)-objs += platform/emi_mng.o
+$(MODULE_NAME)-objs += platform/consys_reg_mng.o
+
+$(MODULE_NAME)-objs += debug_utility/conninfra_dbg.o
+
+# By Plaftfrom
+# MT6880
+$(MODULE_NAME)-objs += platform/mt6880/mt6880.o
+$(MODULE_NAME)-objs += platform/mt6880/mt6880_pmic.o
+$(MODULE_NAME)-objs += platform/mt6880/mt6880_consys_reg.o
+$(MODULE_NAME)-objs += platform/mt6880/mt6880_pos.o
+$(MODULE_NAME)-objs += platform/mt6880/mt6880_emi.o
+
+###############################################################################
+# test
+###############################################################################
+ifneq ($(TARGET_BUILD_VARIANT), user)
+ccflags-y += -D CFG_CONNINFRA_UT_SUPPORT
+endif
+
+#mark for temp start
+#ifeq ($(CFG_CONNINFRA_UT_SUPPORT), y)
+#ccflags-y += -D CFG_CONNINFRA_UT_SUPPORT=1
+
+$(MODULE_NAME)-objs += test/conf_test.o
+$(MODULE_NAME)-objs += test/cal_test.o
+$(MODULE_NAME)-objs += test/msg_evt_test.o
+$(MODULE_NAME)-objs += test/chip_rst_test.o
+$(MODULE_NAME)-objs += test/conninfra_test.o
+$(MODULE_NAME)-objs += test/mailbox_test.o
+#endif
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/Makefile.ce b/src/kernel/modules/connectivity/2.0/conninfra_driver/Makefile.ce
new file mode 100644
index 0000000..7fa78c8
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/Makefile.ce
@@ -0,0 +1,32 @@
+# Makefile for MT66xx conninfra driver
+
+##############################################################
+# Common settings
+##############################################################
+
+
+##############################################################
+# 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/conninfra_driver/NOTICE b/src/kernel/modules/connectivity/2.0/conninfra_driver/NOTICE
new file mode 100755
index 0000000..52c1cac
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/NOTICE
@@ -0,0 +1,202 @@
+The GNU General Public License (GPL)
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU
+General Public License is intended to guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to most of the Free Software Foundation's
+software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make
+sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you
+receive source code or can get it if you want it, that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to
+surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all
+the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them
+these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty
+for this free software. If the software is modified by someone else and passed on, we want its recipients to know that
+what they have is not the original, so that any problems introduced by others will not reflect on the original authors'
+reputations.
+
+Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors
+of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this,
+we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification follow.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it
+may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or
+work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to
+say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into
+another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is
+addressed as "you".
+
+Activities other than copying, distribution and modification are not covered by this License; they are outside its
+scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by running the Program). Whether that is true
+depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided
+that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of
+warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other
+recipients of the Program a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection
+in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and
+copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of
+these conditions:
+
+a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any
+change.
+
+b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the
+Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this
+License.
+
+c) If the modified program normally reads commands interactively when run, you must cause it, when started running for
+such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright
+notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may
+redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if
+the Program itself is interactive but does not normally print such an announcement, your work based on the Program is
+not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the
+Program, and can be reasonably considered independent and separate works in themselves, then this License, and its
+terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same
+sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part
+regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you;
+rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the
+Program.
+
+In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the
+Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
+
+3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you also do one of the following:
+
+a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms
+of Sections 1 and 2 above on a medium customarily used for software interchange; or,
+
+b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than
+your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source
+code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange;
+or,
+
+c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This
+alternative is allowed only for noncommercial distribution and only if you received the program in object code or
+executable form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making modifications to it. For an executable work,
+complete source code means all the source code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the executable. However, as a special exception,
+the source code distributed need not include anything that is normally distributed (in either source or binary form)
+with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless
+that component itself accompanies the executable.
+
+If distribution of executable or object code is made by offering access to copy from a designated place, then offering
+equivalent access to copy the source code from the same place counts as distribution of the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your
+rights under this License. However, parties who have received copies, or rights, from you under this License will not
+have their licenses terminated so long as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it. However, nothing else grants you
+permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do
+not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you
+indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or
+modifying the Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a
+license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You
+may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not
+responsible for enforcing compliance by third parties to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to
+patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the
+conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as
+to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence
+you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution
+of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy
+both it and this License would be to refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the
+section is intended to apply and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest
+validity of any such claims; this section has the sole purpose of protecting the integrity of the free software
+distribution system, which is implemented by public license practices. Many people have made generous contributions to
+the wide range of software distributed through that system in reliance on consistent application of that system; it is
+up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee
+cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted
+interfaces, the original copyright holder who places the Program under this License may add an explicit geographical
+distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if written in the body of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time.
+Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or
+concerns.
+
+Each version is given a distinguishing version number. If the Program specifies a version number of this License which
+applies to it and "any later version", you have the option of following the terms and conditions either of that version
+or of any later version published by the Free Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are
+different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two
+goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
+"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY
+WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL,
+SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT
+LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
+THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY
+OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
+
+
+
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/base/include/msg_thread.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/base/include/msg_thread.h
new file mode 100755
index 0000000..6cb4628
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/base/include/msg_thread.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _BASE_MSG_THREAD_H_
+#define _BASE_MSG_THREAD_H_
+
+#include "osal.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+#define MSG_THREAD_OP_DATA_SIZE 8
+#define MSG_THREAD_OP_BUF_SIZE 64
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+struct msg_op_data {
+ unsigned int op_id; /* Event ID */
+ unsigned int info_bit; /* Reserved */
+ size_t op_data[MSG_THREAD_OP_DATA_SIZE]; /* OP Data */
+};
+
+struct msg_op {
+ struct msg_op_data op;
+ OSAL_SIGNAL signal;
+ int result;
+ atomic_t ref_count;
+};
+
+
+struct msg_op_q {
+ OSAL_SLEEPABLE_LOCK lock;
+ unsigned int write;
+ unsigned int read;
+ unsigned int size;
+ struct msg_op *queue[MSG_THREAD_OP_BUF_SIZE];
+};
+
+typedef OSAL_OP_DAT msg_evt_op;
+typedef int(*msg_opid_func) (struct msg_op_data *);
+
+struct msg_thread_ctx {
+ OSAL_THREAD thread; /* core thread */
+ OSAL_EVENT evt;
+
+ struct msg_op_q free_op_q; /* free op queue */
+ struct msg_op_q active_op_q; /* active op queue */
+ struct msg_op op_q_inst[MSG_THREAD_OP_BUF_SIZE]; /* real op instances */
+ struct msg_op *cur_op; /* current op */
+
+ int op_func_size;
+ const msg_opid_func *op_func;
+
+ struct osal_op_history op_history;
+};
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+#define MSG_OP_TIMEOUT 20000
+
+int msg_thread_init(struct msg_thread_ctx *ctx, const char *name,
+ const msg_opid_func *func, int op_size);
+int msg_thread_deinit(struct msg_thread_ctx *ctx);
+
+/* timeout:
+ * 0: default value (by MSG_OP_TIMEOUT define)
+ * >0: cutom timeout (ms)
+ */
+int msg_thread_send(struct msg_thread_ctx *ctx, int opid);
+int msg_thread_send_1(struct msg_thread_ctx *ctx, int opid,
+ size_t param1);
+int msg_thread_send_2(struct msg_thread_ctx *ctx, int opid,
+ size_t param1, size_t param2);
+
+int msg_thread_send_wait(struct msg_thread_ctx *ctx, int opid,
+ int timeout);
+int msg_thread_send_wait_1(struct msg_thread_ctx *ctx, int opid,
+ int timeout, size_t param1);
+int msg_thread_send_wait_2(struct msg_thread_ctx *ctx, int opid,
+ int timeout, size_t param1, size_t param2);
+int msg_thread_send_wait_3(struct msg_thread_ctx *ctx, int opid, int timeout, size_t param1,
+ size_t param2,size_t param3);
+
+int msg_thread_dump(struct msg_thread_ctx *ctx);
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _BASE_MSG_THREAD_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/base/include/osal.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/base/include/osal.h
new file mode 100755
index 0000000..0c511ce
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/base/include/osal.h
@@ -0,0 +1,405 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+
+/*! \file
+ * \brief Declaration of library functions
+ * Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+ */
+
+#ifndef _OSAL_H_
+#define _OSAL_H_
+
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/wait.h>
+#include "ring.h"
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+#define OS_BIT_OPS_SUPPORT 1
+
+#ifndef MTK_CONN_BOOL_TRUE
+#define MTK_CONN_BOOL_FALSE ((MTK_CONN_BOOL) 0)
+#define MTK_CONN_BOOL_TRUE ((MTK_CONN_BOOL) 1)
+#endif
+
+#define _osal_inline_ inline
+
+#define MAX_THREAD_NAME_LEN 16
+#define MAX_HISTORY_NAME_LEN 16
+#define OSAL_OP_BUF_SIZE 64
+
+
+#if (defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) && !defined(CONFIG_MTK_ENG_BUILD))
+#define OSAL_OP_DATA_SIZE 8
+#else
+#define OSAL_OP_DATA_SIZE 32
+#endif
+
+#define DBG_LOG_STR_SIZE 256
+
+#define osal_sizeof(x) sizeof(x)
+
+#define osal_array_size(x) ARRAY_SIZE(x)
+
+#ifndef NAME_MAX
+#define NAME_MAX 256
+#endif
+
+#define WMT_OP_BIT(x) (0x1UL << x)
+#define WMT_OP_HIF_BIT WMT_OP_BIT(0)
+
+#define GET_BIT_MASK(value, mask) ((value) & (mask))
+#define SET_BIT_MASK(pdest, value, mask) (*(pdest) = (GET_BIT_MASK(*(pdest), ~(mask)) | GET_BIT_MASK(value, mask)))
+#define GET_BIT_RANGE(data, end, begin) ((data) & GENMASK(end, begin))
+#define SET_BIT_RANGE(pdest, data, end, begin) (SET_BIT_MASK(pdest, data, GENMASK(end, begin)))
+
+#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 { \
+ pr_warn("RB is full!"); \
+ } \
+} 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; \
+ pr_warn("RB is empty!"); \
+ } \
+} 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)
+
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+typedef int MTK_CONN_BOOL;
+
+typedef int(*P_COND) (void *);
+
+typedef struct _OSAL_UNSLEEPABLE_LOCK_ {
+ spinlock_t lock;
+ unsigned long flag;
+} OSAL_UNSLEEPABLE_LOCK, *P_OSAL_UNSLEEPABLE_LOCK;
+
+typedef struct _OSAL_SLEEPABLE_LOCK_ {
+ struct mutex lock;
+} OSAL_SLEEPABLE_LOCK, *P_OSAL_SLEEPABLE_LOCK;
+
+typedef struct _OSAL_SIGNAL_ {
+ struct completion comp;
+ unsigned int timeoutValue;
+ unsigned int timeoutExtension; /* max number of timeout caused by thread not able to acquire CPU */
+} OSAL_SIGNAL, *P_OSAL_SIGNAL;
+
+typedef struct _OSAL_EVENT_ {
+ wait_queue_head_t waitQueue;
+ unsigned int timeoutValue;
+ int waitFlag;
+
+} OSAL_EVENT, *P_OSAL_EVENT;
+
+/* Data collected from sched_entity and sched_statistics */
+typedef struct _OSAL_THREAD_SCHEDSTATS_ {
+ unsigned long long time; /* when marked: the profiling start time(ms), when unmarked: total duration(ms) */
+ unsigned long long exec; /* time spent in exec (sum_exec_runtime) */
+ unsigned long long runnable; /* time spent in run-queue while not being scheduled (wait_sum) */
+ unsigned long long iowait; /* time spent waiting for I/O (iowait_sum) */
+} OSAL_THREAD_SCHEDSTATS, *P_OSAL_THREAD_SCHEDSTATS;
+
+typedef struct _OSAL_THREAD_ {
+ struct task_struct *pThread;
+ void *pThreadFunc;
+ void *pThreadData;
+ char threadName[MAX_THREAD_NAME_LEN];
+} OSAL_THREAD, *P_OSAL_THREAD;
+
+
+typedef struct _OSAL_FIFO_ {
+ /*fifo definition */
+ void *pFifoBody;
+ spinlock_t fifoSpinlock;
+ /*fifo operations */
+ int (*FifoInit)(struct _OSAL_FIFO_ *pFifo, unsigned char *buf, unsigned int);
+ int (*FifoDeInit)(struct _OSAL_FIFO_ *pFifo);
+ int (*FifoReset)(struct _OSAL_FIFO_ *pFifo);
+ int (*FifoSz)(struct _OSAL_FIFO_ *pFifo);
+ int (*FifoAvailSz)(struct _OSAL_FIFO_ *pFifo);
+ int (*FifoLen)(struct _OSAL_FIFO_ *pFifo);
+ int (*FifoIsEmpty)(struct _OSAL_FIFO_ *pFifo);
+ int (*FifoIsFull)(struct _OSAL_FIFO_ *pFifo);
+ int (*FifoDataIn)(struct _OSAL_FIFO_ *pFifo, const void *buf, unsigned int len);
+ int (*FifoDataOut)(struct _OSAL_FIFO_ *pFifo, void *buf, unsigned int len);
+} OSAL_FIFO, *P_OSAL_FIFO;
+
+typedef struct firmware osal_firmware;
+
+typedef struct _OSAL_OP_DAT {
+ unsigned int opId; /* Event ID */
+ unsigned int u4InfoBit; /* Reserved */
+ size_t au4OpData[OSAL_OP_DATA_SIZE]; /* OP Data */
+} OSAL_OP_DAT, *P_OSAL_OP_DAT;
+
+typedef struct _OSAL_LXOP_ {
+ OSAL_OP_DAT op;
+ OSAL_SIGNAL signal;
+ int result;
+ atomic_t ref_count;
+} OSAL_OP, *P_OSAL_OP;
+
+typedef struct _OSAL_LXOP_Q {
+ OSAL_SLEEPABLE_LOCK sLock;
+ unsigned int write;
+ unsigned int read;
+ unsigned int size;
+ P_OSAL_OP queue[OSAL_OP_BUF_SIZE];
+} OSAL_OP_Q, *P_OSAL_OP_Q;
+
+typedef struct _OSAL_BIT_OP_VAR_ {
+ unsigned long data;
+ OSAL_UNSLEEPABLE_LOCK opLock;
+} OSAL_BIT_OP_VAR, *P_OSAL_BIT_OP_VAR;
+
+typedef unsigned int (*P_OSAL_EVENT_CHECKER) (P_OSAL_THREAD pThread);
+
+struct osal_op_history_entry {
+ void *opbuf_address;
+ unsigned int op_id;
+ unsigned int opbuf_ref_count;
+ unsigned int op_info_bit;
+ size_t param_0;
+ size_t param_1;
+ size_t param_2;
+ size_t param_3;
+ unsigned long long ts;
+ unsigned long usec;
+};
+
+struct osal_op_history {
+ struct ring ring_buffer;
+ struct osal_op_history_entry *queue;
+ spinlock_t lock;
+ struct ring dump_ring_buffer;
+ struct work_struct dump_work;
+ unsigned char name[MAX_HISTORY_NAME_LEN];
+};
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+unsigned int osal_strlen(const char *str);
+int osal_strcmp(const char *dst, const char *src);
+int osal_strncmp(const char *dst, const char *src, unsigned int len);
+char *osal_strcpy(char *dst, const char *src);
+char *osal_strncpy(char *dst, const char *src, unsigned int len);
+char *osal_strcat(char *dst, const char *src);
+char *osal_strncat(char *dst, const char *src, unsigned int len);
+char *osal_strchr(const char *str, unsigned char c);
+char *osal_strsep(char **str, const char *c);
+int osal_strtol(const char *str, unsigned int adecimal, long *res);
+char *osal_strstr(char *str1, const char *str2);
+char *osal_strnstr(char *str1, const char *str2, int n);
+
+void osal_bug_on(unsigned int val);
+
+int osal_snprintf(char *buf, unsigned int len, const char *fmt, ...);
+
+int osal_sprintf(char *str, const char *format, ...);
+void *osal_malloc(unsigned int size);
+void osal_free(const void *dst);
+void *osal_memset(void *buf, int i, unsigned int len);
+void *osal_memcpy(void *dst, const void *src, unsigned int len);
+void osal_memcpy_fromio(void *dst, const void *src, unsigned int len);
+void osal_memcpy_toio(void *dst, const void *src, unsigned int len);
+int osal_memcmp(const void *buf1, const void *buf2, unsigned int len);
+
+void osal_thread_show_stack(P_OSAL_THREAD pThread);
+
+int osal_sleep_ms(unsigned int ms);
+int osal_udelay(unsigned int us);
+int osal_usleep_range(unsigned long min, unsigned long max);
+
+int osal_fifo_init(P_OSAL_FIFO pFifo, unsigned char *buffer, unsigned int size);
+void osal_fifo_deinit(P_OSAL_FIFO pFifo);
+int osal_fifo_reset(P_OSAL_FIFO pFifo);
+unsigned int osal_fifo_in(P_OSAL_FIFO pFifo, unsigned char *buffer,
+ unsigned int size);
+unsigned int osal_fifo_out(P_OSAL_FIFO pFifo, unsigned char *buffer,
+ unsigned int size);
+unsigned int osal_fifo_len(P_OSAL_FIFO pFifo);
+unsigned int osal_fifo_sz(P_OSAL_FIFO pFifo);
+unsigned int osal_fifo_avail(P_OSAL_FIFO pFifo);
+unsigned int osal_fifo_is_empty(P_OSAL_FIFO pFifo);
+unsigned int osal_fifo_is_full(P_OSAL_FIFO pFifo);
+
+#if defined(CONFIG_PROVE_LOCKING)
+#define osal_unsleepable_lock_init(l) { spin_lock_init(&((l)->lock)); }
+#else
+int osal_unsleepable_lock_init(P_OSAL_UNSLEEPABLE_LOCK);
+#endif
+int osal_lock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK);
+int osal_unlock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK);
+int osal_unsleepable_lock_deinit(P_OSAL_UNSLEEPABLE_LOCK);
+
+#if defined(CONFIG_PROVE_LOCKING)
+#define osal_sleepable_lock_init(l) { mutex_init(&((l)->lock)); }
+#else
+int osal_sleepable_lock_init(P_OSAL_SLEEPABLE_LOCK);
+#endif
+int osal_lock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK);
+int osal_unlock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK);
+int osal_trylock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK);
+int osal_sleepable_lock_deinit(P_OSAL_SLEEPABLE_LOCK);
+
+int osal_signal_init(P_OSAL_SIGNAL);
+int osal_wait_for_signal(P_OSAL_SIGNAL);
+int osal_wait_for_signal_timeout(P_OSAL_SIGNAL, P_OSAL_THREAD);
+int osal_raise_signal(P_OSAL_SIGNAL);
+int osal_signal_active_state(P_OSAL_SIGNAL pSignal);
+int osal_signal_deinit(P_OSAL_SIGNAL);
+
+int osal_event_init(P_OSAL_EVENT);
+int osal_wait_for_event(P_OSAL_EVENT, P_COND, void*);
+int osal_wait_for_event_timeout(P_OSAL_EVENT, P_COND, void*);
+extern int osal_trigger_event(P_OSAL_EVENT);
+
+int osal_event_deinit(P_OSAL_EVENT);
+long osal_wait_for_event_bit_set(P_OSAL_EVENT pEvent, unsigned long *pState, unsigned int bitOffset);
+long osal_wait_for_event_bit_clr(P_OSAL_EVENT pEvent, unsigned long *pState, unsigned int bitOffset);
+
+int osal_thread_create(P_OSAL_THREAD);
+int osal_thread_run(P_OSAL_THREAD);
+int osal_thread_should_stop(P_OSAL_THREAD);
+int osal_thread_stop(P_OSAL_THREAD);
+/*int osal_thread_wait_for_event(P_OSAL_THREAD, P_OSAL_EVENT);*/
+int osal_thread_wait_for_event(P_OSAL_THREAD, P_OSAL_EVENT, P_OSAL_EVENT_CHECKER);
+/*check pOsalLxOp and OSAL_THREAD_SHOULD_STOP*/
+int osal_thread_destroy(P_OSAL_THREAD);
+int osal_thread_sched_mark(P_OSAL_THREAD, P_OSAL_THREAD_SCHEDSTATS schedstats);
+int osal_thread_sched_unmark(P_OSAL_THREAD pThread, P_OSAL_THREAD_SCHEDSTATS schedstats);
+
+int osal_clear_bit(unsigned int bitOffset, P_OSAL_BIT_OP_VAR pData);
+int osal_set_bit(unsigned int bitOffset, P_OSAL_BIT_OP_VAR pData);
+int osal_test_bit(unsigned int bitOffset, P_OSAL_BIT_OP_VAR pData);
+int osal_test_and_clear_bit(unsigned int bitOffset, P_OSAL_BIT_OP_VAR pData);
+int osal_test_and_set_bit(unsigned int bitOffset, P_OSAL_BIT_OP_VAR pData);
+
+int osal_gettimeofday(int *sec, int *usec);
+//int osal_printtimeofday(const unsigned char *prefix);
+void osal_get_local_time(unsigned long long *sec, unsigned long *nsec);
+unsigned long long osal_elapsed_us(unsigned long long ts, unsigned long usec);
+
+void osal_buffer_dump(const unsigned char *buf, const unsigned char *title, unsigned int len, unsigned int limit);
+void osal_buffer_dump_data(const unsigned int *buf, const unsigned char *title, const unsigned int len, const unsigned int limit,
+ const int flag);
+
+unsigned int osal_op_get_id(P_OSAL_OP pOp);
+MTK_CONN_BOOL osal_op_is_wait_for_signal(P_OSAL_OP pOp);
+void osal_op_raise_signal(P_OSAL_OP pOp, int result);
+void osal_set_op_result(P_OSAL_OP pOp, int result);
+void osal_opq_dump(const char *qName, P_OSAL_OP_Q pOpQ);
+void osal_opq_dump_locked(const char *qName, P_OSAL_OP_Q pOpQ);
+MTK_CONN_BOOL osal_opq_has_op(P_OSAL_OP_Q pOpQ, P_OSAL_OP pOp);
+
+int osal_ftrace_print(const char *str, ...);
+int osal_ftrace_print_ctrl(int flag);
+
+void osal_dump_thread_state(const unsigned char *name);
+void osal_op_history_init(struct osal_op_history *log_history, int queue_size);
+void osal_op_history_save(struct osal_op_history *log_history, P_OSAL_OP pOp);
+void osal_op_history_print(struct osal_op_history *log_history, char *name);
+
+void osal_systrace_major_b(const char *name, ...);
+void osal_systrace_major_e(void);
+
+void osal_systrace_minor_b(const char *name, ...);
+void osal_systrace_minor_e(void);
+void osal_systrace_minor_c(int val, const char *name, ...);
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _OSAL_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/base/include/ring.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/base/include/ring.h
new file mode 100755
index 0000000..81168ce
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/base/include/ring.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 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 _RING_H_
+#define _RING_H_
+
+struct ring {
+ /* addr where ring buffer starts */
+ void *base;
+ /* addr storing the next writable pos, guaranteed to be >= read except when write overflow, but it's ok. */
+ unsigned int write;
+ /* addr storing the next readable pos, except when read == write as buffer empty */
+ unsigned int read;
+ /* must be power of 2 */
+ unsigned int max_size;
+};
+
+struct ring_segment {
+ /* addr points into ring buffer for read/write */
+ void *ring_pt;
+ /* size to read/write */
+ unsigned int sz;
+ /* pos in external data buffer to read/write */
+ unsigned int data_pos;
+ /* the size to be read/write after this segment completed */
+ unsigned int remain;
+};
+
+void ring_init(void *base, unsigned int max_size, unsigned int read,
+ unsigned int write, struct ring *ring);
+unsigned int ring_read_prepare(unsigned int sz, struct ring_segment *seg, struct ring *ring);
+#define ring_read_all_prepare(seg, ring) ring_read_prepare((ring)->max_size, seg, ring)
+unsigned int ring_write_prepare(unsigned int sz, struct ring_segment *seg, struct ring *ring);
+unsigned int ring_overwrite_prepare(unsigned int sz,
+ struct ring_segment *seg, struct ring *ring);
+
+/* making sure max_size is power of 2 */
+#define RING_VALIDATE_SIZE(max_size) WARN_ON(!max_size || (max_size & (max_size - 1)))
+
+#define RING_EMPTY(ring) ((ring)->read == (ring)->write)
+/* equation works even when write overflow */
+#define RING_SIZE(ring) ((ring)->write - (ring)->read)
+#define RING_FULL(ring) (RING_SIZE(ring) == (ring)->max_size)
+#define RING_WRITE_REMAIN_SIZE(ring) ((ring)->max_size - RING_SIZE(ring))
+
+#define RING_READ_FOR_EACH(_sz, _seg, _ring) \
+ for (ring_read_prepare(_sz, &(_seg), _ring), \
+ _ring_segment_prepare((_ring)->read, &(_seg), (_ring)); \
+ (_seg).sz > 0; \
+ _ring_read_commit(&(_seg), (_ring)), _ring_segment_prepare((_ring)->read, \
+ &(_seg), (_ring)))
+
+#define RING_READ_ALL_FOR_EACH(seg, ring) RING_READ_FOR_EACH((ring)->max_size, seg, ring)
+
+#define RING_READ_FOR_EACH_ITEM(_sz, _seg, _ring) \
+ for (ring_read_prepare(_sz, &(_seg), _ring), \
+ _ring_segment_prepare_item((_ring)->read, &(_seg), (_ring)); \
+ (_seg).sz > 0; \
+ _ring_read_commit(&(_seg), (_ring)), _ring_segment_prepare_item((_ring)->read, \
+ &(_seg), (_ring)))
+
+#define RING_WRITE_FOR_EACH(_sz, _seg, _ring) \
+ for (ring_write_prepare(_sz, &(_seg), _ring),\
+ _ring_segment_prepare((_ring)->write, &(_seg), (_ring)); \
+ (_seg).sz > 0; \
+ _ring_write_commit(&(_seg), (_ring)), _ring_segment_prepare((_ring)->write, \
+ &(_seg), (_ring)))
+
+#define RING_OVERWRITE_FOR_EACH(_sz, _seg, _ring) \
+ for (ring_overwrite_prepare(_sz, &(_seg), _ring), \
+ _ring_segment_prepare((_ring)->write, &(_seg), (_ring)); \
+ (_seg).sz > 0; \
+ _ring_write_commit(&(_seg), (_ring)), _ring_segment_prepare((_ring)->write, \
+ &(_seg), (_ring)))
+
+void ring_dump(const char *title, struct ring *ring);
+void ring_dump_segment(const char *title, struct ring_segment *seg);
+
+
+/* ring Buffer Internal API */
+void _ring_segment_prepare(unsigned int from, struct ring_segment *seg, struct ring *ring);
+void _ring_segment_prepare_item(unsigned int from, struct ring_segment *seg, struct ring *ring);
+void _ring_read_commit(struct ring_segment *seg, struct ring *ring);
+void _ring_write_commit(struct ring_segment *seg, struct ring *ring);
+
+#endif
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/base/msg_thread.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/base/msg_thread.c
new file mode 100755
index 0000000..873c0f7
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/base/msg_thread.c
@@ -0,0 +1,716 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__
+#include <linux/delay.h>
+#include "msg_thread.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+static void msg_opq_dump(const char *qName, struct msg_op_q *op_q);
+static void _msg_opq_dump(const char *qName, struct msg_op_q *op_q);
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#define MSG_OP_SIZE(prb) ((prb)->size)
+#define MSG_OP_MASK(prb) (MSG_OP_SIZE(prb) - 1)
+#define MSG_OP_COUNT(prb) ((prb)->write - (prb)->read)
+#define MSG_OP_FULL(prb) (MSG_OP_COUNT(prb) >= MSG_OP_SIZE(prb))
+#define MSG_OP_EMPTY(prb) ((prb)->write == (prb)->read)
+
+#define MSG_OP_INIT(prb, qsize) \
+do { \
+ (prb)->read = (prb)->write = 0; \
+ (prb)->size = (qsize); \
+} while (0)
+
+#define MSG_OP_PUT(prb, value) \
+do { \
+ if (!MSG_OP_FULL(prb)) { \
+ (prb)->queue[(prb)->write & MSG_OP_MASK(prb)] = value; \
+ ++((prb)->write); \
+ } \
+ else { \
+ pr_warn("Message queue is full."); \
+ } \
+} while (0)
+
+#define MSG_OP_GET(prb, value) \
+do { \
+ if (!MSG_OP_EMPTY(prb)) { \
+ value = (prb)->queue[(prb)->read & MSG_OP_MASK(prb)]; \
+ ++((prb)->read); \
+ if (MSG_OP_EMPTY(prb)) { \
+ (prb)->read = (prb)->write = 0; \
+ } \
+ } \
+ else { \
+ value = NULL; \
+ pr_warn("Message queue is empty."); \
+ } \
+} while (0)
+
+
+
+#if defined(CONFIG_MTK_ENG_BUILD) || defined(CONFIG_MT_ENG_BUILD)
+static bool msg_evt_opq_has_op(struct msg_op_q *op_q, struct msg_op *op)
+{
+ unsigned int rd;
+ unsigned int wt;
+ struct msg_op *tmp_op;
+
+ rd = op_q->read;
+ wt = op_q->write;
+
+ while (rd != wt) {
+ tmp_op = op_q->queue[rd & MSG_OP_MASK(op_q)];
+ if (op == tmp_op)
+ return true;
+ rd++;
+ }
+ return false;
+}
+#endif
+
+/*
+ * Utility functions
+ */
+static int msg_evt_put_op_to_q(struct msg_op_q *op_q, struct msg_op *op)
+{
+ int ret;
+
+ if (!op_q || !op) {
+ pr_err("invalid input param: pOpQ(0x%p), pLxOp(0x%p)\n", op_q, op);
+ return -1;
+ }
+
+ ret = osal_lock_sleepable_lock(&op_q->lock);
+ if (ret) {
+ pr_warn("osal_lock_sleepable_lock iRet(%d)\n", ret);
+ return -2;
+ }
+
+#if defined(CONFIG_MTK_ENG_BUILD) || defined(CONFIG_MT_ENG_BUILD)
+ if (msg_evt_opq_has_op(op_q, op)) {
+ pr_err("Op(%p) already exists in queue(%p)\n", op, op_q);
+ ret = -3;
+ }
+#endif
+
+ /* acquire lock success */
+ if (!MSG_OP_FULL(op_q))
+ MSG_OP_PUT(op_q, op);
+ else {
+ pr_warn("MSG_OP_FULL(%p -> %p)\n", op, op_q);
+ ret = -4;
+ }
+
+ osal_unlock_sleepable_lock(&op_q->lock);
+
+ if (ret) {
+ //osal_opq_dump("FreeOpQ", &g_conninfra_ctx.rFreeOpQ);
+ //osal_opq_dump("ActiveOpQ", &g_conninfra_ctx.rActiveOpQ);
+ return ret;
+ }
+ return 0;
+}
+
+
+/*
+ * Utility functions
+ */
+static struct msg_op *msg_evt_get_op_from_q(struct msg_op_q *op_q)
+{
+ struct msg_op *op;
+ int ret;
+
+ if (op_q == NULL) {
+ pr_err("pOpQ = NULL\n");
+ return NULL;
+ }
+
+ ret = osal_lock_sleepable_lock(&op_q->lock);
+ if (ret) {
+ pr_err("osal_lock_sleepable_lock iRet(%d)\n", ret);
+ return NULL;
+ }
+
+ /* acquire lock success */
+ MSG_OP_GET(op_q, op);
+ osal_unlock_sleepable_lock(&op_q->lock);
+
+ if (op == NULL) {
+ pr_warn("MSG_OP_GET(%p) return NULL\n", op_q);
+ //osal_opq_dump("FreeOpQ", &g_conninfra_ctx.rFreeOpQ);
+ //osal_opq_dump("ActiveOpQ", &g_conninfra_ctx.rActiveOpQ);
+ }
+
+ return op;
+}
+
+static void _msg_opq_dump(const char *qName, struct msg_op_q *op_q)
+{
+ /* Line format:
+ * [LogicalIdx(PhysicalIdx)]Address:OpId(Ref)(Result)-Info-OpData0,OpData1,OpData2,OpData3,OpData5_
+ * [LogicalIdx] max 10+2=12 chars (decimal)
+ * (PhysicalIdx) max 10+2=12 chars (decimal)
+ * Address: max 16+1=17 chars (hex)
+ * OpId max 10 chars (decimal)
+ * (Ref) max 2+2=4 chars (should only be 1 digit, reserve 2 in case of negative number)
+ * (Result) max 11+2=13 chars (signed decimal)
+ * -Info- max 8+2=10 chars (hex)
+ * OpData, max 16+1=17 chars (hex)
+ */
+#define OPQ_DUMP_OP_PER_LINE 1
+#define OPQ_DUMP_OPDATA_PER_OP 6
+#define OPQ_DUMP_OP_BUF_SIZE (12 + 12 + 17 + 10 + 4 + 13 + 10 + (17 * (OPQ_DUMP_OPDATA_PER_OP)) + 1)
+#define OPQ_DUMP_LINE_BUF_SIZE ((OPQ_DUMP_OP_BUF_SIZE * OPQ_DUMP_OP_PER_LINE) + 1)
+ unsigned int rd;
+ unsigned int wt;
+ unsigned int idx = 0;
+ unsigned int op_data_idx;
+ unsigned int buf_idx;
+ int printed;
+ struct msg_op *op;
+ char buf[OPQ_DUMP_LINE_BUF_SIZE];
+
+ rd = op_q->read;
+ wt = op_q->write;
+
+ pr_info("%s(%p), sz:%u/%u, rd:%u, wt:%u\n",
+ qName, op_q, RB_COUNT(op_q), RB_SIZE(op_q), rd, wt);
+ while (rd != wt && idx < RB_SIZE(op_q)) {
+ buf_idx = idx % OPQ_DUMP_OP_PER_LINE;
+ op = op_q->queue[rd & RB_MASK(op_q)];
+
+ if (buf_idx == 0) {
+ printed = 0;
+ buf[0] = 0;
+ }
+
+ if (op) {
+ printed += snprintf(buf + printed, OPQ_DUMP_LINE_BUF_SIZE - printed,
+ "[%u(%u)]%p:%u(%d)(%d)-%u-",
+ idx,
+ (rd & RB_MASK(op_q)),
+ op,
+ op->op.op_id,
+ atomic_read(&op->ref_count),
+ op->result,
+ op->op.info_bit);
+ for (op_data_idx = 0; op_data_idx < OPQ_DUMP_OPDATA_PER_OP; op_data_idx++)
+ printed += snprintf(buf + printed, OPQ_DUMP_LINE_BUF_SIZE - printed,
+ "%zx,", op->op.op_data[op_data_idx]);
+ buf[printed-1] = ' ';
+ } else {
+ printed += snprintf(buf + printed, OPQ_DUMP_LINE_BUF_SIZE - printed,
+ "[%u(%u)]%p ", idx, (rd & RB_MASK(op_q)), op);
+ }
+ buf[printed++] = ' ';
+
+ if (buf_idx == OPQ_DUMP_OP_PER_LINE - 1 || rd == wt - 1) {
+ buf[printed - 1] = 0;
+ pr_info("%s\n", buf);
+ }
+ rd++;
+ idx++;
+ }
+}
+
+void msg_opq_dump(const char *qName, struct msg_op_q *op_q)
+{
+ int err;
+
+ err = osal_lock_sleepable_lock(&op_q->lock);
+ if (err) {
+ pr_info("Failed to lock queue (%d)\n", err);
+ return;
+ }
+
+ _msg_opq_dump(qName, op_q);
+
+ osal_unlock_sleepable_lock(&op_q->lock);
+}
+
+/*
+ * msg_evt_thread API
+ */
+
+int msg_evt_put_op_to_free_queue(struct msg_thread_ctx *ctx, struct msg_op *op)
+{
+ if (msg_evt_put_op_to_q(&ctx->free_op_q, op))
+ return -1;
+ return 0;
+}
+
+
+struct msg_op *msg_evt_get_free_op(struct msg_thread_ctx *ctx)
+{
+ struct msg_op *op = NULL;
+
+ if (ctx == NULL) {
+ pr_warn("ctx is null.");
+ return op;
+ }
+ op = msg_evt_get_op_from_q(&ctx->free_op_q);
+ if (op)
+ osal_memset(op, 0, osal_sizeof(struct msg_op));
+ return op;
+}
+
+int msg_evt_put_op_to_active(struct msg_thread_ctx *ctx, struct msg_op *op)
+{
+ P_OSAL_SIGNAL signal = NULL;
+ int wait_ret = -1;
+ int ret = 0;
+
+ do {
+ if (!ctx || !op) {
+ pr_err("msg_thread_ctx(0x%p), op(0x%p)\n", ctx, op);
+ break;
+ }
+
+ signal = &op->signal;
+ if (signal->timeoutValue) {
+ op->result = -9;
+ osal_signal_init(signal);
+ atomic_set(&op->ref_count, 1);
+ } else
+ atomic_set(&op->ref_count, 0);
+
+ /* Increment ref_count by 1 as wmtd 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(&op->ref_count);
+
+ /* put to active Q */
+ ret = msg_evt_put_op_to_q(&ctx->active_op_q, op);
+ if (ret) {
+ pr_warn("put to active queue fail\n");
+ atomic_dec(&op->ref_count);
+ break;
+ }
+
+ /* wake up conninfra_cored */
+ osal_trigger_event(&ctx->evt);
+
+ if (signal->timeoutValue == 0) {
+ //ret = -1;
+ /* Not set timeout, don't wait */
+ /* pr_info("[%s] timeout is zero", __func__);*/
+ break;
+ }
+
+ /* check result */
+ wait_ret = osal_wait_for_signal_timeout(signal, &ctx->thread);
+ /*pr_info("osal_wait_for_signal_timeout:%d result=[%d]\n",
+ wait_ret, op->result);*/
+
+ if (wait_ret == 0)
+ pr_warn("opId(%d) completion timeout\n", op->op.op_id);
+ else if (op->result)
+ pr_info("opId(%d) result:%d\n",
+ op->op.op_id, op->result);
+
+ /* op completes, check result */
+ ret = op->result;
+ } while (0);
+
+ if (op != NULL && signal != NULL && signal->timeoutValue &&
+ atomic_dec_and_test(&op->ref_count)) {
+ /* put Op back to freeQ */
+ msg_evt_put_op_to_free_queue(ctx, op);
+ }
+
+ return ret;
+}
+
+
+int msg_thread_send(struct msg_thread_ctx *ctx, int opid)
+{
+ return msg_thread_send_2(ctx, opid, 0, 0);
+}
+
+int msg_thread_send_1(struct msg_thread_ctx *ctx, int opid,
+ size_t param1)
+{
+ return msg_thread_send_2(ctx, opid, param1, 0);
+}
+
+int msg_thread_send_2(struct msg_thread_ctx *ctx, int opid,
+ size_t param1, size_t param2)
+{
+ struct msg_op *op = NULL;
+ P_OSAL_SIGNAL signal;
+ int ret;
+
+ op = msg_evt_get_free_op(ctx);
+ if (!op) {
+ pr_err("[%s] can't get free op\n", __func__);
+ return -1;
+ }
+ op->op.op_id = opid;
+ op->op.op_data[0] = param1;
+ op->op.op_data[1] = param2;
+
+ signal = &op->signal;
+ //signal->timeoutValue = timeout > 0 ? timeout : MSG_OP_TIMEOUT;
+ signal->timeoutValue = 0;
+ ret = msg_evt_put_op_to_active(ctx, op);
+
+ return ret;
+}
+
+int msg_thread_send_wait(struct msg_thread_ctx *ctx, int opid,
+ int timeout)
+{
+ return msg_thread_send_wait_3(ctx, opid, timeout, 0, 0, 0);
+}
+
+int msg_thread_send_wait_1(struct msg_thread_ctx *ctx,
+ int opid, int timeout,
+ size_t param1)
+{
+ return msg_thread_send_wait_3(ctx, opid, timeout, param1, 0, 0);
+}
+
+
+int msg_thread_send_wait_2(struct msg_thread_ctx *ctx,
+ int opid, int timeout,
+ size_t param1,
+ size_t param2)
+{
+ return msg_thread_send_wait_3(ctx, opid, timeout, param1, param2, 0);
+}
+
+int msg_thread_send_wait_3(struct msg_thread_ctx *ctx,
+ int opid, int timeout,
+ size_t param1,
+ size_t param2,
+ size_t param3)
+{
+ struct msg_op *op = NULL;
+ P_OSAL_SIGNAL signal;
+ int ret;
+
+ op = msg_evt_get_free_op(ctx);
+ if (!op) {
+ pr_err("[%s] can't get free op for 0x%x\n", __func__, opid);
+ return -1;
+ }
+ op->op.op_id = opid;
+ op->op.op_data[0] = param1;
+ op->op.op_data[1] = param2;
+ op->op.op_data[2] = param3;
+
+ signal = &op->signal;
+ signal->timeoutValue = timeout > 0 ? timeout : MSG_OP_TIMEOUT;
+ ret = msg_evt_put_op_to_active(ctx, op);
+ return ret;
+
+}
+
+void msg_op_history_save(struct osal_op_history *log_history, struct msg_op *op)
+{
+ struct osal_op_history_entry *entry = NULL;
+ struct ring_segment seg;
+ int index;
+ unsigned long long sec = 0;
+ unsigned long usec = 0;
+ unsigned long flags;
+
+ if (log_history->queue == NULL)
+ return;
+
+ osal_get_local_time(&sec, &usec);
+
+ spin_lock_irqsave(&(log_history->lock), flags);
+ RING_OVERWRITE_FOR_EACH(1, seg, &log_history->ring_buffer) {
+ index = seg.ring_pt - log_history->ring_buffer.base;
+ entry = &log_history->queue[index];
+ }
+
+ if (entry == NULL) {
+ pr_info("Entry is null, size %d\n",
+ RING_SIZE(&log_history->ring_buffer));
+ spin_unlock_irqrestore(&(log_history->lock), flags);
+ return;
+ }
+
+ entry->opbuf_address = op;
+ entry->op_id = op->op.op_id;
+ entry->opbuf_ref_count = atomic_read(&op->ref_count);
+ entry->op_info_bit = op->op.info_bit;
+ entry->param_0 = op->op.op_data[0];
+ entry->param_1 = op->op.op_data[1];
+ entry->param_2 = op->op.op_data[2];
+ entry->param_3 = op->op.op_data[3];
+ entry->ts = sec;
+ entry->usec = usec;
+ spin_unlock_irqrestore(&(log_history->lock), flags);
+}
+
+unsigned int msg_evt_wait_event_checker(P_OSAL_THREAD thread)
+{
+ struct msg_thread_ctx *ctx = NULL;
+
+ if (thread) {
+ ctx = (struct msg_thread_ctx *) (thread->pThreadData);
+ return !MSG_OP_EMPTY(&ctx->active_op_q);
+ }
+ return 0;
+}
+
+int msg_evt_set_current_op(struct msg_thread_ctx *ctx, struct msg_op *op)
+{
+ ctx->cur_op = op;
+ return 0;
+}
+
+int msg_evt_opid_handler(struct msg_thread_ctx *ctx, struct msg_op_data *op)
+{
+ int opid, ret;
+
+ /*sanity check */
+ if (op == NULL) {
+ pr_warn("null op\n");
+ return -1;
+ }
+ if (ctx == NULL) {
+ pr_warn("null evt thread ctx\n");
+ return -2;
+ }
+
+ opid = op->op_id;
+
+ if (opid >= ctx->op_func_size) {
+ pr_err("msg_evt_thread invalid OPID(%d)\n", opid);
+ return -3;
+ }
+
+ if (ctx->op_func[opid] == NULL) {
+ pr_err("null handler (%d)\n", opid);
+ return -4;
+ }
+ ret = (*(ctx->op_func[opid])) (op);
+ return ret;
+}
+
+static int msg_evt_thread(void *pvData)
+{
+ struct msg_thread_ctx *ctx = (struct msg_thread_ctx *)pvData;
+ P_OSAL_EVENT evt = NULL;
+ struct msg_op *op;
+ int ret;
+
+ if (ctx == NULL) {
+ pr_err("msg_evt_thread (NULL)\n");
+ return -1;
+ }
+
+ evt = &(ctx->evt);
+
+ for (;;) {
+ op = NULL;
+ evt->timeoutValue = 0;
+
+ osal_thread_wait_for_event(&ctx->thread, evt, msg_evt_wait_event_checker);
+
+ if (osal_thread_should_stop(&ctx->thread)) {
+ pr_info("msg_evt_thread thread should stop now...\n");
+ /* TODO: clean up active opQ */
+ break;
+ }
+ /* get Op from activeQ */
+ op = msg_evt_get_op_from_q(&ctx->active_op_q);
+ if (!op) {
+ pr_warn("get op from activeQ fail\n");
+ continue;
+ }
+
+ /* TODO: save op history */
+ msg_op_history_save(&ctx->op_history, op);
+ msg_evt_set_current_op(ctx, op);
+ ret = msg_evt_opid_handler(ctx, &op->op);
+ msg_evt_set_current_op(ctx, NULL);
+
+ if (ret)
+ pr_warn("opid (0x%x) failed, ret(%d)\n",
+ op->op.op_id, ret);
+
+ if (atomic_dec_and_test(&op->ref_count)) {
+ /* msg_evt_free_op(ctx) */
+ msg_evt_put_op_to_free_queue(ctx, op);
+ } else if (op->signal.timeoutValue) {
+ op->result = ret;
+ osal_raise_signal(&op->signal);
+ }
+ }
+
+ pr_debug("msg evt thread exists\n");
+ return 0;
+}
+
+int msg_thread_dump(struct msg_thread_ctx *ctx)
+{
+ P_OSAL_THREAD p_thread;
+ struct msg_op *cur_op;
+
+ if (ctx == NULL) {
+ pr_err("%s get NULL input\n", __func__);
+ return 0;
+ }
+ p_thread = &ctx->thread;
+ pr_info("Dump msg_thread_ctx: %s\n", p_thread->threadName);
+ cur_op = ctx->cur_op;
+ if (cur_op) {
+ pr_info("cur_op: %x(%x)-%zx,%zx,%zx,%zx\n",
+ cur_op->op.op_id, cur_op->op.info_bit,
+ cur_op->op.op_data[0], cur_op->op.op_data[1],
+ cur_op->op.op_data[2], cur_op->op.op_data[3]);
+ }
+ osal_dump_thread_state(p_thread->threadName);
+ osal_op_history_print(&(ctx->op_history), p_thread->threadName);
+ msg_opq_dump("ActiveOpQ", &ctx->active_op_q);
+
+ return 0;
+}
+
+int msg_thread_init(struct msg_thread_ctx *ctx,
+ const char *thread_name, const msg_opid_func *funcs,
+ int op_size)
+{
+ int r = 0, i;
+ P_OSAL_THREAD p_thread;
+
+ osal_memset(ctx, 0, sizeof(struct msg_thread_ctx));
+
+ ctx->op_func = funcs;
+ ctx->op_func_size = op_size;
+
+ /* init thread inst */
+ p_thread = &ctx->thread;
+
+ osal_strncpy(p_thread->threadName, thread_name,
+ sizeof(p_thread->threadName));
+
+ p_thread->pThreadData = (void *) ctx;
+ p_thread->pThreadFunc = (void *) msg_evt_thread;
+ r = osal_thread_create(p_thread);
+
+ if (r) {
+ pr_err("osal_thread_create(0x%p) fail(%d)\n", p_thread, r);
+ return -1;
+ }
+
+ osal_event_init(&ctx->evt);
+ osal_sleepable_lock_init(&ctx->active_op_q.lock);
+ osal_sleepable_lock_init(&ctx->free_op_q.lock);
+
+ /* Initialize op queue */
+ MSG_OP_INIT(&ctx->free_op_q, MSG_THREAD_OP_BUF_SIZE);
+ MSG_OP_INIT(&ctx->active_op_q, MSG_THREAD_OP_BUF_SIZE);
+
+ /* Put all to free Q */
+ for (i = 0; i < MSG_THREAD_OP_BUF_SIZE; i++) {
+ osal_signal_init(&(ctx->op_q_inst[i].signal));
+ msg_evt_put_op_to_free_queue(ctx, &(ctx->op_q_inst[i]));
+ }
+
+ osal_op_history_init(&ctx->op_history, 16);
+
+ r = osal_thread_run(p_thread);
+ if (r) {
+ pr_err("osal_thread_run(evt_thread 0x%p) fail(%d)\n",
+ p_thread, r);
+ return -2;
+ }
+ return r;
+}
+
+int msg_thread_deinit(struct msg_thread_ctx *ctx)
+{
+ int r, i;
+ P_OSAL_THREAD p_thraed = &ctx->thread;
+
+ r = osal_thread_stop(p_thraed);
+ if (r) {
+ pr_err("osal_thread_stop(0x%p) fail(%d)\n", p_thraed, r);
+ return -1;
+ }
+
+ for (i = 0; i < MSG_THREAD_OP_BUF_SIZE; i++)
+ osal_signal_deinit(&(ctx->op_q_inst[i].signal));
+
+ osal_sleepable_lock_deinit(&ctx->free_op_q.lock);
+ osal_sleepable_lock_deinit(&ctx->active_op_q.lock);
+
+ r = osal_thread_destroy(p_thraed);
+ if (r) {
+ pr_err("osal_thread_stop(0x%p) fail(%d)\n", p_thraed, r);
+ return -2;
+ }
+
+ osal_memset(ctx, 0, sizeof(struct msg_thread_ctx));
+
+ pr_debug("[%s] DONE\n", __func__);
+ return 0;
+}
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/base/osal.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/base/osal.c
new file mode 100755
index 0000000..ab0d550
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/base/osal.c
@@ -0,0 +1,1630 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+/*! \file
+ * \brief Declaration of library functions
+ * Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+ */
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/kallsyms.h>
+#include <linux/trace_events.h>
+#include <linux/kthread.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <asm/current.h>
+#include <linux/kfifo.h>
+#include "connectivity_build_in_adapter.h"
+#include "osal.h"
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+#define GPIO_ASSERT 70
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+int ftrace_flag = 1;
+
+static unsigned long __read_mostly mark_addr;
+static unsigned int g_pid;
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+/*string operations*/
+unsigned int osal_strlen(const char *str)
+{
+ return strlen(str);
+}
+
+int osal_strcmp(const char *dst, const char *src)
+{
+ return strcmp(dst, src);
+}
+
+int osal_strncmp(const char *dst, const char *src, unsigned int len)
+{
+ return strncmp(dst, src, len);
+}
+
+char *osal_strcpy(char *dst, const char *src)
+{
+ return strncpy(dst, src, strlen(src)+1);
+}
+
+char *osal_strncpy(char *dst, const char *src, unsigned int len)
+{
+ return strncpy(dst, src, len);
+}
+
+char *osal_strcat(char *dst, const char *src)
+{
+ return strncat(dst, src, strlen(src));
+}
+
+char *osal_strncat(char *dst, const char *src, unsigned int len)
+{
+ return strncat(dst, src, len);
+}
+
+char *osal_strchr(const char *str, unsigned char c)
+{
+ return strchr(str, c);
+}
+
+char *osal_strsep(char **str, const char *c)
+{
+ return strsep(str, c);
+}
+
+int 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);
+}
+
+char *osal_strstr(char *str1, const char *str2)
+{
+ return strstr(str1, str2);
+}
+
+char *osal_strnstr(char *str1, const char *str2, int n)
+{
+ return strnstr(str1, str2, n);
+}
+
+void osal_bug_on(unsigned int val)
+{
+ WARN_ON(val);
+}
+
+int osal_snprintf(char *buf, unsigned int len, const char *fmt, ...)
+{
+ int iRet = 0;
+ va_list args;
+
+ /*va_start(args, fmt); */
+ va_start(args, fmt);
+ /*iRet = snprintf(buf, len, fmt, args); */
+ iRet = vsnprintf(buf, len, fmt, args);
+ va_end(args);
+
+ return iRet;
+}
+
+int osal_sprintf(char *str, const char *format, ...)
+{
+ int iRet = 0;
+ va_list args;
+
+ va_start(args, format);
+ iRet = vsnprintf(str, DBG_LOG_STR_SIZE, format, args);
+ va_end(args);
+
+ return iRet;
+}
+
+void *osal_malloc(unsigned int size)
+{
+ return vmalloc(size);
+}
+
+void osal_free(const void *dst)
+{
+ vfree(dst);
+}
+
+void *osal_memset(void *buf, int i, unsigned int len)
+{
+ return memset(buf, i, len);
+}
+
+void *osal_memcpy(void *dst, const void *src, unsigned int len)
+{
+ return memcpy(dst, src, len);
+}
+
+void osal_memcpy_fromio(void *dst, const void *src, unsigned int len)
+{
+ return memcpy_fromio(dst, src, len);
+}
+
+void osal_memcpy_toio(void *dst, const void *src, unsigned int len)
+{
+ return memcpy_toio(dst, src, len);
+}
+
+int osal_memcmp(const void *buf1, const void *buf2, unsigned int len)
+{
+ return memcmp(buf1, buf2, len);
+}
+
+void osal_dump_thread_state(const unsigned char *name)
+{
+ return connectivity_export_dump_thread_state(name);
+}
+
+static inline bool __osal_is_valid_thread(P_OSAL_THREAD pThread)
+{
+ if ((pThread) && !IS_ERR_OR_NULL(pThread->pThread))
+ return true;
+ else
+ return false;
+}
+
+void osal_thread_show_stack(P_OSAL_THREAD pThread)
+{
+ if (__osal_is_valid_thread(pThread))
+ KERNEL_show_stack(pThread->pThread, NULL);
+}
+
+/*
+ * OSAL layer Thread Opeartion related APIs
+ *
+ */
+int osal_thread_create(P_OSAL_THREAD pThread)
+{
+ struct task_struct *task;
+
+ if (!pThread)
+ return -1;
+
+ task = kthread_create(pThread->pThreadFunc,
+ pThread->pThreadData, pThread->threadName);
+ if (IS_ERR(task)) {
+ pr_err("[%s] create %s thread fail", __func__, pThread->threadName);
+ return -1;
+ }
+
+ pThread->pThread = task;
+ return 0;
+}
+
+int osal_thread_run(P_OSAL_THREAD pThread)
+{
+ if (__osal_is_valid_thread(pThread)) {
+ wake_up_process(pThread->pThread);
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+int osal_thread_stop(P_OSAL_THREAD pThread)
+{
+ int iRet;
+
+ if (__osal_is_valid_thread(pThread)) {
+ iRet = kthread_stop(pThread->pThread);
+ pThread->pThread = NULL;
+ return iRet;
+ }
+ return -1;
+}
+
+int osal_thread_should_stop(P_OSAL_THREAD pThread)
+{
+ if (__osal_is_valid_thread(pThread))
+ return kthread_should_stop();
+ else
+ return 1;
+
+}
+
+int osal_thread_wait_for_event(P_OSAL_THREAD pThread,
+ P_OSAL_EVENT pEvent, P_OSAL_EVENT_CHECKER pChecker)
+{
+ /* P_DEV_WMT pDevWmt;*/
+
+ if (__osal_is_valid_thread(pThread) && (pEvent) && (pChecker)) {
+ return wait_event_interruptible(pEvent->waitQueue, (
+ osal_thread_should_stop(pThread)
+ || (*pChecker) (pThread)));
+ }
+ return -1;
+}
+
+int osal_thread_destroy(P_OSAL_THREAD pThread)
+{
+ if (__osal_is_valid_thread(pThread)) {
+ kthread_stop(pThread->pThread);
+ pThread->pThread = NULL;
+ }
+ return 0;
+}
+
+/*
+ * osal_thread_sched_retrieve
+ * Retrieve thread's current scheduling statistics and stored in output "sched".
+ * Return value:
+ * 0 : Schedstats successfully retrieved
+ * -1 : Kernel's schedstats feature not enabled
+ * -2 : pThread not yet initialized or sched is a NULL pointer
+ */
+static int osal_thread_sched_retrieve(P_OSAL_THREAD pThread,
+ P_OSAL_THREAD_SCHEDSTATS sched)
+{
+#ifdef CONFIG_SCHEDSTATS
+ struct sched_entity se;
+ unsigned long long sec;
+ unsigned long usec;
+
+ if (!sched)
+ return -2;
+
+ /* always clear sched to simplify error handling at caller side */
+ memset(sched, 0, sizeof(OSAL_THREAD_SCHEDSTATS));
+
+ if (!__osal_is_valid_thread(pThread))
+ return -2;
+
+ memcpy(&se, &pThread->pThread->se, sizeof(struct sched_entity));
+ osal_get_local_time(&sec, &usec);
+
+ sched->time = sec*1000 + usec/1000;
+ sched->exec = se.sum_exec_runtime;
+ sched->runnable = se.statistics.wait_sum;
+ sched->iowait = se.statistics.iowait_sum;
+
+ return 0;
+#else
+ /* always clear sched to simplify error handling at caller side */
+ if (sched)
+ memset(sched, 0, sizeof(OSAL_THREAD_SCHEDSTATS));
+ return -1;
+#endif
+}
+
+/*
+ * osal_thread_sched_mark
+ * Record the thread's current schedstats and stored
+ * in output "schedstats" parameter for profiling at
+ * later time.
+ * Return value:
+ * 0 : Schedstats successfully recorded
+ * -1 : Kernel's schedstats feature not enabled
+ * -2 : pThread not yet initialized or invalid parameters
+ */
+int osal_thread_sched_mark(P_OSAL_THREAD pThread,
+ P_OSAL_THREAD_SCHEDSTATS schedstats)
+{
+ return osal_thread_sched_retrieve(pThread, schedstats);
+}
+
+/*
+ * osal_thread_sched_unmark
+ * Calculate scheduling statistics against the previously marked point.
+ * The result will be filled back into the schedstats output parameter.
+ * Return value:
+ * 0 : Schedstats successfully calculated
+ * -1 : Kernel's schedstats feature not enabled
+ * -2 : pThread not yet initialized or invalid parameters
+ */
+int osal_thread_sched_unmark(P_OSAL_THREAD pThread,
+ P_OSAL_THREAD_SCHEDSTATS schedstats)
+{
+ int ret;
+ OSAL_THREAD_SCHEDSTATS sched_now;
+
+ if (unlikely(!schedstats)) {
+ ret = -2;
+ } else {
+ ret = osal_thread_sched_retrieve(pThread, &sched_now);
+ if (ret == 0) {
+ schedstats->time = sched_now.time - schedstats->time;
+ schedstats->exec = sched_now.exec - schedstats->exec;
+ schedstats->runnable =
+ sched_now.runnable - schedstats->runnable;
+ schedstats->iowait =
+ sched_now.iowait - schedstats->iowait;
+ }
+ }
+ return ret;
+}
+
+/*
+ * OSAL layer Signal Opeartion related APIs
+ * initialization
+ * wait for signal
+ * wait for signal timerout
+ * raise signal
+ * destroy a signal
+ *
+ */
+
+int osal_signal_init(P_OSAL_SIGNAL pSignal)
+{
+ if (pSignal) {
+ init_completion(&pSignal->comp);
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+int osal_wait_for_signal(P_OSAL_SIGNAL pSignal)
+{
+ if (pSignal) {
+ wait_for_completion_interruptible(&pSignal->comp);
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+/*
+ * 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 osal_wait_for_signal_timeout(P_OSAL_SIGNAL pSignal, P_OSAL_THREAD pThread)
+{
+ OSAL_THREAD_SCHEDSTATS schedstats;
+ int waitRet;
+
+ /* [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));
+
+ 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) {
+ pr_err(
+ "[E]%s:wait completion timeout, %s cannot get CPU, extension(%d), show backtrace:\n",
+ __func__,
+ pThread->threadName,
+ pSignal->timeoutExtension);
+ } else {
+ pr_err(
+ "[E]%s:wait completion timeout, show %s backtrace:\n",
+ __func__,
+ pThread->threadName);
+ pSignal->timeoutExtension = 0;
+ }
+ pr_err(
+ "[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("mtk_wmtd_worker");
+ 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;
+}
+
+int osal_raise_signal(P_OSAL_SIGNAL pSignal)
+{
+ if (pSignal) {
+ complete(&pSignal->comp);
+ return 0;
+ } else
+ return -1;
+}
+
+int osal_signal_active_state(P_OSAL_SIGNAL pSignal)
+{
+ if (pSignal)
+ return pSignal->timeoutValue;
+ else
+ return -1;
+}
+
+int osal_signal_deinit(P_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 osal_event_init(P_OSAL_EVENT pEvent)
+{
+ if (pEvent) {
+ init_waitqueue_head(&pEvent->waitQueue);
+ return 0;
+ }
+ return -1;
+}
+
+int osal_trigger_event(P_OSAL_EVENT pEvent)
+{
+ int ret = 0;
+
+ if (pEvent) {
+ wake_up_interruptible(&pEvent->waitQueue);
+ return ret;
+ }
+ return -1;
+}
+
+int osal_wait_for_event(P_OSAL_EVENT pEvent,
+ int (*condition)(void *), void *cond_pa)
+{
+ if (pEvent)
+ return wait_event_interruptible(pEvent->waitQueue,
+ condition(cond_pa));
+ else
+ return -1;
+}
+
+int osal_wait_for_event_timeout(P_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 osal_event_deinit(P_OSAL_EVENT pEvent)
+{
+ return 0;
+}
+
+long osal_wait_for_event_bit_set(P_OSAL_EVENT pEvent,
+ unsigned long *pState, unsigned int bitOffset)
+{
+ unsigned int ms = 0;
+
+ if (pEvent) {
+ ms = pEvent->timeoutValue;
+ if (ms != 0)
+ return wait_event_interruptible_timeout(
+ pEvent->waitQueue,
+ test_bit(bitOffset, pState),
+ msecs_to_jiffies(ms));
+ else
+ return wait_event_interruptible(pEvent->waitQueue,
+ test_bit(bitOffset, pState));
+ } else
+ return -1;
+
+}
+
+long osal_wait_for_event_bit_clr(P_OSAL_EVENT pEvent,
+ unsigned long *pState, unsigned int bitOffset)
+{
+ unsigned int ms = 0;
+
+ if (pEvent) {
+ ms = pEvent->timeoutValue;
+ if (ms != 0)
+ return wait_event_interruptible_timeout(
+ pEvent->waitQueue,
+ !test_bit(bitOffset, pState),
+ msecs_to_jiffies(ms));
+ else
+ return wait_event_interruptible(pEvent->waitQueue,
+ !test_bit(bitOffset, pState));
+ } else
+ return -1;
+}
+
+/*
+ * bit test and set/clear operations APIs
+ */
+#if OS_BIT_OPS_SUPPORT
+#define osal_bit_op_lock(x)
+#define osal_bit_op_unlock(x)
+#else
+
+int osal_bit_op_lock(P_OSAL_UNSLEEPABLE_LOCK pLock)
+{
+
+ return 0;
+}
+
+int osal_bit_op_unlock(P_OSAL_UNSLEEPABLE_LOCK pLock)
+{
+
+ return 0;
+}
+#endif
+int osal_clear_bit(unsigned int bitOffset, P_OSAL_BIT_OP_VAR pData)
+{
+ osal_bit_op_lock(&(pData->opLock));
+ clear_bit(bitOffset, &pData->data);
+ osal_bit_op_unlock(&(pData->opLock));
+ return 0;
+}
+
+int osal_set_bit(unsigned int bitOffset, P_OSAL_BIT_OP_VAR pData)
+{
+ osal_bit_op_lock(&(pData->opLock));
+ set_bit(bitOffset, &pData->data);
+ osal_bit_op_unlock(&(pData->opLock));
+ return 0;
+}
+
+int osal_test_bit(unsigned int bitOffset, P_OSAL_BIT_OP_VAR pData)
+{
+ unsigned int iRet = 0;
+
+ osal_bit_op_lock(&(pData->opLock));
+ iRet = test_bit(bitOffset, &pData->data);
+ osal_bit_op_unlock(&(pData->opLock));
+ return iRet;
+}
+
+int osal_test_and_clear_bit(unsigned int bitOffset, P_OSAL_BIT_OP_VAR pData)
+{
+ unsigned int iRet = 0;
+
+ osal_bit_op_lock(&(pData->opLock));
+ iRet = test_and_clear_bit(bitOffset, &pData->data);
+ osal_bit_op_unlock(&(pData->opLock));
+ return iRet;
+
+}
+
+int osal_test_and_set_bit(unsigned int bitOffset, P_OSAL_BIT_OP_VAR pData)
+{
+ unsigned int iRet = 0;
+
+ osal_bit_op_lock(&(pData->opLock));
+ iRet = test_and_set_bit(bitOffset, &pData->data);
+ osal_bit_op_unlock(&(pData->opLock));
+ return iRet;
+}
+
+int _osal_fifo_init(OSAL_FIFO *pFifo, unsigned char *buf, unsigned int size)
+{
+ struct kfifo *fifo = NULL;
+ int ret = -1;
+
+ if (!pFifo) {
+ pr_err("pFifo must be !NULL\n");
+ return -1;
+ }
+ if (pFifo->pFifoBody) {
+ pr_err("pFifo->pFifoBody must be NULL\n");
+ pr_err("pFifo(0x%p), pFifo->pFifoBody(0x%p)\n",
+ pFifo, pFifo->pFifoBody);
+ return -1;
+ }
+ fifo = kzalloc(sizeof(struct kfifo), GFP_ATOMIC);
+ if (!buf) {
+ /*fifo's buffer is not ready, we allocate automatically */
+ ret = kfifo_alloc(fifo, size, /*GFP_KERNEL */ GFP_ATOMIC);
+ } else {
+ if (is_power_of_2(size)) {
+ kfifo_init(fifo, buf, size);
+ ret = 0;
+ } else {
+ kfree(fifo);
+ fifo = NULL;
+ ret = -1;
+ }
+ }
+
+ pFifo->pFifoBody = fifo;
+ return (ret < 0) ? (-1) : (0);
+}
+
+int _osal_fifo_deinit(OSAL_FIFO *pFifo)
+{
+ struct kfifo *fifo = NULL;
+
+ if (!pFifo || !pFifo->pFifoBody) {
+ pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n",
+ __func__);
+ return -1;
+ }
+
+ fifo = (struct kfifo *)pFifo->pFifoBody;
+
+ if (fifo)
+ kfifo_free(fifo);
+
+ return 0;
+}
+
+int _osal_fifo_size(OSAL_FIFO *pFifo)
+{
+ struct kfifo *fifo = NULL;
+ int ret = 0;
+
+ if (!pFifo || !pFifo->pFifoBody) {
+ pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n",
+ __func__);
+ return -1;
+ }
+
+ fifo = (struct kfifo *)pFifo->pFifoBody;
+
+ if (fifo)
+ ret = kfifo_size(fifo);
+
+ return ret;
+}
+
+/*returns unused bytes in fifo*/
+int _osal_fifo_avail_size(OSAL_FIFO *pFifo)
+{
+ struct kfifo *fifo = NULL;
+ int ret = 0;
+
+ if (!pFifo || !pFifo->pFifoBody) {
+ pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n",
+ __func__);
+ return -1;
+ }
+
+ fifo = (struct kfifo *)pFifo->pFifoBody;
+
+ if (fifo)
+ ret = kfifo_avail(fifo);
+
+ return ret;
+}
+
+/*returns used bytes in fifo*/
+int _osal_fifo_len(OSAL_FIFO *pFifo)
+{
+ struct kfifo *fifo = NULL;
+ int ret = 0;
+
+ if (!pFifo || !pFifo->pFifoBody) {
+ pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n",
+ __func__);
+ return -1;
+ }
+
+ fifo = (struct kfifo *)pFifo->pFifoBody;
+
+ if (fifo)
+ ret = kfifo_len(fifo);
+
+ return ret;
+}
+
+int _osal_fifo_is_empty(OSAL_FIFO *pFifo)
+{
+ struct kfifo *fifo = NULL;
+ int ret = 0;
+
+ if (!pFifo || !pFifo->pFifoBody) {
+ pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n",
+ __func__);
+ return -1;
+ }
+
+ fifo = (struct kfifo *)pFifo->pFifoBody;
+
+ if (fifo)
+ ret = kfifo_is_empty(fifo);
+
+ return ret;
+}
+
+int _osal_fifo_is_full(OSAL_FIFO *pFifo)
+{
+ struct kfifo *fifo = NULL;
+ int ret = 0;
+
+ if (!pFifo || !pFifo->pFifoBody) {
+ pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n",
+ __func__);
+ return -1;
+ }
+
+ fifo = (struct kfifo *)pFifo->pFifoBody;
+
+ if (fifo)
+ ret = kfifo_is_full(fifo);
+
+ return ret;
+}
+
+int _osal_fifo_data_in(OSAL_FIFO *pFifo, const void *buf, unsigned int len)
+{
+ struct kfifo *fifo = NULL;
+ int ret = 0;
+
+ if (!pFifo || !pFifo->pFifoBody) {
+ pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n",
+ __func__);
+ return -1;
+ }
+
+ fifo = (struct kfifo *)pFifo->pFifoBody;
+
+ if (fifo && buf && (len <= _osal_fifo_avail_size(pFifo))) {
+ ret = kfifo_in(fifo, buf, len);
+ } else {
+ pr_err("%s: kfifo_in, error, len = %d, _osal_fifo_avail_size = %d, buf=%p\n",
+ __func__, len, _osal_fifo_avail_size(pFifo), buf);
+
+ ret = 0;
+ }
+
+ return ret;
+}
+
+int _osal_fifo_data_out(OSAL_FIFO *pFifo, void *buf, unsigned int len)
+{
+ struct kfifo *fifo = NULL;
+ int ret = 0;
+
+ if (!pFifo || !pFifo->pFifoBody) {
+ pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n"
+ , __func__);
+ return -1;
+ }
+
+ fifo = (struct kfifo *)pFifo->pFifoBody;
+
+ if (fifo && buf && (len <= _osal_fifo_len(pFifo))) {
+ ret = kfifo_out(fifo, buf, len);
+ } else {
+ pr_err("%s: kfifo_out, error, len = %d, osal_fifo_len = %d, buf=%p\n",
+ __func__, len, _osal_fifo_len(pFifo), buf);
+
+ ret = 0;
+ }
+
+ return ret;
+}
+
+int _osal_fifo_reset(OSAL_FIFO *pFifo)
+{
+ struct kfifo *fifo = NULL;
+
+ if (!pFifo || !pFifo->pFifoBody) {
+ pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n",
+ __func__);
+ return -1;
+ }
+
+ fifo = (struct kfifo *)pFifo->pFifoBody;
+
+ if (fifo)
+ kfifo_reset(fifo);
+
+ return 0;
+}
+
+int osal_fifo_init(P_OSAL_FIFO pFifo, unsigned char *buffer, unsigned int size)
+{
+ if (!pFifo) {
+ pr_err("%s:pFifo = NULL, error\n", __func__);
+ return -1;
+ }
+
+ pFifo->FifoInit = _osal_fifo_init;
+ pFifo->FifoDeInit = _osal_fifo_deinit;
+ pFifo->FifoSz = _osal_fifo_size;
+ pFifo->FifoAvailSz = _osal_fifo_avail_size;
+ pFifo->FifoLen = _osal_fifo_len;
+ pFifo->FifoIsEmpty = _osal_fifo_is_empty;
+ pFifo->FifoIsFull = _osal_fifo_is_full;
+ pFifo->FifoDataIn = _osal_fifo_data_in;
+ pFifo->FifoDataOut = _osal_fifo_data_out;
+ pFifo->FifoReset = _osal_fifo_reset;
+
+ if (pFifo->pFifoBody != NULL) {
+ pr_err("%s:Because pFifo room is avialable, we clear the room and allocate them again.\n", __func__);
+ pFifo->FifoDeInit(pFifo->pFifoBody);
+ pFifo->pFifoBody = NULL;
+ }
+
+ pFifo->FifoInit(pFifo, buffer, size);
+
+ return 0;
+}
+
+void osal_fifo_deinit(P_OSAL_FIFO pFifo)
+{
+ if (pFifo)
+ pFifo->FifoDeInit(pFifo);
+ else {
+ pr_err("%s:pFifo = NULL, error\n", __func__);
+ return;
+ }
+ kfree(pFifo->pFifoBody);
+}
+
+int osal_fifo_reset(P_OSAL_FIFO pFifo)
+{
+ int ret = -1;
+
+ if (pFifo) {
+ ret = pFifo->FifoReset(pFifo);
+ } else {
+ pr_err("%s:pFifo = NULL, error\n", __func__);
+ ret = -1;
+ }
+ return ret;
+}
+
+unsigned int osal_fifo_in(P_OSAL_FIFO pFifo,
+ unsigned char *buffer, unsigned int size)
+{
+ unsigned int ret = 0;
+
+ if (pFifo) {
+ ret = pFifo->FifoDataIn(pFifo, buffer, size);
+ } else {
+ pr_err("%s:pFifo = NULL, error\n", __func__);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+unsigned int osal_fifo_out(P_OSAL_FIFO pFifo,
+ unsigned char *buffer, unsigned int size)
+{
+ unsigned int ret = 0;
+
+ if (pFifo) {
+ ret = pFifo->FifoDataOut(pFifo, buffer, size);
+ } else {
+ pr_err("%s:pFifo = NULL, error\n", __func__);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+unsigned int osal_fifo_len(P_OSAL_FIFO pFifo)
+{
+ unsigned int ret = 0;
+
+ if (pFifo) {
+ ret = pFifo->FifoLen(pFifo);
+ } else {
+ pr_err("%s:pFifo = NULL, error\n", __func__);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+unsigned int osal_fifo_sz(P_OSAL_FIFO pFifo)
+{
+ unsigned int ret = 0;
+
+ if (pFifo) {
+ ret = pFifo->FifoSz(pFifo);
+ } else {
+ pr_err("%s:pFifo = NULL, error\n", __func__);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+unsigned int osal_fifo_avail(P_OSAL_FIFO pFifo)
+{
+ unsigned int ret = 0;
+
+ if (pFifo) {
+ ret = pFifo->FifoAvailSz(pFifo);
+ } else {
+ pr_err("%s:pFifo = NULL, error\n", __func__);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+unsigned int osal_fifo_is_empty(P_OSAL_FIFO pFifo)
+{
+ unsigned int ret = 0;
+
+ if (pFifo) {
+ ret = pFifo->FifoIsEmpty(pFifo);
+ } else {
+ pr_err("%s:pFifo = NULL, error\n", __func__);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+unsigned int osal_fifo_is_full(P_OSAL_FIFO pFifo)
+{
+ unsigned int ret = 0;
+
+ if (pFifo) {
+ ret = pFifo->FifoIsFull(pFifo);
+ } else {
+ pr_err("%s:pFifo = NULL, error\n", __func__);
+ ret = 0;
+ }
+ return ret;
+}
+
+/*
+ * sleepable lock operations APIs
+ * init
+ * lock
+ * unlock
+ * destroy
+ *
+ */
+#if !defined(CONFIG_PROVE_LOCKING)
+int osal_unsleepable_lock_init(P_OSAL_UNSLEEPABLE_LOCK pUSL)
+{
+ spin_lock_init(&(pUSL->lock));
+ return 0;
+}
+#endif
+
+int osal_lock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK pUSL)
+{
+ spin_lock_irqsave(&(pUSL->lock), pUSL->flag);
+ return 0;
+}
+
+int osal_unlock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK pUSL)
+{
+ spin_unlock_irqrestore(&(pUSL->lock), pUSL->flag);
+ return 0;
+}
+
+int osal_unsleepable_lock_deinit(P_OSAL_UNSLEEPABLE_LOCK pUSL)
+{
+ return 0;
+}
+
+/*
+ * unsleepable operations APIs
+ * init
+ * lock
+ * unlock
+ * destroy
+ *
+ */
+
+#if !defined(CONFIG_PROVE_LOCKING)
+int osal_sleepable_lock_init(P_OSAL_SLEEPABLE_LOCK pSL)
+{
+ mutex_init(&pSL->lock);
+ return 0;
+}
+#endif
+
+int osal_lock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK pSL)
+{
+ return mutex_lock_killable(&pSL->lock);
+}
+
+int osal_unlock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK pSL)
+{
+ mutex_unlock(&pSL->lock);
+ return 0;
+}
+
+int osal_trylock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK pSL)
+{
+ return mutex_trylock(&pSL->lock);
+}
+
+int osal_sleepable_lock_deinit(P_OSAL_SLEEPABLE_LOCK pSL)
+{
+ mutex_destroy(&pSL->lock);
+ return 0;
+}
+
+int osal_sleep_ms(unsigned int ms)
+{
+ msleep(ms);
+ return 0;
+}
+
+int osal_udelay(unsigned int us)
+{
+ udelay(us);
+ return 0;
+}
+
+int osal_usleep_range(unsigned long min, unsigned long max)
+{
+ usleep_range(min, max);
+ return 0;
+}
+
+int osal_gettimeofday(int *sec, int *usec)
+{
+ int ret = 0;
+ struct timeval now;
+
+ do_gettimeofday(&now);
+
+ if (sec != NULL)
+ *sec = now.tv_sec;
+ else
+ ret = -1;
+
+ if (usec != NULL)
+ *usec = now.tv_usec;
+ else
+ ret = -1;
+
+ return ret;
+}
+
+void osal_get_local_time(unsigned long long *sec, unsigned long *nsec)
+{
+ if (sec != NULL && nsec != NULL) {
+ *sec = local_clock();
+ *nsec = do_div(*sec, 1000000000)/1000;
+ } else
+ pr_err("The input parameters error when get local time\n");
+}
+
+unsigned long long osal_elapsed_us(unsigned long long ts, unsigned long usec)
+{
+ unsigned long long current_ts = 0;
+ unsigned long current_usec = 0;
+
+ osal_get_local_time(¤t_ts, ¤t_usec);
+ return (current_ts*1000000 + current_usec) - (ts*1000000 + usec);
+}
+
+void osal_buffer_dump(const unsigned char *buf,
+ const unsigned char *title, const unsigned int len,
+ const unsigned int limit)
+{
+ int k;
+ unsigned int dump_len;
+ char str[DBG_LOG_STR_SIZE] = {""};
+ int strlen = 0;
+
+ pr_info("[%s] len=%d, limit=%d, start dump\n", title, len, limit);
+
+ dump_len = ((limit != 0) && (len > limit)) ? limit : len;
+ for (k = 0; k < dump_len; k++) {
+ if ((k+1) % 16 != 0) {
+ strlen += osal_snprintf(str + strlen, DBG_LOG_STR_SIZE - strlen,
+ "%02x ", buf[k]);
+ } else {
+ strlen += osal_snprintf(str + strlen, DBG_LOG_STR_SIZE - strlen,
+ "%02x ", buf[k]);
+
+ pr_info("%s", str);
+ strlen = 0;
+ }
+ }
+ if (k % 16 != 0)
+ pr_info("%s\n", str);
+
+ pr_info("end of dump\n");
+}
+
+void osal_buffer_dump_data(const unsigned int *buf,
+ const unsigned char *title, const unsigned int len,
+ const unsigned int limit,
+ const int flag)
+{
+ int k;
+ unsigned int dump_len;
+ char str[DBG_LOG_STR_SIZE] = {""};
+ int strlen = 0;
+
+ dump_len = ((limit != 0) && (len > limit)) ? limit : len;
+ for (k = 0; k < dump_len; k++) {
+ if (((k+1) % 8 != 0) && (k < (dump_len - 1))) {
+ strlen += osal_snprintf(str + strlen, DBG_LOG_STR_SIZE - strlen,
+ "0x%08x,", buf[k]);
+ } else {
+ strlen += osal_snprintf(str + strlen, DBG_LOG_STR_SIZE - strlen,
+ "0x%08x,", buf[k]);
+ if (flag)
+ osal_ftrace_print("%s%s", title, str);
+ else
+ pr_info("%s%s", title, str);
+ strlen = 0;
+ }
+ }
+ if (k % 8 != 0) {
+ if (flag)
+ osal_ftrace_print("%s%s", title, str);
+ else
+ pr_info("%s%s", title, str);
+ }
+}
+
+unsigned int osal_op_get_id(P_OSAL_OP pOp)
+{
+ return (pOp) ? pOp->op.opId : 0xFFFFFFFF;
+}
+
+MTK_CONN_BOOL osal_op_is_wait_for_signal(P_OSAL_OP pOp)
+{
+ return (pOp && pOp->signal.timeoutValue)
+ ? MTK_CONN_BOOL_TRUE : MTK_CONN_BOOL_FALSE;
+}
+
+void osal_op_raise_signal(P_OSAL_OP pOp, int result)
+{
+ if (pOp) {
+ pOp->result = result;
+ osal_raise_signal(&pOp->signal);
+ }
+}
+
+int osal_ftrace_print(const char *str, ...)
+{
+#ifdef CONFIG_TRACING
+ va_list args;
+ char tempString[DBG_LOG_STR_SIZE];
+
+ if (ftrace_flag) {
+ va_start(args, str);
+ vsnprintf(tempString, DBG_LOG_STR_SIZE, str, args);
+ va_end(args);
+
+ trace_printk("%s\n", tempString);
+ }
+#endif
+ return 0;
+}
+
+int osal_ftrace_print_ctrl(int flag)
+{
+#ifdef CONFIG_TRACING
+ if (flag)
+ ftrace_flag = 1;
+ else
+ ftrace_flag = 0;
+#endif
+ return 0;
+}
+
+void osal_set_op_result(P_OSAL_OP pOp, int result)
+{
+ if (pOp)
+ pOp->result = result;
+
+}
+
+static void _osal_opq_dump(const char *qName, P_OSAL_OP_Q pOpQ)
+{
+ /* Line format:
+ * [LogicalIdx(PhysicalIdx)]Address:OpId(Ref)(Result)-Info-OpData0,OpData1,OpData2,OpData3,OpData5_
+ * [LogicalIdx] max 10+2=12 chars (decimal)
+ * (PhysicalIdx) max 10+2=12 chars (decimal)
+ * Address: max 16+1=17 chars (hex)
+ * OpId max 10 chars (decimal)
+ * (Ref) max 2+2=4 chars (should only be 1 digit, reserve 2 in case of negative number)
+ * (Result) max 11+2=13 chars (signed decimal)
+ * -Info- max 8+2=10 chars (hex)
+ * OpData, max 16+1=17 chars (hex)
+ */
+#define OPQ_DUMP_OP_PER_LINE 1
+#define OPQ_DUMP_OPDATA_PER_OP 6
+#define OPQ_DUMP_OP_BUF_SIZE (12 + 12 + 17 + 10 + 4 + 13 + 10 + (17 * (OPQ_DUMP_OPDATA_PER_OP)) + 1)
+#define OPQ_DUMP_LINE_BUF_SIZE ((OPQ_DUMP_OP_BUF_SIZE * OPQ_DUMP_OP_PER_LINE) + 1)
+ unsigned int rd;
+ unsigned int wt;
+ unsigned int idx = 0;
+ unsigned int opDataIdx;
+ unsigned int idxInBuf;
+ int printed;
+ P_OSAL_OP op;
+ char buf[OPQ_DUMP_LINE_BUF_SIZE];
+
+ rd = pOpQ->read;
+ wt = pOpQ->write;
+
+ pr_info("%s(%p), sz:%u/%u, rd:%u, wt:%u\n",
+ qName, pOpQ, RB_COUNT(pOpQ), RB_SIZE(pOpQ), rd, wt);
+ while (rd != wt && idx < RB_SIZE(pOpQ)) {
+ idxInBuf = idx % OPQ_DUMP_OP_PER_LINE;
+ op = pOpQ->queue[rd & RB_MASK(pOpQ)];
+
+ if (idxInBuf == 0) {
+ printed = 0;
+ buf[0] = 0;
+ }
+
+ if (op) {
+ printed += snprintf(buf + printed, OPQ_DUMP_LINE_BUF_SIZE - printed,
+ "[%u(%u)]%p:%u(%d)(%d)-%u-",
+ idx,
+ (rd & RB_MASK(pOpQ)),
+ op,
+ op->op.opId,
+ atomic_read(&op->ref_count),
+ op->result,
+ op->op.u4InfoBit);
+ for (opDataIdx = 0; opDataIdx < OPQ_DUMP_OPDATA_PER_OP; opDataIdx++)
+ printed += snprintf(buf + printed, OPQ_DUMP_LINE_BUF_SIZE - printed,
+ "%zx,", op->op.au4OpData[opDataIdx]);
+ buf[printed-1] = ' ';
+ } else {
+ printed += snprintf(buf + printed, OPQ_DUMP_LINE_BUF_SIZE - printed,
+ "[%u(%u)]%p ", idx, (rd & RB_MASK(pOpQ)), op);
+ }
+ buf[printed++] = ' ';
+
+ if (idxInBuf == OPQ_DUMP_OP_PER_LINE - 1 || rd == wt - 1) {
+ buf[printed - 1] = 0;
+ pr_info("%s\n", buf);
+ }
+ rd++;
+ idx++;
+ }
+}
+
+void osal_opq_dump(const char *qName, P_OSAL_OP_Q pOpQ)
+{
+ int err;
+
+ err = osal_lock_sleepable_lock(&pOpQ->sLock);
+ if (err) {
+ pr_info("Failed to lock queue (%d)\n", err);
+ return;
+ }
+
+ _osal_opq_dump(qName, pOpQ);
+
+ osal_unlock_sleepable_lock(&pOpQ->sLock);
+}
+
+void osal_opq_dump_locked(const char *qName, P_OSAL_OP_Q pOpQ)
+{
+ _osal_opq_dump(qName, pOpQ);
+}
+
+MTK_CONN_BOOL osal_opq_has_op(P_OSAL_OP_Q pOpQ, P_OSAL_OP pOp)
+{
+ unsigned int rd;
+ unsigned int wt;
+ P_OSAL_OP op;
+
+ rd = pOpQ->read;
+ wt = pOpQ->write;
+
+ while (rd != wt) {
+ op = pOpQ->queue[rd & RB_MASK(pOpQ)];
+ if (op == pOp)
+ return MTK_CONN_BOOL_TRUE;
+ rd++;
+ }
+ return MTK_CONN_BOOL_FALSE;
+}
+
+static void osal_op_history_print_work(struct work_struct *work)
+{
+ struct osal_op_history *log_history
+ = container_of(work, struct osal_op_history, dump_work);
+ struct ring *ring_buffer = &log_history->dump_ring_buffer;
+ struct ring_segment seg;
+ struct osal_op_history_entry *queue = ring_buffer->base;
+ struct osal_op_history_entry *entry;
+ int index = 0;
+
+ if (queue == NULL) {
+ pr_info("queue shouldn't be NULL, %s", log_history->name);
+ return;
+ }
+
+ if (RING_EMPTY(ring_buffer))
+ pr_info("History of %s is empty.\n", log_history->name);
+
+ RING_READ_FOR_EACH_ITEM(RING_SIZE(ring_buffer), seg, ring_buffer) {
+ index = seg.ring_pt - ring_buffer->base;
+ entry = &queue[index];
+ pr_info("(%llu.%06lu) %s: pOp(%p):%u(%d)-%x-%zx,%zx,%zx,%zx\n",
+ entry->ts,
+ entry->usec,
+ log_history->name,
+ entry->opbuf_address,
+ entry->op_id,
+ entry->opbuf_ref_count,
+ entry->op_info_bit,
+ entry->param_0,
+ entry->param_1,
+ entry->param_2,
+ entry->param_3);
+ }
+ kfree(queue);
+ ring_buffer->base = NULL;
+}
+
+void osal_op_history_init(struct osal_op_history *log_history, int queue_size)
+{
+ int size = queue_size * sizeof(struct osal_op_history_entry);
+
+ spin_lock_init(&(log_history->lock));
+
+ log_history->queue = kzalloc(size, GFP_ATOMIC);
+ if (log_history->queue == NULL)
+ return;
+
+ /* queue_size must be power of 2 */
+ ring_init(
+ &log_history->queue,
+ queue_size,
+ 0,
+ 0,
+ &log_history->ring_buffer);
+
+ INIT_WORK(&log_history->dump_work, osal_op_history_print_work);
+}
+
+void osal_op_history_print(struct osal_op_history *log_history, char *name)
+{
+ struct osal_op_history_entry *queue;
+ struct ring *ring_buffer, *dump_ring_buffer;
+ int queue_size;
+ unsigned long flags;
+ struct work_struct *work = &log_history->dump_work;
+ spinlock_t *lock = &(log_history->lock);
+
+ if (log_history->queue == NULL) {
+ pr_info("Queue is NULL, name: %s\n", name);
+ return;
+ }
+
+ ring_buffer = &log_history->ring_buffer;
+ queue_size = sizeof(struct osal_op_history_entry)
+ * RING_SIZE(ring_buffer);
+
+ /* Allocate memory before getting lock to save time of holding lock */
+ queue = kmalloc(queue_size, GFP_KERNEL);
+ if (queue == NULL)
+ return;
+
+ dump_ring_buffer = &log_history->dump_ring_buffer;
+
+ spin_lock_irqsave(lock, flags);
+ if (dump_ring_buffer->base != NULL) {
+ spin_unlock_irqrestore(lock, flags);
+ kfree(queue);
+ pr_info("print is ongoing: %s\n", name);
+ return;
+ }
+
+ osal_snprintf(log_history->name, sizeof(log_history->name), "%s", name);
+ osal_memcpy(queue, log_history->queue, queue_size);
+ osal_memcpy(dump_ring_buffer, ring_buffer, sizeof(struct ring));
+ /* assign value to base after memory copy */
+ dump_ring_buffer->base = queue;
+ spin_unlock_irqrestore(lock, flags);
+ schedule_work(work);
+}
+
+void osal_op_history_save(struct osal_op_history *log_history, P_OSAL_OP pOp)
+{
+ struct osal_op_history_entry *entry = NULL;
+ struct ring_segment seg;
+ int index;
+ unsigned long long sec = 0;
+ unsigned long usec = 0;
+ unsigned long flags;
+
+ if (log_history->queue == NULL)
+ return;
+
+ osal_get_local_time(&sec, &usec);
+
+ spin_lock_irqsave(&(log_history->lock), flags);
+ RING_OVERWRITE_FOR_EACH(1, seg, &log_history->ring_buffer) {
+ index = seg.ring_pt - log_history->ring_buffer.base;
+ entry = &log_history->queue[index];
+ }
+
+ if (entry == NULL) {
+ pr_info("Entry is null, size %d\n",
+ RING_SIZE(&log_history->ring_buffer));
+ spin_unlock_irqrestore(&(log_history->lock), flags);
+ return;
+ }
+
+ entry->opbuf_address = pOp;
+ entry->op_id = pOp->op.opId;
+ entry->opbuf_ref_count = atomic_read(&pOp->ref_count);
+ entry->op_info_bit = pOp->op.u4InfoBit;
+ entry->param_0 = pOp->op.au4OpData[0];
+ entry->param_1 = pOp->op.au4OpData[1];
+ entry->param_2 = pOp->op.au4OpData[2];
+ entry->param_3 = pOp->op.au4OpData[3];
+ entry->ts = sec;
+ entry->usec = usec;
+ spin_unlock_irqrestore(&(log_history->lock), flags);
+}
+
+static inline void osal_systrace_prepare(void)
+{
+ if (unlikely(mark_addr == 0))
+ mark_addr = kallsyms_lookup_name("tracing_mark_write");
+ if (unlikely(g_pid == 0))
+ g_pid = task_pid_nr(current);
+}
+
+static void osal_systrace_b(const char *log)
+{
+ osal_systrace_prepare();
+ preempt_disable();
+ KERNEL_event_trace_printk(mark_addr, "B|%d|%s\n", g_pid, log);
+ preempt_enable();
+}
+
+
+static void osal_systrace_e(void)
+{
+ preempt_disable();
+ KERNEL_event_trace_printk(mark_addr, "E\n");
+ preempt_enable();
+}
+
+static void osal_systrace_c(int val, const char *log)
+{
+ osal_systrace_prepare();
+ preempt_disable();
+ KERNEL_event_trace_printk(mark_addr, "C|%d|%s|%d\n", g_pid, log, val);
+ preempt_enable();
+}
+
+void osal_systrace_major_b(const char *fmt, ...)
+{
+ char log[DBG_LOG_STR_SIZE];
+ va_list args;
+
+ memset(log, ' ', sizeof(log));
+ va_start(args, fmt);
+ vsnprintf(log, sizeof(log), fmt, args);
+ va_end(args);
+ osal_systrace_b(log);
+}
+
+void osal_systrace_major_e(void)
+{
+ osal_systrace_e();
+}
+
+void osal_systrace_minor_b(const char *fmt, ...)
+{
+ char log[DBG_LOG_STR_SIZE];
+ va_list args;
+
+ if (!ftrace_flag)
+ return;
+
+ memset(log, ' ', sizeof(log));
+ va_start(args, fmt);
+ vsnprintf(log, sizeof(log), fmt, args);
+ va_end(args);
+ osal_systrace_b(log);
+
+}
+
+void osal_systrace_minor_e(void)
+{
+ if (!ftrace_flag)
+ return;
+ osal_systrace_e();
+}
+
+void osal_systrace_minor_c(int val, const char *fmt, ...)
+{
+ char log[DBG_LOG_STR_SIZE];
+ va_list args;
+
+ if (!ftrace_flag)
+ return;
+
+ memset(log, ' ', sizeof(log));
+ va_start(args, fmt);
+ vsnprintf(log, sizeof(log), fmt, args);
+ va_end(args);
+ osal_systrace_c(val, log);
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/base/ring.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/base/ring.c
new file mode 100755
index 0000000..e563760
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/base/ring.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2016 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 "ring.h"
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/bug.h>
+
+
+
+void ring_init(void *base, unsigned int max_size, unsigned int read,
+ unsigned int write, struct ring *ring)
+{
+ WARN_ON(!base);
+
+ /* making sure max_size is power of 2 */
+ WARN_ON(!max_size || (max_size & (max_size - 1)));
+
+ /* making sure write largger than read */
+ WARN_ON(read > write);
+
+ ring->base = base;
+ ring->read = read;
+ ring->write = write;
+ ring->max_size = max_size;
+}
+
+void ring_dump(const char *title, struct ring *ring)
+{
+ pr_info("[%s] ring:{write=%d, read=%d, max_size=%d}\n",
+ title, ring->write, ring->read, ring->max_size);
+}
+
+void ring_dump_segment(const char *title, struct ring_segment *seg)
+{
+ pr_info("[%s] seg:{ring_pt=0x%p, data_pos=%d, sz=%d, remain=%d}\n",
+ title, seg->ring_pt, seg->data_pos,
+ seg->sz, seg->remain);
+}
+
+/*
+ * Function prepares the ring_segment and
+ * returns the number of valid bytes for read.
+ */
+unsigned int ring_read_prepare(unsigned int sz,
+ struct ring_segment *seg,
+ struct ring *ring)
+{
+ unsigned int wt = ring->write;
+ unsigned int rd = ring->read;
+
+ memset(seg, 0, sizeof(struct ring_segment));
+ if (sz > wt - rd)
+ sz = wt - rd;
+ seg->remain = sz;
+ /* ring_dump(__func__, ring); */
+ /* ring_dump_segment(__func__, seg); */
+ return seg->remain;
+}
+
+/*
+ * Function prepares the ring_segment and
+ * returns the number of bytes available for write.
+ */
+unsigned int ring_write_prepare(unsigned int sz,
+ struct ring_segment *seg,
+ struct ring *ring)
+{
+ unsigned int wt = ring->write;
+ unsigned int rd = ring->read;
+
+ memset(seg, 0, sizeof(struct ring_segment));
+ if (sz > ring->max_size - (wt - rd))
+ sz = ring->max_size - (wt - rd);
+ seg->remain = sz;
+ /* ring_dump(__func__, ring); */
+ /* ring_dump_segment(__func__, seg); */
+ return seg->remain;
+}
+
+unsigned int ring_overwrite_prepare(unsigned int sz, struct ring_segment *seg,
+ struct ring *ring)
+{
+ unsigned int wt = ring->write;
+ unsigned int rd = ring->read;
+
+ memset(seg, 0, sizeof(struct ring_segment));
+ if (sz > ring->max_size - (wt - rd))
+ ring->read += sz - (ring->max_size - (wt - rd));
+ seg->remain = sz;
+ /* ring_dump(__func__, ring); */
+ /* ring_dump_segment(__func__, seg); */
+ return seg->remain;
+}
+
+void __ring_segment_prepare(unsigned int from, unsigned int sz,
+ struct ring_segment *seg,
+ struct ring *ring)
+{
+ unsigned int ring_pos = from & (ring->max_size - 1);
+
+ seg->ring_pt = ring->base + ring_pos;
+ seg->data_pos = (seg->sz ? seg->data_pos + seg->sz : 0);
+ if (ring_pos + sz <= ring->max_size)
+ seg->sz = sz;
+ else
+ seg->sz = ring->max_size - ring_pos;
+ seg->remain -= seg->sz;
+ /* ring_dump(__func__, ring); */
+ /* ring_dump_segment(__func__, seg); */
+}
+
+void _ring_segment_prepare(unsigned int from,
+ struct ring_segment *seg,
+ struct ring *ring)
+{
+ __ring_segment_prepare(from, seg->remain, seg, ring);
+}
+
+void _ring_segment_prepare_item(unsigned int from,
+ struct ring_segment *seg,
+ struct ring *ring)
+{
+ unsigned int size;
+
+ size = (seg->remain ? 1 : 0);
+ __ring_segment_prepare(from, size, seg, ring);
+}
+
+void _ring_read_commit(struct ring_segment *seg, struct ring *ring)
+{
+ ring->read += seg->sz;
+ /* ring_dump(__func__, ring); */
+ /* ring_dump_segment(__func__, seg); */
+}
+void _ring_write_commit(struct ring_segment *seg, struct ring *ring)
+{
+ ring->write += seg->sz;
+ /* ring_dump(__func__, ring); */
+ /* ring_dump_segment(__func__, seg); */
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/conf/conninfra_conf.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/conf/conninfra_conf.c
new file mode 100755
index 0000000..e333e98
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/conf/conninfra_conf.c
@@ -0,0 +1,634 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__
+
+#include <linux/firmware.h>
+#include "conninfra_conf.h"
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+struct parse_data {
+ char *name;
+ int (*parser)(const struct parse_data *data, const char *value);
+ char *(*writer)(const struct parse_data *data);
+ void (*relase_mem)(const struct parse_data *data);
+ /*PCHAR param1, *param2, *param3; */
+ /* TODO:[FixMe][George] CLARIFY WHAT SHOULD BE USED HERE!!! */
+ char *param1;
+ char *param2;
+ char *param3;
+};
+
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+struct conninfra_conf g_conninfra_conf;
+
+/******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+*******************************************************************************
+*/
+static int conf_parse_char(const struct parse_data *data, const char *pos);
+
+static char *conf_write_char(const struct parse_data *data);
+
+static int conf_parse_short(const struct parse_data *data, const char *pos);
+
+static char *conf_write_short(const struct parse_data *data);
+
+static int conf_parse_int(const struct parse_data *data, const char *pos);
+
+static char *conf_write_int(const struct parse_data *data);
+
+static int conf_parse_byte_array(const struct parse_data *data,
+ const char *pos);
+
+static char *conf_write_byte_array(const struct parse_data *data);
+
+static void conf_release_byte_array(const struct parse_data *data);
+
+static int conf_parse_pair(const char *key, const char *pVal);
+
+static int conf_parse(const char *pInBuf, unsigned int size);
+
+//#define OFFSET(v) ((void *) &((struct conninfra_conf*) 0)->v)
+
+#define CHAR(f) {#f, conf_parse_char, conf_write_char, NULL, (char *)&g_conninfra_conf.f, NULL, NULL}
+
+#define SHORT(f) {#f, conf_parse_short, conf_write_short, NULL, (char *)&g_conninfra_conf.f, NULL, NULL}
+
+#define INT(f) {#f, conf_parse_int, conf_write_int, NULL, (char *)&g_conninfra_conf.f, NULL, NULL}
+
+#define BYTE_ARRAY(f) {#f, conf_parse_byte_array, conf_write_byte_array, conf_release_byte_array,\
+ (char *)&g_conninfra_conf.f, NULL, NULL}
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+static const struct parse_data cfg_fields[] = {
+ CHAR(coex_wmt_ant_mode),
+ CHAR(coex_wmt_ant_mode_ex),
+ CHAR(coex_wmt_ext_component),
+ CHAR(coex_wmt_wifi_time_ctl),
+ CHAR(coex_wmt_ext_pta_dev_on),
+ CHAR(coex_wmt_filter_mode),
+
+ CHAR(coex_bt_rssi_upper_limit),
+ CHAR(coex_bt_rssi_mid_limit),
+ CHAR(coex_bt_rssi_lower_limit),
+ CHAR(coex_bt_pwr_high),
+ CHAR(coex_bt_pwr_mid),
+ CHAR(coex_bt_pwr_low),
+
+ CHAR(coex_wifi_rssi_upper_limit),
+ CHAR(coex_wifi_rssi_mid_limit),
+ CHAR(coex_wifi_rssi_lower_limit),
+ CHAR(coex_wifi_pwr_high),
+ CHAR(coex_wifi_pwr_mid),
+ CHAR(coex_wifi_pwr_low),
+
+ CHAR(coex_ext_pta_hi_tx_tag),
+ CHAR(coex_ext_pta_hi_rx_tag),
+ CHAR(coex_ext_pta_lo_tx_tag),
+ CHAR(coex_ext_pta_lo_rx_tag),
+ SHORT(coex_ext_pta_sample_t1),
+ SHORT(coex_ext_pta_sample_t2),
+ CHAR(coex_ext_pta_wifi_bt_con_trx),
+
+ INT(coex_misc_ext_pta_on),
+ INT(coex_misc_ext_feature_set),
+
+ CHAR(wmt_gps_lna_pin),
+ CHAR(wmt_gps_lna_enable),
+
+ CHAR(pwr_on_rtc_slot),
+ CHAR(pwr_on_ldo_slot),
+ CHAR(pwr_on_rst_slot),
+ CHAR(pwr_on_off_slot),
+ CHAR(pwr_on_on_slot),
+ CHAR(co_clock_flag),
+
+ CHAR(disable_deep_sleep_cfg),
+
+ INT(sdio_driving_cfg),
+
+ SHORT(coex_wmt_wifi_path),
+
+ CHAR(coex_wmt_ext_elna_gain_p1_support),
+ INT(coex_wmt_ext_elna_gain_p1_D0),
+ INT(coex_wmt_ext_elna_gain_p1_D1),
+ INT(coex_wmt_ext_elna_gain_p1_D2),
+ INT(coex_wmt_ext_elna_gain_p1_D3),
+
+ BYTE_ARRAY(coex_wmt_epa_elna),
+
+ CHAR(bt_tssi_from_wifi),
+ SHORT(bt_tssi_target),
+
+ CHAR(coex_config_bt_ctrl),
+ CHAR(coex_config_bt_ctrl_mode),
+ CHAR(coex_config_bt_ctrl_rw),
+
+ CHAR(coex_config_addjust_opp_time_ratio),
+ CHAR(coex_config_addjust_opp_time_ratio_bt_slot),
+ CHAR(coex_config_addjust_opp_time_ratio_wifi_slot),
+
+ CHAR(coex_config_addjust_ble_scan_time_ratio),
+ CHAR(coex_config_addjust_ble_scan_time_ratio_bt_slot),
+ CHAR(coex_config_addjust_ble_scan_time_ratio_wifi_slot),
+ CHAR(tcxo_gpio),
+};
+
+#define NUM_CFG_FIELDS (osal_sizeof(cfg_fields) / osal_sizeof(cfg_fields[0]))
+
+static int conf_parse_char(const struct parse_data *data, const char *pos)
+{
+ char *dst;
+ long res = 0;
+
+ dst = (char *)(data->param1);
+
+ if ((osal_strlen(pos) > 2) && ((*pos) == '0') && (*(pos + 1) == 'x')) {
+ osal_strtol(pos + 2, 16, &res);
+ *dst = (char)res;
+ pr_debug("cfg==> %s=0x%x\n", data->name, *dst);
+ } else {
+ osal_strtol(pos, 10, &res);
+ *dst = (char)res;
+ pr_debug("cfg==> %s=%d\n", data->name, *dst);
+ }
+ return 0;
+}
+
+static char *conf_write_char(const struct parse_data *data)
+{
+ char *src;
+ int res;
+ char *value;
+
+ src = data->param1;
+
+ value = osal_malloc(20);
+ if (value == NULL)
+ return NULL;
+ res = osal_snprintf(value, 20, "0x%x", *src);
+ if (res < 0 || res >= 20) {
+ osal_free(value);
+ return NULL;
+ }
+ value[20 - 1] = '\0';
+ return value;
+}
+
+static int conf_parse_short(const struct parse_data *data, const char *pos)
+{
+ unsigned short *dst;
+ long res = 0;
+
+ dst = (unsigned short *)data->param1;
+
+ if ((osal_strlen(pos) > 2) && ((*pos) == '0') && (*(pos + 1) == 'x')) {
+ osal_strtol(pos + 2, 16, &res);
+ *dst = (unsigned short)res;
+ pr_debug("cfg==> %s=0x%x\n", data->name, *dst);
+ } else {
+ osal_strtol(pos, 10, &res);
+ *dst = (unsigned short)res;
+ pr_debug("cfg==> %s=%d\n", data->name, *dst);
+ }
+
+ return 0;
+}
+
+static char *conf_write_short(const struct parse_data *data)
+{
+ short *src;
+ int res;
+ char *value;
+
+ /* TODO: [FixMe][George] FIX COMPILE WARNING HERE! */
+ src = (short *)data->param1;
+
+ value = osal_malloc(20);
+ if (value == NULL)
+ return NULL;
+ res = osal_snprintf(value, 20, "0x%x", *src);
+ if (res < 0 || res >= 20) {
+ osal_free(value);
+ return NULL;
+ }
+ value[20 - 1] = '\0';
+ return value;
+}
+
+static int conf_parse_int(const struct parse_data *data, const char *pos)
+{
+ int *dst;
+ long res = 0;
+
+ dst = (int *)data->param1;
+
+ if ((osal_strlen(pos) > 2) && ((*pos) == '0') && (*(pos + 1) == 'x')) {
+ osal_strtol(pos + 2, 16, &res);
+ *dst = (unsigned int)res;
+ pr_debug("cfg==> %s=0x%x\n", data->name, *dst);
+ } else {
+ osal_strtol(pos, 10, &res);
+ *dst = (unsigned int)res;
+ pr_debug("cfg==> %s=%d\n", data->name, *dst);
+ }
+
+ return 0;
+}
+
+static char *conf_write_int(const struct parse_data *data)
+{
+ int *src;
+ int res;
+ char *value;
+
+ src = (unsigned int *) data->param1;
+
+ value = osal_malloc(20);
+ if (value == NULL)
+ return NULL;
+ res = osal_snprintf(value, 20, "0x%x", *src);
+ if (res < 0 || res >= 20) {
+ osal_free(value);
+ return NULL;
+ }
+ value[20 - 1] = '\0';
+ return value;
+}
+
+static int conf_parse_byte_array(const struct parse_data *data,
+ const char *pos)
+{
+ unsigned char **dst;
+ struct conf_byte_ary *ba;
+ unsigned char *buffer;
+ int size = osal_strlen(pos) / 2;
+ unsigned char temp[3];
+ int i;
+ long value;
+
+ if (size <= 1) {
+ pr_err("cfg==> %s has no value assigned\n",
+ data->name);
+ return -1;
+ } else if (size & 0x1) {
+ pr_debug("cfg==> %s, length should be even\n", data->name);
+ return -1;
+ }
+
+ ba = (struct conf_byte_ary *)osal_malloc(sizeof(struct conf_byte_ary));
+ if (ba == NULL) {
+ pr_err("cfg==> %s malloc fail\n", data->name);
+ return -1;
+ }
+
+ buffer = osal_malloc(size);
+ if (buffer == NULL) {
+ osal_free(ba);
+ pr_err("cfg==> %s malloc fail, size %d\n", data->name, size);
+ return -1;
+ }
+
+ temp[2] = '\0';
+ for (i = 0; i < size; i++) {
+ osal_memcpy(temp, &pos[i * 2], 2);
+ if (osal_strtol(temp, 16, &value) < 0) {
+ pr_err("cfg==> %s should be hexadecimal format\n",
+ data->name);
+ osal_free(ba);
+ osal_free(buffer);
+ return -1;
+ }
+ buffer[i] = (char)value;
+ }
+ ba->data = buffer;
+ ba->size = size;
+
+ dst = (unsigned char **) data->param1;
+ *dst = (unsigned char *)ba;
+
+ return 0;
+}
+
+static char *conf_write_byte_array(const struct parse_data *data)
+{
+ unsigned char **src;
+ char *value;
+ struct conf_byte_ary *ba;
+ int i;
+
+ src = (unsigned char **) data->param1;
+ if (*src == NULL)
+ return NULL;
+
+ ba = (struct conf_byte_ary *)*src;
+
+ value = osal_malloc(ba->size * 2 + 1);
+ if (value == NULL)
+ return NULL;
+
+ for (i = 0; i < ba->size; i++)
+ osal_snprintf(&value[i * 2], 3, "%x", ba->data[i]);
+
+ return value;
+}
+
+
+static void conf_release_byte_array(const struct parse_data *data)
+{
+ //unsigned char *buffer;
+ struct conf_byte_ary *ba;
+ unsigned char **src;
+
+ if (data->param1 != NULL) {
+ src = (unsigned char **) data->param1;
+ ba = (struct conf_byte_ary *) *src;
+ if (ba->data != NULL) {
+ osal_free(ba->data);
+ ba->data = NULL;
+ }
+ osal_free(ba);
+ //data->param1 = NULL;
+ *src = NULL;
+ }
+}
+
+static int conf_parse_pair(const char *pKey, const char *pVal)
+{
+ int i = 0;
+ int ret = 0;
+
+
+ for (i = 0; i < NUM_CFG_FIELDS; i++) {
+ const struct parse_data *field = &cfg_fields[i];
+
+ if (osal_strcmp(pKey, field->name) != 0)
+ continue;
+ if (field->parser(field, pVal)) {
+ pr_err("failed to parse %s '%s'.\n", pKey, pVal);
+ ret = -1;
+ }
+ break;
+ }
+ if (i == NUM_CFG_FIELDS) {
+ pr_err("unknown field '%s'.\n", pKey);
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static int conf_parse(const char *pInBuf, unsigned int size)
+{
+ char *pch;
+ char *pBuf;
+ char *pLine;
+ char *pKey;
+ char *pVal;
+ char *pPos;
+ int ret = 0;
+ int i = 0;
+ char *pa = NULL;
+
+ pBuf = osal_malloc(size+1);
+ if (!pBuf)
+ return -1;
+
+ osal_memcpy(pBuf, pInBuf, size);
+ pBuf[size] = '\0';
+
+ pch = pBuf;
+ /* pch is to be updated by strsep(). Keep pBuf unchanged!! */
+
+ while ((pLine = osal_strsep(&pch, "\r\n")) != NULL) {
+ /* pch is updated to the end of pLine by
+ * strsep() and updated to '\0'
+ */
+ /* parse each line */
+
+ if (!*pLine)
+ continue;
+
+ pVal = osal_strchr(pLine, '=');
+ if (!pVal) {
+ pr_warn("mal-format cfg string(%s)\n", pLine);
+ continue;
+ }
+
+ /* |<-pLine->|'='<-pVal->|'\n' ('\0')| */
+ *pVal = '\0'; /* replace '=' with '\0' to get key */
+ /* |<-pKey->|'\0'|<-pVal->|'\n' ('\0')| */
+ pKey = pLine;
+
+ if ((pVal - pBuf) < size)
+ pVal++;
+
+ /*key handling */
+ pPos = pKey;
+ /*skip space characeter */
+ while (((*pPos) == ' ') ||
+ ((*pPos) == '\t') || ((*pPos) == '\n')) {
+ if ((pPos - pBuf) >= size)
+ break;
+ pPos++;
+ }
+ /*key head */
+ pKey = pPos;
+ while (((*pPos) != ' ') &&
+ ((*pPos) != '\t') && ((*pPos) != '\0')
+ && ((*pPos) != '\n')) {
+ if ((pPos - pBuf) >= size)
+ break;
+ pPos++;
+ }
+ /*key tail */
+ (*pPos) = '\0';
+
+ /*value handling */
+ pPos = pVal;
+ /*skip space characeter */
+ while (((*pPos) == ' ') ||
+ ((*pPos) == '\t') || ((*pPos) == '\n')) {
+ if ((pPos - pBuf) >= size)
+ break;
+ pPos++;
+ }
+ /*value head */
+ pVal = pPos;
+ while (((*pPos) != ' ') &&
+ ((*pPos) != '\t') && ((*pPos) != '\0')
+ && ((*pPos) != '\n')) {
+ if ((pPos - pBuf) >= size)
+ break;
+ pPos++;
+ }
+ /*value tail */
+ (*pPos) = '\0';
+
+ ret = conf_parse_pair(pKey, pVal);
+ pr_debug("parse (%s, %s, %d)\n", pKey, pVal, ret);
+ if (ret)
+ pr_debug("parse fail (%s, %s, %d)\n", pKey, pVal, ret);
+ }
+
+ for (i = 0; i < NUM_CFG_FIELDS; i++) {
+ const struct parse_data *field = &cfg_fields[i];
+
+ pa = field->writer(field);
+ if (pa) {
+ pr_debug("#%d(%s)=>%s\n", i, field->name, pa);
+ osal_free(pa);
+ } else
+ pr_err("failed to parse '%s'.\n", field->name);
+ }
+ osal_free(pBuf);
+ return 0;
+}
+
+static int platform_request_firmware(char *patch_name, osal_firmware **ppPatch)
+{
+ int ret;
+ osal_firmware *fw = NULL;
+
+ if (!ppPatch) {
+ pr_err("invalid ppBufptr!\n");
+ return -1;
+ }
+
+ *ppPatch = NULL;
+ do {
+ ret = request_firmware((const struct firmware **)&fw,
+ patch_name, NULL);
+ if (ret == -EAGAIN) {
+ pr_err("failed to open or read!(%s), retry again!\n",
+ patch_name);
+ osal_sleep_ms(100);
+ }
+ } while (ret == -EAGAIN);
+ if (ret != 0) {
+ pr_err("failed to open or read!(%s)\n", patch_name);
+ release_firmware(fw);
+ return -1;
+ }
+ pr_debug("loader firmware %s ok!!\n", patch_name);
+ ret = 0;
+ *ppPatch = fw;
+
+ return ret;
+}
+
+static int platform_release_firmware(osal_firmware **ppPatch)
+{
+ if (*ppPatch != NULL) {
+ release_firmware((const struct firmware *)*ppPatch);
+ *ppPatch = NULL;
+ }
+ return 0;
+}
+
+int conninfra_conf_init(void)
+{
+ int ret = -1;
+ const osal_firmware *conf_inst;
+
+ osal_memset(&g_conninfra_conf, 0, osal_sizeof(struct conninfra_conf));
+ osal_strcpy(&(g_conninfra_conf.conf_name[0]), "conninfra.cfg");
+
+ pr_debug("config file:%s\n", &(g_conninfra_conf.conf_name[0]));
+ if (0 ==
+ platform_request_firmware(&g_conninfra_conf.conf_name[0],
+ (osal_firmware **) &conf_inst)) {
+ /*get full name patch success */
+ pr_debug("get full file name(%s) buf(0x%p) size(%zu)\n",
+ &g_conninfra_conf.conf_name[0], conf_inst->data,
+ conf_inst->size);
+ if (0 ==
+ conf_parse((const char *)conf_inst->data,
+ conf_inst->size)) {
+ /*config file exists */
+ g_conninfra_conf.cfg_exist = 1;
+ ret = 0;
+ } else {
+ pr_err("conf parsing fail\n");
+ ret = -1;
+ }
+ platform_release_firmware((osal_firmware **) &conf_inst);
+ return ret;
+ }
+ pr_err("read %s file fails\n", &(g_conninfra_conf.conf_name[0]));
+ g_conninfra_conf.cfg_exist = 0;
+ return ret;
+}
+
+int conninfra_conf_set_cfg_file(const char *name)
+{
+ if (name == NULL) {
+ pr_err("name is NULL\n");
+ return -1;
+ }
+ if (osal_strlen(name) >= osal_sizeof(g_conninfra_conf.conf_name)) {
+ pr_err("name is too long, length=%d, expect to < %zu\n",
+ osal_strlen(name),
+ osal_sizeof(g_conninfra_conf.conf_name));
+ return -2;
+ }
+ osal_memset(&g_conninfra_conf.conf_name[0], 0,
+ osal_sizeof(g_conninfra_conf.conf_name));
+ osal_strcpy(&(g_conninfra_conf.conf_name[0]), name);
+ pr_err("WMT config file is set to (%s)\n",
+ &(g_conninfra_conf.conf_name[0]));
+
+ return 0;
+}
+
+const struct conninfra_conf *conninfra_conf_get_cfg(void)
+{
+ if (g_conninfra_conf.cfg_exist == 0)
+ return NULL;
+
+ return &g_conninfra_conf;
+}
+
+int conninfra_conf_deinit(void)
+{
+ int i;
+
+ if (g_conninfra_conf.cfg_exist == 0)
+ return -1;
+
+ for (i = 0; i < NUM_CFG_FIELDS; i++) {
+ const struct parse_data *field = &cfg_fields[i];
+ field->relase_mem(field);
+ }
+ g_conninfra_conf.cfg_exist = 0;
+ return 0;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/conf/include/conninfra_conf.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/conf/include/conninfra_conf.h
new file mode 100755
index 0000000..4e49b3b
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/conf/include/conninfra_conf.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+
+
+#ifndef _CONNINFRA_CONF_H_
+#define _CONNINFRA_CONF_H_
+
+#include "osal.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+#define CUST_CFG_INFRA "WMT.cfg"
+#define CUST_CFG_INFRA_SOC "WMT_SOC.cfg"
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+struct conf_byte_ary {
+ unsigned int size;
+ char *data;
+};
+
+struct conninfra_conf {
+
+ char conf_name[NAME_MAX + 1];
+ //const osal_firmware *conf_inst;
+ unsigned char cfg_exist;
+
+ unsigned char coex_wmt_ant_mode;
+ unsigned char coex_wmt_ant_mode_ex;
+ unsigned char coex_wmt_ext_component;
+ unsigned char coex_wmt_wifi_time_ctl;
+ unsigned char coex_wmt_ext_pta_dev_on;
+ /*combo chip and LTE coex filter mode setting */
+ unsigned char coex_wmt_filter_mode;
+
+ unsigned char coex_bt_rssi_upper_limit;
+ unsigned char coex_bt_rssi_mid_limit;
+ unsigned char coex_bt_rssi_lower_limit;
+ unsigned char coex_bt_pwr_high;
+ unsigned char coex_bt_pwr_mid;
+ unsigned char coex_bt_pwr_low;
+
+ unsigned char coex_wifi_rssi_upper_limit;
+ unsigned char coex_wifi_rssi_mid_limit;
+ unsigned char coex_wifi_rssi_lower_limit;
+ unsigned char coex_wifi_pwr_high;
+ unsigned char coex_wifi_pwr_mid;
+ unsigned char coex_wifi_pwr_low;
+
+ unsigned char coex_ext_pta_hi_tx_tag;
+ unsigned char coex_ext_pta_hi_rx_tag;
+ unsigned char coex_ext_pta_lo_tx_tag;
+ unsigned char coex_ext_pta_lo_rx_tag;
+ unsigned short coex_ext_pta_sample_t1;
+ unsigned short coex_ext_pta_sample_t2;
+ unsigned char coex_ext_pta_wifi_bt_con_trx;
+
+ unsigned int coex_misc_ext_pta_on;
+ unsigned int coex_misc_ext_feature_set;
+ /*GPS LNA setting */
+ unsigned char wmt_gps_lna_pin;
+ unsigned char wmt_gps_lna_enable;
+ /*Power on sequence */
+ unsigned char pwr_on_rtc_slot;
+ unsigned char pwr_on_ldo_slot;
+ unsigned char pwr_on_rst_slot;
+ unsigned char pwr_on_off_slot;
+ unsigned char pwr_on_on_slot;
+ unsigned char co_clock_flag;
+
+ /*deep sleep feature flag*/
+ unsigned char disable_deep_sleep_cfg;
+
+ /* Combo chip side SDIO driving setting */
+ unsigned int sdio_driving_cfg;
+
+ /* Combo chip WiFi path setting */
+ unsigned short coex_wmt_wifi_path;
+ /* Combo chip WiFi eLAN gain setting */
+ unsigned char coex_wmt_ext_elna_gain_p1_support;
+ unsigned int coex_wmt_ext_elna_gain_p1_D0;
+ unsigned int coex_wmt_ext_elna_gain_p1_D1;
+ unsigned int coex_wmt_ext_elna_gain_p1_D2;
+ unsigned int coex_wmt_ext_elna_gain_p1_D3;
+
+ struct conf_byte_ary *coex_wmt_epa_elna;
+
+ unsigned char bt_tssi_from_wifi;
+ unsigned short bt_tssi_target;
+
+ unsigned char coex_config_bt_ctrl;
+ unsigned char coex_config_bt_ctrl_mode;
+ unsigned char coex_config_bt_ctrl_rw;
+
+ unsigned char coex_config_addjust_opp_time_ratio;
+ unsigned char coex_config_addjust_opp_time_ratio_bt_slot;
+ unsigned char coex_config_addjust_opp_time_ratio_wifi_slot;
+
+ unsigned char coex_config_addjust_ble_scan_time_ratio;
+ unsigned char coex_config_addjust_ble_scan_time_ratio_bt_slot;
+ unsigned char coex_config_addjust_ble_scan_time_ratio_wifi_slot;
+
+ /* POS. If set, means using ext TCXO */
+ unsigned char tcxo_gpio;
+
+};
+
+
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+
+
+
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+const struct conninfra_conf *conninfra_conf_get_cfg(void);
+int conninfra_conf_set_cfg_file(const char *name);
+
+int conninfra_conf_init(void);
+int conninfra_conf_deinit(void);
+
+#endif /* _CONNINFRA_CONF_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/core/conninfra_core.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/core/conninfra_core.c
new file mode 100755
index 0000000..ebbb359
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/core/conninfra_core.c
@@ -0,0 +1,1765 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__
+
+#include "consys_hw.h"
+#include "conninfra_core.h"
+#include "msg_thread.h"
+#include "consys_reg_mng.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+#define CONNINFRA_EVENT_TIMEOUT 3000
+#define CONNINFRA_RESET_TIMEOUT 500
+#define CONNINFRA_PRE_CAL_TIMEOUT 500
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+#include <linux/delay.h>
+#include <linux/thermal.h>
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+static int opfunc_power_on(struct msg_op_data *op);
+static int opfunc_power_off(struct msg_op_data *op);
+static int opfunc_chip_rst(struct msg_op_data *op);
+static int opfunc_pre_cal(struct msg_op_data *op);
+static int opfunc_therm_ctrl(struct msg_op_data *op);
+static int opfunc_rfspi_read(struct msg_op_data *op);
+static int opfunc_rfspi_write(struct msg_op_data *op);
+static int opfunc_adie_top_ck_en_on(struct msg_op_data *op);
+static int opfunc_adie_top_ck_en_off(struct msg_op_data *op);
+static int opfunc_spi_clock_switch(struct msg_op_data *op);
+static int opfunc_clock_fail_dump(struct msg_op_data *op);
+static int opfunc_pre_cal_prepare(struct msg_op_data *op);
+static int opfunc_pre_cal_check(struct msg_op_data *op);
+
+static int opfunc_force_conninfra_wakeup(struct msg_op_data *op);
+static int opfunc_force_conninfra_sleep(struct msg_op_data *op);
+
+static int opfunc_dump_power_state(struct msg_op_data *op);
+
+static int opfunc_subdrv_pre_reset(struct msg_op_data *op);
+static int opfunc_subdrv_post_reset(struct msg_op_data *op);
+static int opfunc_subdrv_cal_pwr_on(struct msg_op_data *op);
+static int opfunc_subdrv_cal_do_cal(struct msg_op_data *op);
+static int opfunc_subdrv_therm_ctrl(struct msg_op_data *op);
+
+static void _conninfra_core_update_rst_status(enum chip_rst_status status);
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+struct conninfra_ctx g_conninfra_ctx;
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+static const msg_opid_func conninfra_core_opfunc[] = {
+ [CONNINFRA_OPID_PWR_ON] = opfunc_power_on,
+ [CONNINFRA_OPID_PWR_OFF] = opfunc_power_off,
+ [CONNINFRA_OPID_THERM_CTRL] = opfunc_therm_ctrl,
+ [CONNINFRA_OPID_RFSPI_READ] = opfunc_rfspi_read,
+ [CONNINFRA_OPID_RFSPI_WRITE] = opfunc_rfspi_write,
+ [CONNINFRA_OPID_ADIE_TOP_CK_EN_ON] = opfunc_adie_top_ck_en_on,
+ [CONNINFRA_OPID_ADIE_TOP_CK_EN_OFF] = opfunc_adie_top_ck_en_off,
+ [CONNINFRA_OPID_SPI_CLOCK_SWITCH] = opfunc_spi_clock_switch,
+ [CONNINFRA_OPID_CLOCK_FAIL_DUMP] = opfunc_clock_fail_dump,
+ [CONNINFRA_OPID_PRE_CAL_PREPARE] = opfunc_pre_cal_prepare,
+ [CONNINFRA_OPID_PRE_CAL_CHECK] = opfunc_pre_cal_check,
+
+ [CONNINFRA_OPID_FORCE_CONNINFRA_WAKUP] = opfunc_force_conninfra_wakeup,
+ [CONNINFRA_OPID_FORCE_CONNINFRA_SLEEP] = opfunc_force_conninfra_sleep,
+
+ [CONNINFRA_OPID_DUMP_POWER_STATE] = opfunc_dump_power_state,
+};
+
+static const msg_opid_func conninfra_core_cb_opfunc[] = {
+ [CONNINFRA_CB_OPID_CHIP_RST] = opfunc_chip_rst,
+ [CONNINFRA_CB_OPID_PRE_CAL] = opfunc_pre_cal,
+};
+
+
+/* subsys ops */
+static char *drv_thread_name[] = {
+ [CONNDRV_TYPE_BT] = "sub_bt_thrd",
+ [CONNDRV_TYPE_FM] = "sub_fm_thrd",
+ [CONNDRV_TYPE_GPS] = "sub_gps_thrd",
+ [CONNDRV_TYPE_WIFI] = "sub_wifi_thrd",
+ [CONNDRV_TYPE_CONNINFRA] = "sub_conninfra_thrd",
+};
+
+static char *drv_name[] = {
+ [CONNDRV_TYPE_BT] = "BT",
+ [CONNDRV_TYPE_FM] = "FM",
+ [CONNDRV_TYPE_GPS] = "GPS",
+ [CONNDRV_TYPE_WIFI] = "WIFI",
+ [CONNDRV_TYPE_CONNINFRA] = "CONNINFRA",
+};
+
+typedef enum {
+ INFRA_SUBDRV_OPID_PRE_RESET = 0,
+ INFRA_SUBDRV_OPID_POST_RESET = 1,
+ INFRA_SUBDRV_OPID_CAL_PWR_ON = 2,
+ INFRA_SUBDRV_OPID_CAL_DO_CAL = 3,
+ INFRA_SUBDRV_OPID_THERM_CTRL = 4,
+
+ INFRA_SUBDRV_OPID_MAX
+} infra_subdrv_op;
+
+
+static const msg_opid_func infra_subdrv_opfunc[] = {
+ [INFRA_SUBDRV_OPID_PRE_RESET] = opfunc_subdrv_pre_reset,
+ [INFRA_SUBDRV_OPID_POST_RESET] = opfunc_subdrv_post_reset,
+ [INFRA_SUBDRV_OPID_CAL_PWR_ON] = opfunc_subdrv_cal_pwr_on,
+ [INFRA_SUBDRV_OPID_CAL_DO_CAL] = opfunc_subdrv_cal_do_cal,
+ [INFRA_SUBDRV_OPID_THERM_CTRL] = opfunc_subdrv_therm_ctrl,
+};
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+static void reset_chip_rst_trg_data(void)
+{
+ g_conninfra_ctx.trg_drv = CONNDRV_TYPE_MAX;
+ memset(g_conninfra_ctx.trg_reason, '\0', CHIP_RST_REASON_MAX_LEN);
+}
+
+static unsigned long timeval_to_ms(struct timeval *begin, struct timeval *end)
+{
+ unsigned long time_diff;
+
+ time_diff = (end->tv_sec - begin->tv_sec) * 1000;
+ time_diff += (end->tv_usec - begin->tv_usec) / 1000;
+
+ return time_diff;
+}
+
+static unsigned int opfunc_get_current_status(void)
+{
+ unsigned int ret = 0;
+ unsigned int i;
+
+ for (i = 0; i < CONNDRV_TYPE_MAX; i++) {
+ ret |= (g_conninfra_ctx.drv_inst[i].drv_status << i);
+ }
+
+ return ret;
+}
+
+static void opfunc_vcn_control_internal(unsigned int drv_type, bool on)
+{
+ /* VCNx enable */
+ switch (drv_type) {
+ case CONNDRV_TYPE_BT:
+ consys_hw_bt_power_ctl(on);
+ break;
+ case CONNDRV_TYPE_FM:
+ consys_hw_fm_power_ctl(on);
+ break;
+ case CONNDRV_TYPE_GPS:
+ consys_hw_gps_power_ctl(on);
+ break;
+ case CONNDRV_TYPE_WIFI:
+ consys_hw_wifi_power_ctl(on);
+ break;
+ default:
+ pr_err("Wrong parameter: drv_type(%d)\n", drv_type);
+ break;
+ }
+}
+
+static int opfunc_power_on_internal(unsigned int drv_type)
+{
+ int ret;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ /* Check abnormal type */
+ if (drv_type >= CONNDRV_TYPE_MAX) {
+ pr_err("abnormal Fun(%d)\n", drv_type);
+ return -EINVAL;
+ }
+
+ /* Check abnormal state */
+ if ((g_conninfra_ctx.drv_inst[drv_type].drv_status < DRV_STS_POWER_OFF)
+ || (g_conninfra_ctx.drv_inst[drv_type].drv_status >= DRV_STS_MAX)) {
+ pr_err("func(%d) status[0x%x] abnormal\n", drv_type,
+ g_conninfra_ctx.drv_inst[drv_type].drv_status);
+ return -EINVAL;
+ }
+
+ ret = osal_lock_sleepable_lock(&infra_ctx->core_lock);
+ if (ret) {
+ pr_err("core_lock fail!!");
+ return ret;
+ }
+
+ /* check if func already on */
+ if (g_conninfra_ctx.drv_inst[drv_type].drv_status == DRV_STS_POWER_ON) {
+ pr_warn("func(%d) already on\n", drv_type);
+ osal_unlock_sleepable_lock(&infra_ctx->core_lock);
+ return 0;
+ }
+
+ ret = consys_hw_pwr_on(opfunc_get_current_status(), drv_type);
+ if (ret) {
+ pr_err("Conninfra power on fail. drv(%d) ret=(%d)\n",
+ drv_type, ret);
+ osal_unlock_sleepable_lock(&infra_ctx->core_lock);
+ return -3;
+ }
+ /* POWER ON SEQUENCE */
+ g_conninfra_ctx.infra_drv_status = DRV_STS_POWER_ON;
+
+ g_conninfra_ctx.drv_inst[drv_type].drv_status = DRV_STS_POWER_ON;
+
+ /* VCNx enable */
+ opfunc_vcn_control_internal(drv_type, true);
+
+ pr_info("[Conninfra Pwr On] BT=[%d] FM=[%d] GPS=[%d] WF=[%d]",
+ infra_ctx->drv_inst[CONNDRV_TYPE_BT].drv_status,
+ infra_ctx->drv_inst[CONNDRV_TYPE_FM].drv_status,
+ infra_ctx->drv_inst[CONNDRV_TYPE_GPS].drv_status,
+ infra_ctx->drv_inst[CONNDRV_TYPE_WIFI].drv_status);
+ osal_unlock_sleepable_lock(&infra_ctx->core_lock);
+
+ return 0;
+}
+
+static int opfunc_power_on(struct msg_op_data *op)
+{
+ unsigned int drv_type = op->op_data[0];
+
+ return opfunc_power_on_internal(drv_type);
+}
+
+static int opfunc_power_off_internal(unsigned int drv_type)
+{
+ int i, ret;
+ bool try_power_off = true;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+ unsigned int curr_status = opfunc_get_current_status();
+
+ /* Check abnormal type */
+ if (drv_type >= CONNDRV_TYPE_MAX) {
+ pr_err("abnormal Fun(%d)\n", drv_type);
+ return -EINVAL;
+ }
+
+ ret = osal_lock_sleepable_lock(&infra_ctx->core_lock);
+ if (ret) {
+ pr_err("core_lock fail!!");
+ return ret;
+ }
+
+ /* Check abnormal state */
+ if ((g_conninfra_ctx.drv_inst[drv_type].drv_status < DRV_STS_POWER_OFF)
+ || (g_conninfra_ctx.drv_inst[drv_type].drv_status >= DRV_STS_MAX)) {
+ pr_err("func(%d) status[0x%x] abnormal\n", drv_type,
+ g_conninfra_ctx.drv_inst[drv_type].drv_status);
+ osal_unlock_sleepable_lock(&infra_ctx->core_lock);
+ return -2;
+ }
+
+ /* Special case for force power off */
+ if (drv_type == CONNDRV_TYPE_CONNINFRA) {
+ if (g_conninfra_ctx.infra_drv_status == DRV_STS_POWER_OFF) {
+ pr_warn("Connsys already off, do nothing for force off\n");
+ return 0;
+ }
+ /* Turn off subsys VCN and update record */
+ for (i = 0; i < CONNDRV_TYPE_MAX; i++) {
+ if (g_conninfra_ctx.drv_inst[i].drv_status == DRV_STS_POWER_ON) {
+ opfunc_vcn_control_internal(i, false);
+ g_conninfra_ctx.drv_inst[i].drv_status = DRV_STS_POWER_OFF;
+ }
+ }
+ /* POWER OFF SEQUENCE */
+ ret = consys_hw_pwr_off(0, drv_type);
+ /* For force power off operation, ignore err code */
+ if (ret)
+ pr_err("Force power off fail. ret=%d\n", ret);
+ try_power_off = true;
+ } else {
+ /* check if func already off */
+ if (g_conninfra_ctx.drv_inst[drv_type].drv_status
+ == DRV_STS_POWER_OFF) {
+ pr_warn("func(%d) already off\n", drv_type);
+ osal_unlock_sleepable_lock(&infra_ctx->core_lock);
+ return 0;
+ }
+ /* VCNx disable */
+ opfunc_vcn_control_internal(drv_type, false);
+ g_conninfra_ctx.drv_inst[drv_type].drv_status = DRV_STS_POWER_OFF;
+ /* is there subsys on ? */
+ for (i = 0; i < CONNDRV_TYPE_MAX; i++)
+ if (g_conninfra_ctx.drv_inst[i].drv_status == DRV_STS_POWER_ON)
+ try_power_off = false;
+
+ /* POWER OFF SEQUENCE */
+ ret = consys_hw_pwr_off(curr_status, drv_type);
+ if (ret) {
+ pr_err("Conninfra power on fail. drv(%d) ret=(%d)\n",
+ drv_type, ret);
+ osal_unlock_sleepable_lock(&infra_ctx->core_lock);
+ return -3;
+ }
+ }
+
+ if (try_power_off)
+ g_conninfra_ctx.infra_drv_status = DRV_STS_POWER_OFF;
+
+ pr_info("[Conninfra Pwr Off] Conninfra=[%d] BT=[%d] FM=[%d] GPS=[%d] WF=[%d]",
+ infra_ctx->infra_drv_status,
+ infra_ctx->drv_inst[CONNDRV_TYPE_BT].drv_status,
+ infra_ctx->drv_inst[CONNDRV_TYPE_FM].drv_status,
+ infra_ctx->drv_inst[CONNDRV_TYPE_GPS].drv_status,
+ infra_ctx->drv_inst[CONNDRV_TYPE_WIFI].drv_status);
+
+ osal_unlock_sleepable_lock(&infra_ctx->core_lock);
+ return 0;
+}
+
+static int opfunc_power_off(struct msg_op_data *op)
+{
+ unsigned int drv_type = op->op_data[0];
+
+ return opfunc_power_off_internal(drv_type);
+}
+
+static int opfunc_chip_rst(struct msg_op_data *op)
+{
+ int i, ret, cur_rst_state;
+ struct subsys_drv_inst *drv_inst;
+ unsigned int drv_pwr_state[CONNDRV_TYPE_MAX];
+ const unsigned int subdrv_all_done = (0x1 << CONNDRV_TYPE_MAX) - 1;
+ struct timeval pre_begin, pre_end, reset_end, done_end;
+
+ if (g_conninfra_ctx.infra_drv_status == DRV_STS_POWER_OFF) {
+ pr_info("No subsys on, just return");
+ _conninfra_core_update_rst_status(CHIP_RST_NONE);
+ return 0;
+ }
+
+ do_gettimeofday(&pre_begin);
+
+ atomic_set(&g_conninfra_ctx.rst_state, 0);
+ sema_init(&g_conninfra_ctx.rst_sema, 1);
+
+ _conninfra_core_update_rst_status(CHIP_RST_PRE_CB);
+
+ /* pre */
+ for (i = 0; i < CONNDRV_TYPE_MAX; i++) {
+ drv_inst = &g_conninfra_ctx.drv_inst[i];
+ drv_pwr_state[i] = drv_inst->drv_status;
+ pr_info("subsys %d is %d", i, drv_inst->drv_status);
+ ret = msg_thread_send_1(&drv_inst->msg_ctx,
+ INFRA_SUBDRV_OPID_PRE_RESET, i);
+ }
+
+ pr_info("[chip_rst] pre vvvvvvvvvvvvv");
+ while (atomic_read(&g_conninfra_ctx.rst_state) != subdrv_all_done) {
+ ret = down_timeout(&g_conninfra_ctx.rst_sema, msecs_to_jiffies(CONNINFRA_RESET_TIMEOUT));
+ pr_info("sema ret=[%d]", ret);
+ if (ret == 0)
+ continue;
+ cur_rst_state = atomic_read(&g_conninfra_ctx.rst_state);
+ pr_info("cur_rst state =[%d]", cur_rst_state);
+ for (i = 0; i < CONNDRV_TYPE_MAX; i++) {
+ if ((cur_rst_state & (0x1 << i)) == 0) {
+ pr_info("[chip_rst] [%s] pre-callback is not back", drv_thread_name[i]);
+ drv_inst = &g_conninfra_ctx.drv_inst[i];
+ osal_thread_show_stack(&drv_inst->msg_ctx.thread);
+ }
+ }
+ }
+
+ _conninfra_core_update_rst_status(CHIP_RST_RESET);
+
+ do_gettimeofday(&pre_end);
+
+ pr_info("[chip_rst] reset ++++++++++++");
+ /*******************************************************/
+ /* reset */
+ /* call consys_hw */
+ /*******************************************************/
+ /* Special power-off function, turn off connsys directly */
+ ret = opfunc_power_off_internal(CONNDRV_TYPE_CONNINFRA);
+ pr_info("Force conninfra power off, ret=%d\n", ret);
+ pr_info("conninfra status should be power off. Status=%d", g_conninfra_ctx.infra_drv_status);
+
+ /* Turn on subsys */
+ for (i = 0; i < CONNDRV_TYPE_MAX; i++) {
+ if (drv_pwr_state[i]) {
+ ret = opfunc_power_on_internal(i);
+ pr_info("Call subsys(%d) power on ret=%d", i, ret);
+ }
+ }
+ pr_info("conninfra status should be power on. Status=%d", g_conninfra_ctx.infra_drv_status);
+
+ pr_info("[chip_rst] reset --------------");
+
+ _conninfra_core_update_rst_status(CHIP_RST_POST_CB);
+
+ do_gettimeofday(&reset_end);
+
+ /* post */
+ atomic_set(&g_conninfra_ctx.rst_state, 0);
+ sema_init(&g_conninfra_ctx.rst_sema, 1);
+ for (i = 0; i < CONNDRV_TYPE_MAX; i++) {
+ drv_inst = &g_conninfra_ctx.drv_inst[i];
+ ret = msg_thread_send_1(&drv_inst->msg_ctx,
+ INFRA_SUBDRV_OPID_POST_RESET, i);
+ }
+
+ while (atomic_read(&g_conninfra_ctx.rst_state) != subdrv_all_done) {
+ ret = down_timeout(&g_conninfra_ctx.rst_sema, msecs_to_jiffies(CONNINFRA_RESET_TIMEOUT));
+ if (ret == 0)
+ continue;
+ cur_rst_state = atomic_read(&g_conninfra_ctx.rst_state);
+ for (i = 0; i < CONNDRV_TYPE_MAX; i++) {
+ if ((cur_rst_state & (0x1 << i)) == 0) {
+ pr_info("[chip_rst] [%s] post-callback is not back", drv_thread_name[i]);
+ drv_inst = &g_conninfra_ctx.drv_inst[i];
+ osal_thread_show_stack(&drv_inst->msg_ctx.thread);
+ }
+ }
+ }
+ pr_info("[chip_rst] post ^^^^^^^^^^^^^^");
+
+ reset_chip_rst_trg_data();
+ //_conninfra_core_update_rst_status(CHIP_RST_DONE);
+ _conninfra_core_update_rst_status(CHIP_RST_NONE);
+ do_gettimeofday(&done_end);
+
+ pr_info("[chip_rst] summary pre=[%lu] reset=[%lu] post=[%lu]",
+ timeval_to_ms(&pre_begin, &pre_end),
+ timeval_to_ms(&pre_end, &reset_end),
+ timeval_to_ms(&reset_end, &done_end));
+
+ return 0;
+}
+
+static int opfunc_pre_cal(struct msg_op_data *op)
+{
+#define CAL_DRV_COUNT 2
+ int cal_drvs[CAL_DRV_COUNT] = {CONNDRV_TYPE_BT, CONNDRV_TYPE_WIFI};
+ int i, ret, cur_state;
+ int bt_cal_ret, wf_cal_ret;
+ struct subsys_drv_inst *drv_inst;
+ int pre_cal_done_state = (0x1 << CONNDRV_TYPE_BT) | (0x1 << CONNDRV_TYPE_WIFI);
+ struct timeval begin, bt_cal_begin, wf_cal_begin, end;
+
+ /* Check BT/WIFI status again */
+ ret = osal_lock_sleepable_lock(&g_conninfra_ctx.core_lock);
+ if (ret) {
+ pr_err("[%s] core_lock fail!!", __func__);
+ return ret;
+ }
+ /* check if func already on */
+ for (i = 0; i < CAL_DRV_COUNT; i++) {
+ if (g_conninfra_ctx.drv_inst[cal_drvs[i]].drv_status == DRV_STS_POWER_ON) {
+ pr_warn("[%s] %s already on\n", __func__, drv_name[cal_drvs[i]]);
+ osal_unlock_sleepable_lock(&g_conninfra_ctx.core_lock);
+ return 0;
+ }
+ }
+ osal_unlock_sleepable_lock(&g_conninfra_ctx.core_lock);
+
+ ret = conninfra_core_power_on(CONNDRV_TYPE_BT);
+ if (ret) {
+ pr_err("BT power on fail during pre_cal");
+ return -1;
+ }
+ ret = conninfra_core_power_on(CONNDRV_TYPE_WIFI);
+ if (ret) {
+ pr_err("WIFI power on fail during pre_cal");
+ conninfra_core_power_off(CONNDRV_TYPE_BT);
+ return -2;
+ }
+
+ do_gettimeofday(&begin);
+
+ /* power on subsys */
+ atomic_set(&g_conninfra_ctx.pre_cal_state, 0);
+ sema_init(&g_conninfra_ctx.pre_cal_sema, 1);
+
+ for (i = 0; i < CAL_DRV_COUNT; i++) {
+ drv_inst = &g_conninfra_ctx.drv_inst[cal_drvs[i]];
+ ret = msg_thread_send_1(&drv_inst->msg_ctx,
+ INFRA_SUBDRV_OPID_CAL_PWR_ON, cal_drvs[i]);
+ if (ret)
+ pr_warn("driver [%d] power on fail\n", cal_drvs[i]);
+ }
+
+ while (atomic_read(&g_conninfra_ctx.pre_cal_state) != pre_cal_done_state) {
+ ret = down_timeout(&g_conninfra_ctx.pre_cal_sema, msecs_to_jiffies(CONNINFRA_PRE_CAL_TIMEOUT));
+ if (ret == 0)
+ continue;
+ cur_state = atomic_read(&g_conninfra_ctx.pre_cal_state);
+ pr_info("[pre_cal] cur state =[%d]", cur_state);
+ if ((cur_state & (0x1 << CONNDRV_TYPE_BT)) == 0) {
+ pr_info("[pre_cal] BT pwr_on callback is not back");
+ drv_inst = &g_conninfra_ctx.drv_inst[CONNDRV_TYPE_BT];
+ osal_thread_show_stack(&drv_inst->msg_ctx.thread);
+ }
+ if ((cur_state & (0x1 << CONNDRV_TYPE_WIFI)) == 0) {
+ pr_info("[pre_cal] WIFI pwr_on callback is not back");
+ drv_inst = &g_conninfra_ctx.drv_inst[CONNDRV_TYPE_WIFI];
+ osal_thread_show_stack(&drv_inst->msg_ctx.thread);
+ }
+ }
+ pr_info("[pre_cal] >>>>>>> power on DONE!!");
+
+ do_gettimeofday(&bt_cal_begin);
+
+ /* Do Calibration */
+ drv_inst = &g_conninfra_ctx.drv_inst[CONNDRV_TYPE_BT];
+ bt_cal_ret = msg_thread_send_wait_1(&drv_inst->msg_ctx,
+ INFRA_SUBDRV_OPID_CAL_DO_CAL, 0, CONNDRV_TYPE_BT);
+
+ pr_info("[pre_cal] driver [%s] calibration %s, ret=[%d]\n", drv_name[CONNDRV_TYPE_BT],
+ (bt_cal_ret == CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF ||
+ bt_cal_ret == CONNINFRA_CB_RET_CAL_FAIL_POWER_ON) ? "fail" : "success",
+ bt_cal_ret);
+
+ if (bt_cal_ret == CONNINFRA_CB_RET_CAL_PASS_POWER_OFF ||
+ bt_cal_ret == CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF)
+ conninfra_core_power_off(CONNDRV_TYPE_BT);
+
+ pr_info("[pre_cal] >>>>>>>> BT do cal done");
+
+ do_gettimeofday(&wf_cal_begin);
+
+ drv_inst = &g_conninfra_ctx.drv_inst[CONNDRV_TYPE_WIFI];
+ wf_cal_ret = msg_thread_send_wait_1(&drv_inst->msg_ctx,
+ INFRA_SUBDRV_OPID_CAL_DO_CAL, 0, CONNDRV_TYPE_WIFI);
+
+ pr_info("[pre_cal] driver [%s] calibration %s, ret=[%d]\n", drv_name[CONNDRV_TYPE_WIFI],
+ (wf_cal_ret == CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF ||
+ wf_cal_ret == CONNINFRA_CB_RET_CAL_FAIL_POWER_ON) ? "fail" : "success",
+ wf_cal_ret);
+
+ if (wf_cal_ret == CONNINFRA_CB_RET_CAL_PASS_POWER_OFF ||
+ wf_cal_ret == CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF)
+ conninfra_core_power_off(CONNDRV_TYPE_WIFI);
+
+ pr_info(">>>>>>>> WF do cal done");
+
+ do_gettimeofday(&end);
+
+ pr_info("[pre_cal] summary pwr=[%lu] bt_cal=[%d][%lu] wf_cal=[%d][%lu]",
+ timeval_to_ms(&begin, &bt_cal_begin),
+ bt_cal_ret, timeval_to_ms(&bt_cal_begin, &wf_cal_begin),
+ wf_cal_ret, timeval_to_ms(&wf_cal_begin, &end));
+
+ return 0;
+}
+
+
+static int opfunc_therm_ctrl(struct msg_op_data *op)
+{
+ static DEFINE_RATELIMIT_STATE(_rs, 10*HZ, 1);
+ int ret = -1;
+ int *data_ptr = (int*)op->op_data[0];
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ if (g_conninfra_ctx.infra_drv_status != DRV_STS_POWER_ON) {
+ *data_ptr = THERMAL_TEMP_INVALID;
+ return 0;
+ } else {
+ if (__ratelimit(&_rs)) {
+ pr_info("[Conn status] Conninfra=[%d] BT=[%d] FM=[%d] GPS=[%d] WF=[%d]",
+ infra_ctx->infra_drv_status,
+ infra_ctx->drv_inst[CONNDRV_TYPE_BT].drv_status,
+ infra_ctx->drv_inst[CONNDRV_TYPE_FM].drv_status,
+ infra_ctx->drv_inst[CONNDRV_TYPE_GPS].drv_status,
+ infra_ctx->drv_inst[CONNDRV_TYPE_WIFI].drv_status);
+ }
+ }
+
+ if (data_ptr)
+ ret = consys_hw_therm_query(data_ptr);
+ return ret;
+}
+
+
+static int opfunc_rfspi_read(struct msg_op_data *op)
+{
+ int ret = 0;
+ unsigned int data = 0;
+ unsigned int* data_pt = (unsigned int*)op->op_data[2];
+
+ ret = osal_lock_sleepable_lock(&g_conninfra_ctx.core_lock);
+ if (ret) {
+ pr_err("core_lock fail!!\n");
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+
+ if (g_conninfra_ctx.infra_drv_status != DRV_STS_POWER_ON) {
+ pr_err("Connsys didn't power on\n");
+ ret = CONNINFRA_SPI_OP_FAIL;
+ goto err;
+ }
+ if (consys_hw_reg_readable() == 0) {
+ pr_err("connsys reg not readable\n");
+ ret = CONNINFRA_SPI_OP_FAIL;
+ goto err;
+ }
+ /* DO read spi */
+ ret = consys_hw_spi_read(op->op_data[0], op->op_data[1], &data);
+ if (data_pt)
+ *(data_pt) = data;
+err:
+ osal_unlock_sleepable_lock(&g_conninfra_ctx.core_lock);
+ return ret;
+}
+
+static int opfunc_rfspi_write(struct msg_op_data *op)
+{
+ int ret = 0;
+
+ ret = osal_lock_sleepable_lock(&g_conninfra_ctx.core_lock);
+ if (ret) {
+ pr_err("core_lock fail!!\n");
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+
+ if (g_conninfra_ctx.infra_drv_status != DRV_STS_POWER_ON) {
+ pr_err("Connsys didn't power on\n");
+ ret = CONNINFRA_SPI_OP_FAIL;
+ goto err;
+ }
+ if (consys_hw_reg_readable() == 0) {
+ pr_err("connsys reg not readable\n");
+ ret = CONNINFRA_SPI_OP_FAIL;
+ goto err;
+ }
+ /* DO spi write */
+ ret = consys_hw_spi_write(op->op_data[0], op->op_data[1], op->op_data[2]);
+err:
+ osal_unlock_sleepable_lock(&g_conninfra_ctx.core_lock);
+ return ret;
+}
+
+static int opfunc_adie_top_ck_en_on(struct msg_op_data *op)
+{
+ int ret = 0;
+ unsigned int type = op->op_data[0];
+
+ if (type >= CONNSYS_ADIE_CTL_MAX) {
+ pr_err("wrong parameter %d\n", type);
+ return -EINVAL;
+ }
+
+ ret = osal_lock_sleepable_lock(&g_conninfra_ctx.core_lock);
+ if (ret) {
+ pr_err("core_lock fail!!\n");
+ ret = -1;
+ goto err;
+ }
+
+ if (g_conninfra_ctx.infra_drv_status != DRV_STS_POWER_ON) {
+ pr_err("Connsys didn't power on\n");
+ ret = -2;
+ goto err;
+ }
+
+ ret = consys_hw_adie_top_ck_en_on(type);
+
+err:
+ osal_unlock_sleepable_lock(&g_conninfra_ctx.core_lock);
+ return ret;
+}
+
+
+static int opfunc_adie_top_ck_en_off(struct msg_op_data *op)
+{
+ int ret = 0;
+ unsigned int type = op->op_data[0];
+
+ if (type >= CONNSYS_ADIE_CTL_MAX) {
+ pr_err("wrong parameter %d\n", type);
+ return -EINVAL;
+ }
+
+ ret = osal_lock_sleepable_lock(&g_conninfra_ctx.core_lock);
+ if (ret) {
+ pr_err("core_lock fail!!\n");
+ ret = -1;
+ goto err;
+ }
+ if (g_conninfra_ctx.infra_drv_status != DRV_STS_POWER_ON) {
+ pr_err("Connsys didn't power on\n");
+ ret = -2;
+ goto err;
+ }
+
+ ret = consys_hw_adie_top_ck_en_off(type);
+err:
+ osal_unlock_sleepable_lock(&g_conninfra_ctx.core_lock);
+ return ret;
+}
+
+static int opfunc_spi_clock_switch(struct msg_op_data *op)
+{
+ int ret = 0;
+ unsigned int type = op->op_data[0];
+
+ if (type >= CONNSYS_SPI_SPEED_MAX) {
+ pr_err("wrong parameter %d\n", type);
+ return -EINVAL;
+ }
+
+ ret = osal_lock_sleepable_lock(&g_conninfra_ctx.core_lock);
+ if (ret) {
+ pr_err("core_lock fail!!\n");
+ ret = -2;
+ goto err;
+ }
+ if (g_conninfra_ctx.infra_drv_status != DRV_STS_POWER_ON) {
+ pr_err("Connsys didn't power on\n");
+ ret = -2;
+ goto err;
+ }
+
+ ret = consys_hw_spi_clock_switch(type);
+err:
+ osal_unlock_sleepable_lock(&g_conninfra_ctx.core_lock);
+ return ret;
+}
+
+
+static int opfunc_clock_fail_dump(struct msg_op_data *op)
+{
+ consys_hw_clock_fail_dump();
+ return 0;
+}
+
+
+static int opfunc_pre_cal_prepare(struct msg_op_data *op)
+{
+ int ret, rst_status;
+ unsigned long flag;
+ struct pre_cal_info *cal_info = &g_conninfra_ctx.cal_info;
+ struct subsys_drv_inst *bt_drv = &g_conninfra_ctx.drv_inst[CONNDRV_TYPE_BT];
+ struct subsys_drv_inst *wifi_drv = &g_conninfra_ctx.drv_inst[CONNDRV_TYPE_WIFI];
+ enum pre_cal_status cur_status;
+
+ spin_lock_irqsave(&g_conninfra_ctx.infra_lock, flag);
+
+ if (bt_drv->ops_cb.pre_cal_cb.do_cal_cb == NULL ||
+ wifi_drv->ops_cb.pre_cal_cb.do_cal_cb == NULL) {
+ pr_info("[%s] [pre_cal] [%p][%p]", __func__,
+ bt_drv->ops_cb.pre_cal_cb.do_cal_cb,
+ wifi_drv->ops_cb.pre_cal_cb.do_cal_cb);
+ spin_unlock_irqrestore(&g_conninfra_ctx.infra_lock, flag);
+ return 0;
+ }
+ spin_unlock_irqrestore(&g_conninfra_ctx.infra_lock, flag);
+
+ spin_lock_irqsave(&g_conninfra_ctx.rst_lock, flag);
+ rst_status = g_conninfra_ctx.rst_status;
+ spin_unlock_irqrestore(&g_conninfra_ctx.rst_lock, flag);
+
+ if (rst_status > CHIP_RST_NONE) {
+ pr_info("rst is ongoing, skip pre_cal");
+ return 0;
+ }
+
+ /* non-zero means lock got, zero means not */
+ ret = osal_trylock_sleepable_lock(&cal_info->pre_cal_lock);
+
+ if (ret) {
+ cur_status = cal_info->status;
+
+ if ((cur_status == PRE_CAL_NOT_INIT || cur_status == PRE_CAL_NEED_RESCHEDULE) &&
+ bt_drv->drv_status == DRV_STS_POWER_OFF &&
+ wifi_drv->drv_status == DRV_STS_POWER_OFF) {
+ cal_info->status = PRE_CAL_SCHEDULED;
+ pr_info("[pre_cal] BT&WIFI is off, schedule pre-cal from status=[%d] to new status[%d]\n",
+ cur_status, cal_info->status);
+ schedule_work(&cal_info->pre_cal_work);
+ } else {
+ pr_info("[%s] [pre_cal] bt=[%d] wf=[%d] status=[%d]", __func__,
+ bt_drv->drv_status, wifi_drv->drv_status, cur_status);
+ }
+ osal_unlock_sleepable_lock(&cal_info->pre_cal_lock);
+ }
+
+ return 0;
+}
+
+static int opfunc_pre_cal_check(struct msg_op_data *op)
+{
+ int ret;
+ struct pre_cal_info *cal_info = &g_conninfra_ctx.cal_info;
+ struct subsys_drv_inst *bt_drv = &g_conninfra_ctx.drv_inst[CONNDRV_TYPE_BT];
+ struct subsys_drv_inst *wifi_drv = &g_conninfra_ctx.drv_inst[CONNDRV_TYPE_WIFI];
+ enum pre_cal_status cur_status;
+
+ /* non-zero means lock got, zero means not */
+ ret = osal_trylock_sleepable_lock(&cal_info->pre_cal_lock);
+ if (ret) {
+ cur_status = cal_info->status;
+
+ pr_info("[%s] [pre_cal] bt=[%d] wf=[%d] status=[%d]", __func__,
+ bt_drv->drv_status, wifi_drv->drv_status,
+ cur_status);
+ if (cur_status == PRE_CAL_DONE &&
+ bt_drv->drv_status == DRV_STS_POWER_OFF &&
+ wifi_drv->drv_status == DRV_STS_POWER_OFF) {
+ pr_info("[pre_cal] reset pre-cal");
+ cal_info->status = PRE_CAL_NEED_RESCHEDULE;
+ }
+ osal_unlock_sleepable_lock(&cal_info->pre_cal_lock);
+ }
+ return 0;
+}
+
+
+static int opfunc_force_conninfra_wakeup(struct msg_op_data *op)
+{
+ int ret;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ ret = osal_lock_sleepable_lock(&infra_ctx->core_lock);
+ if (ret) {
+ pr_err("core_lock fail!!");
+ return ret;
+ }
+
+ /* check if conninfra already on */
+ if (g_conninfra_ctx.infra_drv_status != DRV_STS_POWER_ON) {
+ ret = -1;
+ goto err;
+ }
+
+ ret = consys_hw_force_conninfra_wakeup();
+ if (ret)
+ pr_err("force conninfra wakeup fail");
+
+err:
+ osal_unlock_sleepable_lock(&infra_ctx->core_lock);
+ return ret;
+}
+
+static int opfunc_force_conninfra_sleep(struct msg_op_data *op)
+{
+ int ret;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ ret = osal_lock_sleepable_lock(&infra_ctx->core_lock);
+ if (ret) {
+ pr_err("core_lock fail!!");
+ return ret;
+ }
+
+ /* check if conninfra already on */
+ if (g_conninfra_ctx.infra_drv_status != DRV_STS_POWER_ON) {
+ ret = -1;
+ goto err;
+ }
+
+ ret = consys_hw_force_conninfra_sleep();
+ if (ret)
+ pr_err("force conninfra sleep fail");
+
+err:
+ osal_unlock_sleepable_lock(&infra_ctx->core_lock);
+ return ret;
+}
+
+
+static int opfunc_dump_power_state(struct msg_op_data *op)
+{
+ int ret;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ ret = osal_lock_sleepable_lock(&infra_ctx->core_lock);
+ if (ret) {
+ pr_err("core_lock fail!!");
+ return ret;
+ }
+
+ /* check if conninfra already on */
+ if (g_conninfra_ctx.infra_drv_status != DRV_STS_POWER_ON) {
+ ret = -1;
+ goto err;
+ }
+
+ ret = consys_hw_dump_power_state();
+ if (ret)
+ pr_err("dump power state fail");
+
+err:
+ osal_unlock_sleepable_lock(&infra_ctx->core_lock);
+ return ret;
+
+}
+
+static int opfunc_subdrv_pre_reset(struct msg_op_data *op)
+{
+ int ret, cur_rst_state;
+ unsigned int drv_type = op->op_data[0];
+ struct subsys_drv_inst *drv_inst;
+
+
+ /* TODO: should be locked, to avoid cb was reset */
+ drv_inst = &g_conninfra_ctx.drv_inst[drv_type];
+ if (/*drv_inst->drv_status == DRV_ST_POWER_ON &&*/
+ drv_inst->ops_cb.rst_cb.pre_whole_chip_rst) {
+
+ ret = drv_inst->ops_cb.rst_cb.pre_whole_chip_rst(g_conninfra_ctx.trg_drv,
+ g_conninfra_ctx.trg_reason);
+ if (ret)
+ pr_err("[%s] fail [%d]", __func__, ret);
+ }
+
+ atomic_add(0x1 << drv_type, &g_conninfra_ctx.rst_state);
+ cur_rst_state = atomic_read(&g_conninfra_ctx.rst_state);
+
+ pr_info("[%s] rst_state=[%d]", drv_thread_name[drv_type], cur_rst_state);
+
+ up(&g_conninfra_ctx.rst_sema);
+ return 0;
+}
+
+static int opfunc_subdrv_post_reset(struct msg_op_data *op)
+{
+ int ret;
+ unsigned int drv_type = op->op_data[0];
+ struct subsys_drv_inst *drv_inst;
+
+ /* TODO: should be locked, to avoid cb was reset */
+ drv_inst = &g_conninfra_ctx.drv_inst[drv_type];
+ if (/*drv_inst->drv_status == DRV_ST_POWER_ON &&*/
+ drv_inst->ops_cb.rst_cb.post_whole_chip_rst) {
+ ret = drv_inst->ops_cb.rst_cb.post_whole_chip_rst();
+ if (ret)
+ pr_warn("[%s] fail [%d]", __func__, ret);
+ }
+
+ atomic_add(0x1 << drv_type, &g_conninfra_ctx.rst_state);
+ up(&g_conninfra_ctx.rst_sema);
+ return 0;
+}
+
+static int opfunc_subdrv_cal_pwr_on(struct msg_op_data *op)
+{
+ int ret;
+ unsigned int drv_type = op->op_data[0];
+ struct subsys_drv_inst *drv_inst;
+
+ pr_info("[%s] drv=[%s]", __func__, drv_thread_name[drv_type]);
+
+ /* TODO: should be locked, to avoid cb was reset */
+ drv_inst = &g_conninfra_ctx.drv_inst[drv_type];
+ if (/*drv_inst->drv_status == DRV_ST_POWER_ON &&*/
+ drv_inst->ops_cb.pre_cal_cb.pwr_on_cb) {
+ ret = drv_inst->ops_cb.pre_cal_cb.pwr_on_cb();
+ if (ret)
+ pr_warn("[%s] fail [%d]", __func__, ret);
+ }
+
+ atomic_add(0x1 << drv_type, &g_conninfra_ctx.pre_cal_state);
+ up(&g_conninfra_ctx.pre_cal_sema);
+
+ pr_info("[pre_cal][%s] [%s] DONE", __func__, drv_thread_name[drv_type]);
+ return 0;
+}
+
+static int opfunc_subdrv_cal_do_cal(struct msg_op_data *op)
+{
+ int ret;
+ unsigned int drv_type = op->op_data[0];
+ struct subsys_drv_inst *drv_inst;
+
+ pr_info("[%s] drv=[%s]", __func__, drv_thread_name[drv_type]);
+
+ drv_inst = &g_conninfra_ctx.drv_inst[drv_type];
+ if (/*drv_inst->drv_status == DRV_ST_POWER_ON &&*/
+ drv_inst->ops_cb.pre_cal_cb.do_cal_cb) {
+ ret = drv_inst->ops_cb.pre_cal_cb.do_cal_cb();
+ if (ret)
+ pr_warn("[%s] fail [%d]", __func__, ret);
+ }
+
+ pr_info("[pre_cal][%s] [%s] DONE", __func__, drv_thread_name[drv_type]);
+ return 0;
+}
+
+static int opfunc_subdrv_therm_ctrl(struct msg_op_data *op)
+{
+ return 0;
+}
+
+
+/*
+ * CONNINFRA API
+ */
+int conninfra_core_power_on(enum consys_drv_type type)
+{
+ int ret = 0;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ ret = msg_thread_send_wait_1(&infra_ctx->msg_ctx,
+ CONNINFRA_OPID_PWR_ON, 0, type);
+ if (ret) {
+ pr_err("[%s] fail, ret = %d\n", __func__, ret);
+ return -1;
+ }
+ return 0;
+}
+
+int conninfra_core_power_off(enum consys_drv_type type)
+{
+ int ret = 0;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ ret = msg_thread_send_wait_1(&infra_ctx->msg_ctx,
+ CONNINFRA_OPID_PWR_OFF, 0, type);
+ if (ret) {
+ pr_err("[%s] send msg fail, ret = %d\n", __func__, ret);
+ return -1;
+ }
+ return 0;
+}
+
+int conninfra_core_pre_cal_start(void)
+{
+ int ret = 0;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+ struct pre_cal_info *cal_info = &infra_ctx->cal_info;
+
+ ret = osal_lock_sleepable_lock(&cal_info->pre_cal_lock);
+ if (ret) {
+ pr_err("[%s] get lock fail, ret = %d\n",
+ __func__, ret);
+ return -1;
+ }
+ cal_info->status = PRE_CAL_EXECUTING;
+ ret = msg_thread_send_wait(&infra_ctx->cb_ctx,
+ CONNINFRA_CB_OPID_PRE_CAL, 0);
+ if (ret) {
+ pr_err("[%s] send msg fail, ret = %d\n", __func__, ret);
+ }
+
+ cal_info->status = PRE_CAL_DONE;
+ osal_unlock_sleepable_lock(&cal_info->pre_cal_lock);
+ return 0;
+}
+
+int conninfra_core_screen_on(void)
+{
+#if CFG_CONNINFRA_PRE_CAL_SUPPORT
+ int ret = 0, rst_status;
+ unsigned long flag;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ spin_lock_irqsave(&infra_ctx->rst_lock, flag);
+ rst_status = g_conninfra_ctx.rst_status;
+ spin_unlock_irqrestore(&infra_ctx->rst_lock, flag);
+
+ if (rst_status > CHIP_RST_NONE) {
+ pr_info("rst is ongoing, skip pre_cal");
+ return 0;
+ }
+
+ ret = msg_thread_send(&infra_ctx->msg_ctx,
+ CONNINFRA_OPID_PRE_CAL_PREPARE);
+ if (ret) {
+ pr_err("[%s] send msg fail, ret = %d\n", __func__, ret);
+ return -1;
+ }
+#endif /* CFG_CONNINFRA_PRE_CAL_SUPPORT */
+ return 0;
+}
+
+int conninfra_core_screen_off(void)
+{
+ int ret = 0;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ ret = msg_thread_send(&infra_ctx->msg_ctx,
+ CONNINFRA_OPID_PRE_CAL_CHECK);
+ if (ret) {
+ pr_err("[%s] send msg fail, ret = %d\n", __func__, ret);
+ return -1;
+ }
+
+ return 0;
+}
+
+int conninfra_core_reg_readable(void)
+{
+ int ret = 0, rst_status;
+ unsigned long flag;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+
+ /* check if in reseting, can not read */
+ spin_lock_irqsave(&g_conninfra_ctx.rst_lock, flag);
+ rst_status = g_conninfra_ctx.rst_status;
+ spin_unlock_irqrestore(&g_conninfra_ctx.rst_lock, flag);
+
+ if (rst_status >= CHIP_RST_RESET &&
+ rst_status < CHIP_RST_POST_CB)
+ return 0;
+
+ ret = osal_lock_sleepable_lock(&infra_ctx->core_lock);
+ if (ret) {
+ pr_err("core_lock fail!!");
+ return 0;
+ }
+
+ if (infra_ctx->infra_drv_status == DRV_STS_POWER_ON)
+ ret = consys_hw_reg_readable();
+ osal_unlock_sleepable_lock(&infra_ctx->core_lock);
+
+ return ret;
+}
+
+int conninfra_core_reg_readable_no_lock(void)
+{
+ int rst_status;
+ unsigned long flag;
+
+ /* check if in reseting, can not read */
+ spin_lock_irqsave(&g_conninfra_ctx.rst_lock, flag);
+ rst_status = g_conninfra_ctx.rst_status;
+ spin_unlock_irqrestore(&g_conninfra_ctx.rst_lock, flag);
+
+ if (rst_status >= CHIP_RST_RESET &&
+ rst_status < CHIP_RST_POST_CB)
+ return 0;
+
+ return consys_hw_reg_readable();
+}
+
+int conninfra_core_is_bus_hang(void)
+{
+ int ret = 0;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ ret = osal_lock_sleepable_lock(&infra_ctx->core_lock);
+ if (ret) {
+ pr_err("core_lock fail!!");
+ return 0;
+ }
+
+ if (infra_ctx->infra_drv_status == DRV_STS_POWER_ON)
+ ret = consys_hw_is_bus_hang();
+ osal_unlock_sleepable_lock(&infra_ctx->core_lock);
+
+ return ret;
+
+}
+
+int conninfra_core_is_consys_reg(phys_addr_t addr)
+{
+ return consys_hw_is_connsys_reg(addr);
+}
+
+int conninfra_core_reg_read(unsigned long address, unsigned int *value, unsigned int mask)
+{
+ int ret = 0;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ ret = osal_lock_sleepable_lock(&infra_ctx->core_lock);
+ if (ret) {
+ pr_err("core_lock fail!!");
+ return 0;
+ }
+
+ if (infra_ctx->infra_drv_status == DRV_STS_POWER_ON) {
+ if (consys_reg_mng_is_host_csr(address))
+ ret = consys_reg_mng_reg_read(address, value, mask);
+ else if (consys_hw_reg_readable())
+ ret = consys_reg_mng_reg_read(address, value, mask);
+ else
+ pr_info("CR (%lx) is not readable\n", address);
+ } else
+ pr_info("CR (%lx) cannot read. conninfra is off\n", address);
+
+ osal_unlock_sleepable_lock(&infra_ctx->core_lock);
+ return ret;
+}
+
+int conninfra_core_reg_write(unsigned long address, unsigned int value, unsigned int mask)
+{
+ int ret = 0;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ ret = osal_lock_sleepable_lock(&infra_ctx->core_lock);
+ if (ret) {
+ pr_err("core_lock fail!!");
+ return 0;
+ }
+
+ if (infra_ctx->infra_drv_status == DRV_STS_POWER_ON) {
+ if (consys_reg_mng_is_host_csr(address))
+ ret = consys_reg_mng_reg_write(address, value, mask);
+ else if (consys_hw_reg_readable())
+ ret = consys_reg_mng_reg_write(address, value, mask);
+ else
+ pr_info("CR (%p) is not readable\n", (void*)address);
+ } else
+ pr_info("CR (%p) cannot read. conninfra is off\n", (void*)address);
+
+ osal_unlock_sleepable_lock(&infra_ctx->core_lock);
+ return ret;
+
+}
+
+int conninfra_core_lock_rst(void)
+{
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+ int ret = 0;
+ unsigned long flag;
+
+ spin_lock_irqsave(&infra_ctx->rst_lock, flag);
+
+ ret = infra_ctx->rst_status;
+ if (infra_ctx->rst_status > CHIP_RST_NONE &&
+ infra_ctx->rst_status < CHIP_RST_DONE) {
+ /* do nothing */
+ } else {
+ infra_ctx->rst_status = CHIP_RST_START;
+ }
+ spin_unlock_irqrestore(&infra_ctx->rst_lock, flag);
+
+ pr_info("[%s] ret=[%d]", __func__, ret);
+ return ret;
+}
+
+int conninfra_core_unlock_rst(void)
+{
+ unsigned long flag;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ spin_lock_irqsave(&infra_ctx->rst_lock, flag);
+ infra_ctx->rst_status = CHIP_RST_NONE;
+ spin_unlock_irqrestore(&infra_ctx->rst_lock, flag);
+ return 0;
+}
+
+int conninfra_core_trg_chip_rst(enum consys_drv_type drv, char *reason)
+{
+ int ret = 0;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ infra_ctx->trg_drv = drv;
+ snprintf(infra_ctx->trg_reason, CHIP_RST_REASON_MAX_LEN, "%s", reason);
+ ret = msg_thread_send_1(&infra_ctx->cb_ctx,
+ CONNINFRA_CB_OPID_CHIP_RST, drv);
+ if (ret) {
+ pr_err("[%s] send msg fail, ret = %d", __func__, ret);
+ return -1;
+ }
+ pr_info("trg_reset DONE!");
+ return 0;
+}
+
+int conninfra_core_thermal_query(int *temp_val)
+{
+ int ret = 0;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ ret = msg_thread_send_wait_1(&infra_ctx->msg_ctx,
+ CONNINFRA_OPID_THERM_CTRL, 0,
+ (size_t) temp_val);
+ if (ret) {
+ pr_err("send msg fail ret=%d\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+void conninfra_core_clock_fail_dump_cb(void)
+{
+ int ret = 0;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ ret = msg_thread_send(&infra_ctx->msg_ctx,
+ CONNINFRA_OPID_CLOCK_FAIL_DUMP);
+ if (ret)
+ pr_err("failed (ret = %d)", ret);
+}
+
+static inline char* conninfra_core_spi_subsys_string(enum sys_spi_subsystem subsystem)
+{
+ static char* subsys_name[] = {
+ "SYS_SPI_WF1",
+ "SYS_SPI_WF",
+ "SYS_SPI_BT",
+ "SYS_SPI_FM",
+ "SYS_SPI_GPS",
+ "SYS_SPI_TOP",
+ "SYS_SPI_WF2",
+ "SYS_SPI_WF3",
+ "SYS_SPI_MAX"
+ };
+ return subsys_name[subsystem];
+}
+
+int conninfra_core_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data)
+{
+ int ret = 0;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+ size_t data_ptr = (size_t)data;
+
+ ret = msg_thread_send_wait_3(&infra_ctx->msg_ctx,
+ CONNINFRA_OPID_RFSPI_READ, 0,
+ subsystem, addr, data_ptr);
+ if (ret) {
+ pr_err("[%s] failed (ret = %d). subsystem=%s addr=%x\n",
+ __func__, ret, conninfra_core_spi_subsys_string(subsystem), addr);
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+ return 0;
+}
+
+int conninfra_core_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data)
+{
+ int ret;
+ ret = msg_thread_send_wait_3(&(g_conninfra_ctx.msg_ctx), CONNINFRA_OPID_RFSPI_WRITE, 0,
+ subsystem, addr, data);
+ if (ret) {
+ pr_err("[%s] failed (ret = %d). subsystem=%s addr=0x%x data=%d\n",
+ __func__, ret, conninfra_core_spi_subsys_string(subsystem), addr, data);
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+ return 0;
+}
+
+int conninfra_core_adie_top_ck_en_on(enum consys_adie_ctl_type type)
+{
+ int ret = 0;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ ret = msg_thread_send_wait_1(&infra_ctx->msg_ctx,
+ CONNINFRA_OPID_ADIE_TOP_CK_EN_ON, 0, type);
+ if (ret) {
+ pr_err("[%s] fail, ret = %d\n", __func__, ret);
+ return -1;
+ }
+ return 0;
+}
+
+int conninfra_core_adie_top_ck_en_off(enum consys_adie_ctl_type type)
+{
+ int ret = 0;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ ret = msg_thread_send_wait_1(&infra_ctx->msg_ctx,
+ CONNINFRA_OPID_ADIE_TOP_CK_EN_OFF, 0, type);
+ if (ret) {
+ pr_err("[%s] fail, ret = %d\n", __func__, ret);
+ return -1;
+ }
+ return 0;
+}
+
+int conninfra_core_force_conninfra_wakeup(void)
+{
+ int ret = 0;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ /* if in conninfra_cored thread */
+ if (current == infra_ctx->msg_ctx.thread.pThread)
+ return opfunc_force_conninfra_wakeup(NULL);
+
+ ret = msg_thread_send_wait(&infra_ctx->msg_ctx,
+ CONNINFRA_OPID_FORCE_CONNINFRA_WAKUP, 0);
+ if (ret) {
+ pr_err("[%s] fail, ret = %d\n", __func__, ret);
+ return -1;
+ }
+ return 0;
+}
+
+int conninfra_core_force_conninfra_sleep(void)
+{
+ int ret = 0;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ /* if in conninfra_cored thread */
+ if (current == infra_ctx->msg_ctx.thread.pThread)
+ return opfunc_force_conninfra_sleep(NULL);
+
+ ret = msg_thread_send_wait(&infra_ctx->msg_ctx,
+ CONNINFRA_OPID_FORCE_CONNINFRA_SLEEP, 0);
+ if (ret) {
+ pr_err("[%s] fail, ret = %d\n", __func__, ret);
+ return -1;
+ }
+ return 0;
+}
+
+int conninfra_core_spi_clock_switch(enum connsys_spi_speed_type type)
+{
+ int ret = 0;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ ret = msg_thread_send_wait_1(&infra_ctx->msg_ctx,
+ CONNINFRA_OPID_SPI_CLOCK_SWITCH, 0, type);
+ if (ret) {
+ pr_err("[%s] fail, ret = %d\n", __func__, ret);
+ return -1;
+ }
+ return 0;
+}
+
+int conninfra_core_subsys_ops_reg(enum consys_drv_type type,
+ struct sub_drv_ops_cb *cb)
+{
+ unsigned long flag;
+ struct subsys_drv_inst *drv_inst;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+ int ret, trigger_pre_cal = 0;
+
+
+ spin_lock_irqsave(&g_conninfra_ctx.infra_lock, flag);
+ drv_inst = &g_conninfra_ctx.drv_inst[type];
+ memcpy(&g_conninfra_ctx.drv_inst[type].ops_cb, cb,
+ sizeof(struct sub_drv_ops_cb));
+
+ pr_info("[%s] [pre_cal] type=[%s] cb rst=[%p][%p] pre_cal=[%p][%p], therm=[%p]",
+ __func__, drv_name[type],
+ cb->rst_cb.pre_whole_chip_rst, cb->rst_cb.post_whole_chip_rst,
+ cb->pre_cal_cb.pwr_on_cb, cb->pre_cal_cb.do_cal_cb, cb->thermal_qry);
+
+#if CFG_CONNINFRA_PRE_CAL_SUPPORT
+ pr_info("[%s] [pre_cal] type=[%d] bt=[%p] wf=[%p]", __func__, type,
+ infra_ctx->drv_inst[CONNDRV_TYPE_BT].ops_cb.pre_cal_cb.pwr_on_cb,
+ infra_ctx->drv_inst[CONNDRV_TYPE_WIFI].ops_cb.pre_cal_cb.pwr_on_cb);
+
+ /* trigger pre-cal if BT and WIFI are registered */
+ if (infra_ctx->drv_inst[CONNDRV_TYPE_BT].ops_cb.pre_cal_cb.do_cal_cb != NULL &&
+ infra_ctx->drv_inst[CONNDRV_TYPE_WIFI].ops_cb.pre_cal_cb.do_cal_cb != NULL)
+ trigger_pre_cal = 1;
+#endif /* CFG_CONNINFRA_PRE_CAL_SUPPORT */
+
+ spin_unlock_irqrestore(&g_conninfra_ctx.infra_lock, flag);
+
+ if (trigger_pre_cal) {
+ pr_info("[%s] [pre_cal] trigger pre-cal BT/WF are registered", __func__);
+ ret = msg_thread_send(&infra_ctx->msg_ctx,
+ CONNINFRA_OPID_PRE_CAL_PREPARE);
+ if (ret)
+ pr_err("send pre_cal_prepare msg fail, ret = %d\n", ret);
+ }
+
+ return 0;
+}
+
+int conninfra_core_subsys_ops_unreg(enum consys_drv_type type)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&g_conninfra_ctx.infra_lock, flag);
+ memset(&g_conninfra_ctx.drv_inst[type].ops_cb, 0,
+ sizeof(struct sub_drv_ops_cb));
+ spin_unlock_irqrestore(&g_conninfra_ctx.infra_lock, flag);
+
+ return 0;
+}
+
+#if CFG_CONNINFRA_PRE_CAL_BLOCKING
+void conninfra_core_pre_cal_blocking(void)
+{
+#define BLOCKING_CHECK_MONITOR_THREAD 100
+ int ret;
+ struct pre_cal_info *cal_info = &g_conninfra_ctx.cal_info;
+ struct timeval start, end;
+ unsigned long diff;
+
+ do_gettimeofday(&start);
+
+ /* non-zero means lock got, zero means not */
+ while (true) {
+ ret = osal_trylock_sleepable_lock(&cal_info->pre_cal_lock);
+ if (ret) {
+ if (cal_info->status == PRE_CAL_NOT_INIT ||
+ cal_info->status == PRE_CAL_SCHEDULED) {
+ pr_info("[%s] [pre_cal] ret=[%d] status=[%d]", __func__, ret, cal_info->status);
+ osal_unlock_sleepable_lock(&cal_info->pre_cal_lock);
+ osal_sleep_ms(100);
+ continue;
+ }
+ osal_unlock_sleepable_lock(&cal_info->pre_cal_lock);
+ break;
+ } else {
+ pr_info("[%s] [pre_cal] ret=[%d] status=[%d]", __func__, ret, cal_info->status);
+ osal_sleep_ms(100);
+ }
+ }
+ do_gettimeofday(&end);
+
+ diff = timeval_to_ms(&start, &end);
+ if (diff > BLOCKING_CHECK_MONITOR_THREAD)
+ pr_info("blocking spent [%lu]", diff);
+}
+#endif /* CFG_CONNINFRA_PRE_CAL_BLOCKING */
+
+
+static void _conninfra_core_update_rst_status(enum chip_rst_status status)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&g_conninfra_ctx.rst_lock, flag);
+ g_conninfra_ctx.rst_status = status;
+ spin_unlock_irqrestore(&g_conninfra_ctx.rst_lock, flag);
+}
+
+
+int conninfra_core_is_rst_locking(void)
+{
+ unsigned long flag;
+ int ret = 0;
+
+ spin_lock_irqsave(&g_conninfra_ctx.rst_lock, flag);
+
+ if (g_conninfra_ctx.rst_status > CHIP_RST_NONE &&
+ g_conninfra_ctx.rst_status < CHIP_RST_POST_CB)
+ ret = 1;
+ spin_unlock_irqrestore(&g_conninfra_ctx.rst_lock, flag);
+ return ret;
+}
+
+static void conninfra_core_pre_cal_work_handler(struct work_struct *work)
+{
+ int ret;
+
+ /* if fail, do we need re-try? */
+ ret = conninfra_core_pre_cal_start();
+ pr_info("[%s] [pre_cal][ret=%d] -----------", __func__, ret);
+}
+
+
+int conninfra_core_dump_power_state(void)
+{
+ int ret = 0;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ ret = msg_thread_send(&infra_ctx->msg_ctx,
+ CONNINFRA_OPID_DUMP_POWER_STATE);
+ if (ret) {
+ pr_err("[%s] fail, ret = %d\n", __func__, ret);
+ return -1;
+ }
+ return 0;
+
+}
+
+void conninfra_core_config_setup(void)
+{
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+ int ret;
+
+ ret = osal_lock_sleepable_lock(&infra_ctx->core_lock);
+ if (ret) {
+ pr_err("[%s] core_lock fail!!\n", __func__);
+ return;
+ }
+
+ if (infra_ctx->infra_drv_status == DRV_STS_POWER_ON)
+ consys_hw_config_setup();
+
+ osal_unlock_sleepable_lock(&infra_ctx->core_lock);
+}
+
+int conninfra_core_pmic_event_cb(unsigned int id, unsigned int event)
+{
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+ int ret;
+
+ if (conninfra_core_is_rst_locking()) {
+ return 0;
+ }
+
+ ret = osal_lock_sleepable_lock(&infra_ctx->core_lock);
+ if (ret) {
+ pr_err("[%s] core_lock fail!!\n", __func__);
+ return 0;
+ }
+
+ if (infra_ctx->infra_drv_status == DRV_STS_POWER_ON)
+ consys_hw_pmic_event_cb(id, event);
+
+ osal_unlock_sleepable_lock(&infra_ctx->core_lock);
+
+ return 0;
+}
+
+int conninfra_core_bus_clock_ctrl(enum consys_drv_type drv_type, unsigned int bus_clock, int status)
+{
+ int ret = -1, rst_status;
+ unsigned long flag;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ /* check if in reseting, can not read */
+ spin_lock_irqsave(&g_conninfra_ctx.rst_lock, flag);
+ rst_status = g_conninfra_ctx.rst_status;
+ spin_unlock_irqrestore(&g_conninfra_ctx.rst_lock, flag);
+
+ if (rst_status >= CHIP_RST_RESET &&
+ rst_status < CHIP_RST_POST_CB)
+ return -1;
+
+ ret = osal_lock_sleepable_lock(&infra_ctx->core_lock);
+ if (ret) {
+ pr_err("[%s] core_lock fail!!", __func__);
+ return -1;
+ }
+
+ if (infra_ctx->infra_drv_status == DRV_STS_POWER_ON)
+ ret = consys_hw_bus_clock_ctrl(drv_type, bus_clock, status);
+ osal_unlock_sleepable_lock(&infra_ctx->core_lock);
+
+ return ret;
+}
+
+int conninfra_core_debug_dump(void)
+{
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+ int ret = -1;
+ unsigned int i;
+
+ ret = osal_lock_sleepable_lock(&infra_ctx->core_lock);
+ if (ret) {
+ pr_err("[%s] core_lock fail, ret=%d", __func__, ret);
+ return -1;
+ }
+
+ pr_info("%s\n", __func__);
+ msg_thread_dump(&infra_ctx->msg_ctx);
+ msg_thread_dump(&infra_ctx->cb_ctx);
+ for (i = 0; i < CONNDRV_TYPE_MAX; i++) {
+ msg_thread_dump(&(infra_ctx->drv_inst[i].msg_ctx));
+ }
+
+ osal_unlock_sleepable_lock(&infra_ctx->core_lock);
+
+ return ret;
+}
+
+int conninfra_core_init(void)
+{
+ int ret = 0, i;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ osal_memset(&g_conninfra_ctx, 0, sizeof(g_conninfra_ctx));
+
+ reset_chip_rst_trg_data();
+
+ spin_lock_init(&infra_ctx->infra_lock);
+ osal_sleepable_lock_init(&infra_ctx->core_lock);
+ spin_lock_init(&infra_ctx->rst_lock);
+
+
+ ret = msg_thread_init(&infra_ctx->msg_ctx, "conninfra_cored",
+ conninfra_core_opfunc, CONNINFRA_OPID_MAX);
+ if (ret) {
+ pr_err("msg_thread init fail(%d)\n", ret);
+ return -1;
+ }
+
+ ret = msg_thread_init(&infra_ctx->cb_ctx, "conninfra_cb",
+ conninfra_core_cb_opfunc, CONNINFRA_CB_OPID_MAX);
+ if (ret) {
+ pr_err("callback msg thread init fail(%d)\n", ret);
+ return -1;
+ }
+ /* init subsys drv state */
+ for (i = 0; i < CONNDRV_TYPE_MAX; i++) {
+ ret += msg_thread_init(&infra_ctx->drv_inst[i].msg_ctx,
+ drv_thread_name[i], infra_subdrv_opfunc,
+ INFRA_SUBDRV_OPID_MAX);
+ }
+
+ if (ret) {
+ pr_err("subsys callback thread init fail.\n");
+ return -1;
+ }
+
+ INIT_WORK(&infra_ctx->cal_info.pre_cal_work, conninfra_core_pre_cal_work_handler);
+ osal_sleepable_lock_init(&infra_ctx->cal_info.pre_cal_lock);
+
+ return ret;
+}
+
+
+int conninfra_core_deinit(void)
+{
+ int ret, i;
+ struct conninfra_ctx *infra_ctx = &g_conninfra_ctx;
+
+ osal_sleepable_lock_deinit(&infra_ctx->cal_info.pre_cal_lock);
+
+ for (i = 0; i < CONNDRV_TYPE_MAX; i++) {
+ ret = msg_thread_deinit(&infra_ctx->drv_inst[i].msg_ctx);
+ if (ret)
+ pr_warn("subdrv [%d] msg_thread deinit fail (%d)\n",
+ i, ret);
+ }
+
+ ret = msg_thread_deinit(&infra_ctx->msg_ctx);
+ if (ret) {
+ pr_err("msg_thread_deinit fail(%d)\n", ret);
+ return -1;
+ }
+
+ osal_sleepable_lock_deinit(&infra_ctx->core_lock);
+ //osal_sleepable_lock_deinit(&infra_ctx->rst_lock);
+
+ return 0;
+}
+
+
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/core/include/conninfra_core.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/core/include/conninfra_core.h
new file mode 100755
index 0000000..2c1e3e2
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/core/include/conninfra_core.h
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _CONNINFRA_CORE_H_
+#define _CONNINFRA_CORE_H_
+
+#include <linux/semaphore.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/time.h>
+
+#include "osal.h"
+#include "msg_thread.h"
+#include "conninfra.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+#define CHIP_RST_REASON_MAX_LEN 128
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+typedef enum _ENUM_DRV_STS_ {
+ DRV_STS_POWER_OFF = 0, /* initial state */
+ DRV_STS_POWER_ON = 1, /* powered on */
+ DRV_STS_RESET = 2,
+ DRV_STS_MAX
+} ENUM_DRV_STS, *P_ENUM_DRV_STS;
+
+enum pre_cal_status {
+ PRE_CAL_NOT_INIT = 0,
+ PRE_CAL_NEED_RESCHEDULE = 1,
+ PRE_CAL_SCHEDULED = 2,
+ PRE_CAL_EXECUTING = 3,
+ PRE_CAL_DONE = 4
+};
+
+enum chip_rst_status {
+ CHIP_RST_NONE = 0,
+ CHIP_RST_START = 1,
+ CHIP_RST_PRE_CB = 2,
+ CHIP_RST_RESET = 3,
+ CHIP_RST_POST_CB = 4,
+ CHIP_RST_DONE = 5
+};
+
+struct subsys_drv_inst {
+ ENUM_DRV_STS drv_status; /* Controlled driver status */
+ unsigned int rst_state;
+ struct sub_drv_ops_cb ops_cb;
+ struct msg_thread_ctx msg_ctx;
+};
+
+struct pre_cal_info {
+ enum pre_cal_status status;
+ struct work_struct pre_cal_work;
+ OSAL_SLEEPABLE_LOCK pre_cal_lock;
+};
+
+
+/*
+ * state of conninfra
+ *
+ */
+struct conninfra_ctx {
+ ENUM_DRV_STS infra_drv_status;
+
+ struct subsys_drv_inst drv_inst[CONNDRV_TYPE_MAX];
+ /*struct spinlock infra_lock;*/
+ spinlock_t infra_lock;
+
+ OSAL_SLEEPABLE_LOCK core_lock;
+
+ /* chip reset */
+ enum chip_rst_status rst_status;
+ spinlock_t rst_lock;
+
+ struct semaphore rst_sema;
+ atomic_t rst_state;
+ enum consys_drv_type trg_drv;
+ char trg_reason[CHIP_RST_REASON_MAX_LEN];
+
+ /* pre_cal */
+ struct semaphore pre_cal_sema;
+ atomic_t pre_cal_state;
+
+ struct msg_thread_ctx msg_ctx;
+ struct msg_thread_ctx cb_ctx;
+
+ unsigned int hw_ver;
+ unsigned int fw_ver;
+ unsigned int ip_ver;
+
+ struct pre_cal_info cal_info;
+
+};
+
+//typedef enum _ENUM_CONNINFRA_CORE_OPID_T {
+typedef enum {
+ CONNINFRA_OPID_PWR_ON = 0,
+ CONNINFRA_OPID_PWR_OFF = 1,
+ CONNINFRA_OPID_THERM_CTRL = 2,
+ CONNINFRA_OPID_RFSPI_READ = 5,
+ CONNINFRA_OPID_RFSPI_WRITE = 6,
+ CONNINFRA_OPID_ADIE_TOP_CK_EN_ON = 7,
+ CONNINFRA_OPID_ADIE_TOP_CK_EN_OFF = 8,
+ CONNINFRA_OPID_SPI_CLOCK_SWITCH = 9,
+ CONNINFRA_OPID_CLOCK_FAIL_DUMP = 10,
+ CONNINFRA_OPID_PRE_CAL_PREPARE = 11,
+ CONNINFRA_OPID_PRE_CAL_CHECK = 12,
+ CONNINFRA_OPID_FORCE_CONNINFRA_WAKUP = 13,
+ CONNINFRA_OPID_FORCE_CONNINFRA_SLEEP = 14,
+ CONNINFRA_OPID_DUMP_POWER_STATE = 15,
+ CONNINFRA_OPID_MAX
+} conninfra_core_opid;
+
+/* For the operation which may callback subsys driver */
+typedef enum {
+ CONNINFRA_CB_OPID_CHIP_RST = 0,
+ CONNINFRA_CB_OPID_PRE_CAL = 1,
+ CONNINFRA_CB_OPID_MAX
+} conninfra_core_cb_opid;
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+extern int conninfra_core_init(void);
+extern int conninfra_core_deinit(void);
+
+int conninfra_core_power_on(enum consys_drv_type type);
+int conninfra_core_power_off(enum consys_drv_type type);
+
+int conninfra_core_lock_rst(void);
+int conninfra_core_unlock_rst(void);
+int conninfra_core_trg_chip_rst(enum consys_drv_type drv, char *reason);
+
+int conninfra_core_subsys_ops_reg(enum consys_drv_type type,
+ struct sub_drv_ops_cb *cb);
+int conninfra_core_subsys_ops_unreg(enum consys_drv_type type);
+
+
+int conninfra_core_screen_on(void);
+int conninfra_core_screen_off(void);
+
+/* pre_cal */
+int conninfra_core_pre_cal_start(void);
+#if CFG_CONNINFRA_PRE_CAL_BLOCKING
+void conninfra_core_pre_cal_blocking(void);
+#endif
+
+/* reg control */
+/* NOTE: NOT thread-safe
+ * return value
+ * 1 : Yes, 0: NO
+ */
+int conninfra_core_reg_readable(void);
+int conninfra_core_reg_readable_no_lock(void);
+int conninfra_core_is_bus_hang(void);
+
+int conninfra_core_is_consys_reg(phys_addr_t addr);
+int conninfra_core_reg_read(unsigned long address, unsigned int *value, unsigned int mask);
+int conninfra_core_reg_write(unsigned long address, unsigned int value, unsigned int mask);
+
+int conninfra_core_is_rst_locking(void);
+
+int conninfra_core_thermal_query(int *temp_val);
+void conninfra_core_clock_fail_dump_cb(void);
+
+int conninfra_core_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data);
+int conninfra_core_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data);
+
+int conninfra_core_adie_top_ck_en_on(enum consys_adie_ctl_type type);
+int conninfra_core_adie_top_ck_en_off(enum consys_adie_ctl_type type);
+
+int conninfra_core_force_conninfra_wakeup(void);
+int conninfra_core_force_conninfra_sleep(void);
+
+int conninfra_core_spi_clock_switch(enum connsys_spi_speed_type type);
+
+int conninfra_core_dump_power_state(void);
+int conninfra_core_pmic_event_cb(unsigned int, unsigned int);
+
+void conninfra_core_config_setup(void);
+
+int conninfra_core_bus_clock_ctrl(enum consys_drv_type drv_type, unsigned int bus_clock, int status);
+
+int conninfra_core_debug_dump(void);
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _CONNINFRA_CORE_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/conninfra_dbg.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/conninfra_dbg.c
new file mode 100644
index 0000000..83df214
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/conninfra_dbg.c
@@ -0,0 +1,600 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include "osal.h"
+#include "conninfra_dbg.h"
+#include "conninfra.h"
+#include "conninfra_core.h"
+#include "emi_mng.h"
+#if CFG_CONNINFRA_COREDUMP_SUPPORT
+#include "connsys_debug_utility.h"
+#endif
+
+#define CONNINFRA_DBG_PROCNAME "driver/conninfra_dbg"
+
+#define BUF_LEN_MAX 384
+
+static struct proc_dir_entry *g_conninfra_dbg_entry;
+
+static ssize_t conninfra_dbg_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos);
+static ssize_t conninfra_dbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos);
+
+static int conninfra_dbg_hwver_get(int par1, int par2, int par3);
+
+static int conninfra_dbg_chip_rst(int par1, int par2, int par3);
+
+static int conninfra_dbg_read_chipid(int par1, int par2, int par3);
+
+static int conninfra_dbg_force_conninfra_wakeup(int par1, int par2, int par3);
+static int conninfra_dbg_force_conninfra_sleep(int par1, int par2, int par3);
+
+static int conninfra_dbg_reg_read(int par1, int par2, int par3);
+static int conninfra_dbg_reg_write(int par1, int par2, int par3);
+
+static int conninfra_dbg_efuse_read(int par1, int par2, int par3);
+static int conninfra_dbg_efuse_write(int par1, int par2, int par3);
+
+static int conninfra_dbg_ap_reg_read(int par1, int par2, int par3);
+static int conninfra_dbg_ap_reg_write(int par1, int par2, int par3);
+
+
+#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH
+/* consys log, need this ?? */
+static int conninfra_dbg_set_fw_log_mode(int par1, int par2, int par3);
+static int conninfra_dbg_fw_log_dump_emi(int par1, int offset, int size);
+#endif
+
+static int conninfra_dbg_suspend_debug(int par1, int offset, int size);
+static int conninfra_dbg_fw_log_ctrl(int par1, int onoff, int level);
+
+static int conninfra_dbg_thermal_query(int par1, int count, int interval);
+static int conninfra_dbg_thermal_ctrl(int par1, int par2, int par3);
+static int conninfra_dbg_step_ctrl(int par1, int par2, int par3);
+
+static int conninfra_dbg_connsys_emi_dump(int par1, int par2, int par3);
+
+static int conninfra_dbg_connsys_coredump_ctrl(int par1, int par2, int par3);
+static int conninfra_dbg_connsys_coredump_mode_query(int par1, int par2, int par3);
+
+static int conninfra_dbg_thread_status_dump(int par1, int par2, int par3);
+
+static const CONNINFRA_DEV_DBG_FUNC conninfra_dev_dbg_func[] = {
+ [0x0] = conninfra_dbg_hwver_get,
+ [0x1] = conninfra_dbg_chip_rst,
+ [0x2] = conninfra_dbg_read_chipid,
+
+ [0x3] = conninfra_dbg_force_conninfra_wakeup,
+ [0x4] = conninfra_dbg_force_conninfra_sleep,
+ [0x5] = conninfra_dbg_reg_read,
+ [0x6] = conninfra_dbg_reg_write,
+
+ [0x7] = conninfra_dbg_efuse_read,
+ [0x8] = conninfra_dbg_efuse_write,
+ [0x9] = conninfra_dbg_ap_reg_read,
+ [0xa] = conninfra_dbg_ap_reg_write,
+
+ [0xb] = conninfra_dbg_fw_log_ctrl,
+ [0xc] = conninfra_dbg_thermal_query,
+ [0xd] = conninfra_dbg_thermal_ctrl,
+ [0xe] = conninfra_dbg_step_ctrl,
+
+ [0xf] = conninfra_dbg_suspend_debug,
+#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH
+ [0x10] = conninfra_dbg_set_fw_log_mode,
+ [0x11] = conninfra_dbg_fw_log_dump_emi,
+#endif
+ [0x12] = conninfra_dbg_connsys_emi_dump,
+ [0x13] = conninfra_dbg_connsys_coredump_ctrl,
+ [0x14] = conninfra_dbg_connsys_coredump_mode_query,
+ [0x15] = conninfra_dbg_thread_status_dump,
+};
+
+#define CONNINFRA_DBG_DUMP_BUF_SIZE 1024
+char g_dump_buf[CONNINFRA_DBG_DUMP_BUF_SIZE];
+char *g_dump_buf_ptr;
+int g_dump_buf_len;
+static OSAL_SLEEPABLE_LOCK g_dump_lock;
+
+int conninfra_dbg_hwver_get(int par1, int par2, int par3)
+{
+ pr_info("query chip version\n");
+ /* TODO: */
+ return 0;
+}
+
+int conninfra_dbg_chip_rst(int par1, int par2, int par3)
+{
+ /* TODO: */
+ conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_BT, "Conninfra_dbg");
+ return 0;
+}
+
+
+int conninfra_dbg_read_chipid(int par1, int par2, int par3)
+{
+ //pr_info("chip id = %d\n", wmt_lib_get_icinfo(WMTCHIN_CHIPID));
+
+ return 0;
+}
+
+int conninfra_dbg_reg_read(int par1, int par2, int par3)
+{
+ int ret = 0, sz;
+ char buf[CONNINFRA_DBG_DUMP_BUF_SIZE];
+
+ /* par2-->register address */
+ /* par3-->register mask */
+ unsigned int value = 0x0;
+ int iRet;
+
+ iRet = conninfra_core_reg_read(par2, &value, par3);
+ snprintf(buf, CONNINFRA_DBG_DUMP_BUF_SIZE,
+ "read chip register (0x%08x) with mask (0x%08x) %s, value = 0x%08x\n",
+ par2, par3, iRet != 0 ? "failed" : "succeed", iRet != 0 ? -1 : value);
+
+ pr_info("%s", buf);
+ ret = osal_lock_sleepable_lock(&g_dump_lock);
+ if (ret) {
+ pr_err("dump_lock fail!!");
+ return ret;
+ }
+
+ if (g_dump_buf_len < CONNINFRA_DBG_DUMP_BUF_SIZE) {
+ sz = strlen(buf);
+ sz = (sz < CONNINFRA_DBG_DUMP_BUF_SIZE - g_dump_buf_len) ?
+ sz : CONNINFRA_DBG_DUMP_BUF_SIZE - g_dump_buf_len;
+ strncpy(g_dump_buf + g_dump_buf_len, buf, sz);
+ g_dump_buf_len += sz;
+ }
+
+ osal_unlock_sleepable_lock(&g_dump_lock);
+
+ return 0;
+}
+
+int conninfra_dbg_reg_write(int par1, int par2, int par3)
+{
+ /* par2-->register address */
+ /* par3-->value to set */
+ int ret;
+
+ ret = conninfra_core_reg_write(par2, par3, 0xffffffff);
+ pr_info("write chip register (0x%08x) with value (0x%08x) %s\n",
+ par2, par3, ret != 0 ? "failed" : "succeed");
+ return 0;
+}
+
+
+int conninfra_dbg_force_conninfra_wakeup(int par1, int par2, int par3)
+{
+ int ret;
+
+ ret = conninfra_core_force_conninfra_wakeup();
+ if (ret)
+ pr_info("conninfra wakup fail\n");
+ else
+ pr_info("conninfra wakup success\n");
+
+ return 0;
+}
+
+int conninfra_dbg_force_conninfra_sleep(int par1, int par2, int par3)
+{
+ int ret;
+
+ ret = conninfra_core_force_conninfra_sleep();
+ if (ret)
+ pr_info("conninfra sleep fail\n");
+ else
+ pr_info("conninfra sleep success\n");
+
+ return 0;
+}
+
+int conninfra_dbg_efuse_read(int par1, int par2, int par3)
+{
+#if 0
+ /* par2-->efuse address */
+ /* par3-->register mask */
+ Uint value = 0x0;
+ Uint iRet = -1;
+
+ iRet = wmt_lib_efuse_rw(0, par2, &value, par3);
+ pr_info("read combo chip efuse (0x%08x) with mask (0x%08x) %s, value = 0x%08x\n",
+ par2, par3, iRet != 0 ? "failed" : "succeed", iRet != 0 ? -1 : value);
+#endif
+ return 0;
+}
+
+int conninfra_dbg_efuse_write(int par1, int par2, int par3)
+{
+#if 0
+ /* par2-->efuse address */
+ /* par3-->value to set */
+ Uint iRet = -1;
+
+ iRet = wmt_lib_efuse_rw(1, par2, &par3, 0xffffffff);
+ pr_info("write combo chip efuse (0x%08x) with value (0x%08x) %s\n",
+ par2, par3, iRet != 0 ? "failed" : "succeed");
+#endif
+ return 0;
+}
+
+
+static int conninfra_dbg_ap_reg_read(int par1, int par2, int par3)
+{
+ int value = 0x0;
+ unsigned char *ap_reg_base = NULL;
+
+ pr_info("AP register read, reg address:0x%x\n", par2);
+ ap_reg_base = ioremap_nocache(par2, 0x4);
+ if (ap_reg_base) {
+ value = readl(ap_reg_base);
+ pr_info("AP register read, reg address:0x%x, value:0x%x\n", par2, value);
+ iounmap(ap_reg_base);
+ } else
+ pr_err("AP register ioremap fail!\n");
+
+ return 0;
+}
+
+static int conninfra_dbg_ap_reg_write(int par1, int par2, int par3)
+{
+ int value = 0x0;
+ unsigned char *ap_reg_base = NULL;
+
+ pr_info("AP register write, reg address:0x%x, value:0x%x\n", par2, par3);
+
+ ap_reg_base = ioremap_nocache(par2, 0x4);
+ if (ap_reg_base) {
+ writel(par3, ap_reg_base);
+ value = readl(ap_reg_base);
+ pr_info("AP register write done, value after write:0x%x\n", value);
+ iounmap(ap_reg_base);
+ } else
+ pr_err("AP register ioremap fail!\n");
+
+ return 0;
+}
+
+#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH
+static int conninfra_dbg_set_fw_log_mode(int par1, int par2, int par3)
+{
+ //connsys_dedicated_log_set_log_mode(par2);
+ return 0;
+}
+
+static int conninfra_dbg_fw_log_dump_emi(int par1, int offset, int size)
+{
+ //connsys_dedicated_log_dump_emi(offset, size);
+ return 0;
+}
+#endif
+
+/********************************************************/
+/* par2: */
+/* 0: Off */
+/* others: alarm time (seconds) */
+/********************************************************/
+static int conninfra_dbg_suspend_debug(int par1, int par2, int par3)
+{
+#if 0
+ if (par2 > 0)
+ connsys_log_alarm_enable(par2);
+ else
+ connsys_log_alarm_disable();
+#endif
+ return 0;
+}
+
+
+static int conninfra_dbg_fw_log_ctrl(int par1, int onoff, int level)
+{
+ /* Parameter format
+ * onoff:
+ * - bit 24~31: unused
+ * - bit 16~23: subsys type
+ * - bit 8~15 : unused
+ * - bit 0~7 : on/off setting
+ * level: only lowest 8 bites will be used.
+ * - bit 8~31 : unused
+ * - bit 0~7 : log level setting
+ * Example:
+ * 1. To turn on MCU log
+ * onoff = 0x0001
+ * 2. To turn on Subsys Z log
+ * onoff = 0x0z01 (z = subsys)
+ * 3. To turn off Subsys Z log
+ * onoff = 0x0z00 (z = subsys)
+ */
+#if 0
+ UINT8 type = (unsigned char)(onoff >> 16);
+
+ pr_info("Configuring firmware log: type:%d, on/off:%d, level:%d\n",
+ type, (unsigned char)onoff, (unsigned char)level);
+ //wmt_lib_fw_log_ctrl(type, (unsigned char)onoff, (unsigned char)level);
+#endif
+ return 0;
+}
+
+int conninfra_dbg_thermal_query(int par1, int count, int interval)
+{
+ int temp, ret;
+
+ ret = conninfra_core_thermal_query(&temp);
+
+ pr_info("[Conninfra_Thermal_Query] ret=[%d] temp=[%d]", ret, temp);
+
+ return 0;
+}
+
+int conninfra_dbg_thermal_ctrl(int par1, int par2, int par3)
+{
+#if 0
+ if (par2 == 0) {
+ if (par3 >= 99) {
+ pr_info("Can`t set temp threshold greater or queal 99\n");
+ return -1;
+ }
+ wmt_dev_set_temp_threshold(par3);
+ }
+#endif
+ return 0;
+}
+
+static int conninfra_dbg_step_ctrl(int par1, int par2, int par3)
+{
+#if 0
+ if (par2 == 0)
+ wmt_step_print_version();
+ else if (par2 == 1) {
+ pr_info("STEP show: Start to change config\n");
+ wmt_step_deinit();
+ wmt_step_init();
+ pr_info("STEP show: End to change config\n");
+ }
+#endif
+ return 0;
+}
+
+static int conninfra_dbg_connsys_emi_dump(int par1, int par2, int par3)
+{
+ unsigned int start;
+ // make size 16-byte alignment
+ int size = (((par3 + 15) >> 4) << 4);
+ void __iomem *vir_addr = NULL;
+ char* buf = NULL;
+ struct consys_emi_addr_info* addr_info = emi_mng_get_phy_addr();
+ int i;
+
+ if (par2 & 0xf) {
+ pr_err("EMI dump fail: wrong offset(0x%x), should be 16-byte alignment\n", par2);
+ return -1;
+ }
+
+ start = (unsigned int)(par2 + addr_info->emi_ap_phy_addr);
+
+ buf = (char*)osal_malloc(sizeof(char)*size);
+ if (buf == NULL) {
+ pr_err("[%s] allocate buffer fail\n", __func__);
+ return -1;
+ }
+
+ pr_info("EMI dump, offset=0x%x(physical addr=0x%x), size=0x%x\n", par2, start, size);
+ vir_addr = ioremap_nocache(start, size);
+ if (!vir_addr) {
+ pr_err("ioremap fail");
+ osal_free(buf);
+ return -1;
+ }
+ memcpy_fromio(buf, vir_addr, size);
+ for (i = 0; i < size; i+= 16) {
+ pr_info(
+ "EMI[0x%x]: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
+ par2 + i,
+ buf[i + 0], buf[i + 1], buf[i + 2], buf[i + 3],
+ buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7],
+ buf[i + 8], buf[i + 9], buf[i + 0xa], buf[i + 0xb],
+ buf[i + 0xc], buf[i + 0xd], buf[i + 0xe], buf[i + 0xf]);
+ }
+
+ iounmap(vir_addr);
+ osal_free(buf);
+ return 0;
+}
+
+static int conninfra_dbg_connsys_coredump_ctrl(int par1, int par2, int par3)
+{
+#if CFG_CONNINFRA_COREDUMP_SUPPORT
+ unsigned int orig_mode = connsys_coredump_get_mode();
+
+ pr_info("Setup coredump mode from %d to %d\n", orig_mode, par2);
+ connsys_coredump_set_dump_mode(par2);
+#else
+ pr_info("Connsys coredump is not support");
+#endif
+ return 0;
+}
+
+static int conninfra_dbg_connsys_coredump_mode_query(int par1, int par2, int par3)
+{
+#if CFG_CONNINFRA_COREDUMP_SUPPORT
+ unsigned int orig_mode = connsys_coredump_get_mode();
+
+ pr_info("Connsys coredump mode is [%d]\n", orig_mode);
+ return orig_mode;
+#else
+ pr_info("Connsys coredump is not support");
+ return 0;
+#endif
+}
+
+static int conninfra_dbg_thread_status_dump(int par1, int par2, int par3)
+{
+ conninfra_debug_dump();
+ return 0;
+}
+
+ssize_t conninfra_dbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
+{
+ int ret = 0;
+ int dump_len;
+
+ ret = osal_lock_sleepable_lock(&g_dump_lock);
+ if (ret) {
+ pr_err("dump_lock fail!!");
+ return ret;
+ }
+
+ if (g_dump_buf_len == 0)
+ goto exit;
+
+ if (*f_pos == 0)
+ g_dump_buf_ptr = g_dump_buf;
+
+ dump_len = g_dump_buf_len >= count ? count : g_dump_buf_len;
+ ret = copy_to_user(buf, g_dump_buf_ptr, dump_len);
+ if (ret) {
+ pr_err("copy to dump info buffer failed, ret:%d\n", ret);
+ ret = -EFAULT;
+ goto exit;
+ }
+
+ *f_pos += dump_len;
+ g_dump_buf_len -= dump_len;
+ g_dump_buf_ptr += dump_len;
+ pr_info("conninfra_dbg:after read,wmt for dump info buffer len(%d)\n", g_dump_buf_len);
+
+ ret = dump_len;
+exit:
+
+ osal_unlock_sleepable_lock(&g_dump_lock);
+ return ret;
+}
+
+ssize_t conninfra_dbg_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos)
+{
+ size_t len = count;
+ char buf[256];
+ char* pBuf;
+ int x = 0, y = 0, z = 0;
+ char* pToken = NULL;
+ char* pDelimiter = " \t";
+ long res = 0;
+ static char dbg_enabled;
+
+ pr_info("write parameter len = %d\n\r", (int) len);
+ if (len >= osal_sizeof(buf)) {
+ pr_err("input handling fail!\n");
+ len = osal_sizeof(buf) - 1;
+ return -1;
+ }
+
+ if (copy_from_user(buf, buffer, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+ pr_info("write parameter data = %s\n\r", buf);
+
+ pBuf = buf;
+ pToken = osal_strsep(&pBuf, pDelimiter);
+ if (pToken != NULL) {
+ osal_strtol(pToken, 16, &res);
+ x = (int)res;
+ } else {
+ x = 0;
+ }
+
+ pToken = osal_strsep(&pBuf, "\t\n ");
+ if (pToken != NULL) {
+ osal_strtol(pToken, 16, &res);
+ y = (int)res;
+ pr_info("y = 0x%08x\n\r", y);
+ } else {
+ y = 3000;
+ /*efuse, register read write default value */
+ if (0x5 == x || 0x6 == x)
+ y = 0x80000000;
+ }
+
+ pToken = osal_strsep(&pBuf, "\t\n ");
+ if (pToken != NULL) {
+ osal_strtol(pToken, 16, &res);
+ z = (int)res;
+ } else {
+ z = 10;
+ /*efuse, register read write default value */
+ if (0x5 == x || 0x6 == x)
+ z = 0xffffffff;
+ }
+
+ pr_info("x(0x%08x), y(0x%08x), z(0x%08x)\n\r", x, y, z);
+
+ /* For eng and userdebug load, have to enable wmt_dbg by writing 0xDB9DB9 to
+ * "/proc/driver/wmt_dbg" to avoid some malicious use
+ */
+#if CFG_CONNINFRA_DBG_SUPPORT
+ if (0xDB9DB9 == x) {
+ dbg_enabled = 1;
+ return len;
+ }
+#endif
+ /* For user load, only 0x13/0x14 is allowed to execute */
+ if (0 == dbg_enabled && ((x != 0x13) && (x != 0x14))) {
+ pr_info("please enable conninfra debug first\n\r");
+ return len;
+ }
+
+ if (osal_array_size(conninfra_dev_dbg_func) > x && NULL != conninfra_dev_dbg_func[x])
+ (*conninfra_dev_dbg_func[x]) (x, y, z);
+ else
+ pr_warn("no handler defined for command id(0x%08x)\n\r", x);
+
+ return len;
+}
+
+int conninfra_dev_dbg_init(void)
+{
+ static const struct file_operations conninfra_dbg_fops = {
+ .owner = THIS_MODULE,
+ .read = conninfra_dbg_read,
+ .write = conninfra_dbg_write,
+ };
+ int i_ret = 0;
+
+ g_conninfra_dbg_entry = proc_create(CONNINFRA_DBG_PROCNAME, 0664, NULL, &conninfra_dbg_fops);
+ if (g_conninfra_dbg_entry == NULL) {
+ pr_err("Unable to create / wmt_aee proc entry\n\r");
+ i_ret = -1;
+ }
+
+ osal_sleepable_lock_init(&g_dump_lock);
+
+ return i_ret;
+}
+
+int conninfra_dev_dbg_deinit(void)
+{
+ osal_sleepable_lock_deinit(&g_dump_lock);
+
+ if (g_conninfra_dbg_entry != NULL) {
+ proc_remove(g_conninfra_dbg_entry);
+ g_conninfra_dbg_entry = NULL;
+ }
+
+ return 0;
+}
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/conninfra_dbg.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/conninfra_dbg.h
new file mode 100644
index 0000000..c06b8c6
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/conninfra_dbg.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _CONNINFRA_DBG_H_
+#define _CONNINFRA_DBG_H_
+#include "osal.h"
+
+typedef int(*CONNINFRA_DEV_DBG_FUNC) (int par1, int par2, int par3);
+int conninfra_dev_dbg_init(void);
+int conninfra_dev_dbg_deinit(void);
+
+#endif /* _CONNINFRA_DBG_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/connsyslog.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/connsyslog.c
new file mode 100644
index 0000000..b373a52
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/connsyslog.c
@@ -0,0 +1,1271 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <linux/ratelimit.h>
+#include <linux/alarmtimer.h>
+#include <linux/suspend.h>
+
+#include "connsyslog.h"
+#include "connsyslog_emi.h"
+#include "connsyslog_hw_config.h"
+#include "ring.h"
+#include "ring_emi.h"
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/* Close debug log */
+//#define DEBUG_RING 1
+
+#define CONNLOG_ALARM_STATE_DISABLE 0x0
+#define CONNLOG_ALARM_STATE_ENABLE 0x01
+#define CONNLOG_ALARM_STATE_RUNNING 0x03
+
+#define BYETES_PER_LINE 16
+#define LOG_LINE_SIZE (3*BYETES_PER_LINE + BYETES_PER_LINE + 1)
+#define IS_VISIBLE_CHAR(c) ((c) >= 32 && (c) <= 126)
+
+#define LOG_MAX_LEN 1024
+#define LOG_HEAD_LENG 16
+#define TIMESYNC_LENG 40
+
+static const char log_head[] = {0x55, 0x00, 0x00, 0x62};
+static const char timesync_head[] = {0x55, 0x00, 0x25, 0x62};
+
+struct connlog_alarm {
+ struct alarm alarm_timer;
+ unsigned int alarm_state;
+ unsigned int blank_state;
+ unsigned int alarm_sec;
+ spinlock_t alarm_lock;
+ unsigned long flags;
+};
+
+struct connlog_offset {
+ unsigned int emi_base_offset;
+ unsigned int emi_size;
+ unsigned int emi_read;
+ unsigned int emi_write;
+ unsigned int emi_buf;
+ unsigned int emi_guard_pattern_offset;
+};
+
+struct connlog_buffer {
+ struct ring_emi ring_emi;
+ struct ring ring_cache;
+ void *cache_base;
+};
+
+struct connlog_event_cb {
+ CONNLOG_EVENT_CB log_data_handler;
+};
+
+struct connlog_dev {
+ int conn_type;
+ phys_addr_t phyAddrEmiBase;
+ unsigned int emi_size;
+ void __iomem *virAddrEmiLogBase;
+ struct connlog_offset log_offset;
+ struct connlog_buffer log_buffer;
+ bool eirqOn;
+ spinlock_t irq_lock;
+ unsigned long flags;
+ unsigned int irq_counter;
+ struct timer_list workTimer;
+ struct work_struct logDataWorker;
+ void *log_data;
+ char log_line[LOG_MAX_LEN];
+ struct connlog_event_cb callback;
+};
+
+static char *type_to_title[CONN_DEBUG_TYPE_END] = {
+ "wifi_fw", "bt_fw"
+};
+
+static struct connlog_dev* gLogDev[CONN_DEBUG_TYPE_END];
+
+#ifdef CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH
+static atomic_t g_log_mode = ATOMIC_INIT(LOG_TO_FILE);
+#else
+static atomic_t g_log_mode = ATOMIC_INIT(PRINT_TO_KERNEL_LOG);
+#endif
+
+static phys_addr_t gPhyEmiBase;
+
+/* alarm timer for suspend */
+struct connlog_alarm gLogAlarm;
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+static void connlog_do_schedule_work(struct connlog_dev* handler, bool count);
+static void work_timer_handler(unsigned long data);
+static void connlog_event_set(struct connlog_dev* handler);
+static struct connlog_dev* connlog_subsys_init(
+ int conn_type,
+ phys_addr_t emiaddr,
+ unsigned int emi_size);
+static void connlog_subsys_deinit(struct connlog_dev* handler);
+static ssize_t connlog_read_internal(
+ struct connlog_dev* handler, int conn_type,
+ char *buf, char __user *userbuf, size_t count, bool to_user);
+static void connlog_dump_emi(struct connlog_dev* handler, int offset, int size);
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+struct connlog_emi_config* __weak get_connsyslog_platform_config(int conn_type)
+{
+ pr_err("Miss platform ops !!\n");
+ return NULL;
+}
+
+void *connlog_cache_allocate(size_t size)
+{
+ void *pBuffer = NULL;
+
+ pBuffer = kmalloc(size, GFP_KERNEL);
+ if (!pBuffer)
+ return NULL;
+ return pBuffer;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * connlog_event_set
+ * DESCRIPTION
+ * Trigger event call back to wakeup waitqueue
+ * PARAMETERS
+ * conn_type [IN] subsys type
+ * RETURNS
+ * void
+ *****************************************************************************/
+static void connlog_event_set(struct connlog_dev* handler)
+{
+ if (handler->callback.log_data_handler)
+ handler->callback.log_data_handler();
+}
+
+
+/*****************************************************************************
+* FUNCTION
+* connlog_set_ring_ready
+* DESCRIPTION
+* set reserved bit be EMIFWLOG to indicate that init is ready.
+* PARAMETERS
+* void
+* RETURNS
+* void
+*****************************************************************************/
+static void connlog_set_ring_ready(struct connlog_dev* handler)
+{
+ const char ready_str[] = "EMIFWLOG";
+
+ memcpy_toio(handler->virAddrEmiLogBase + CONNLOG_READY_PATTERN_BASE,
+ ready_str, CONNLOG_READY_PATTERN_BASE_SIZE);
+}
+
+static unsigned int connlog_cal_log_size(unsigned int emi_size)
+{
+ int position;
+ int i;
+
+ if (emi_size > 0) {
+ for (i = (emi_size >> 1), position = 0; i != 0; ++position)
+ i >>= 1;
+ } else {
+ return 0;
+ }
+
+ return (1UL << position);
+}
+
+static int connlog_emi_init(struct connlog_dev* handler, phys_addr_t emiaddr, unsigned int emi_size)
+{
+ int conn_type = handler->conn_type;
+ unsigned int cal_log_size = connlog_cal_log_size(
+ emi_size - CONNLOG_EMI_BASE_OFFSET - CONNLOG_EMI_END_PATTERN_SIZE);
+
+ if (emiaddr == 0 || cal_log_size == 0) {
+ pr_err("[%s] consys emi memory address invalid emi_addr=%p emi_size=%d\n",
+ type_to_title[conn_type], emiaddr, emi_size);
+ return -1;
+ }
+ pr_info("input size = %d cal_size = %d\n", emi_size, cal_log_size);
+
+ handler->phyAddrEmiBase = emiaddr;
+ handler->emi_size = emi_size;
+ handler->virAddrEmiLogBase = ioremap_nocache(handler->phyAddrEmiBase, emi_size);
+ handler->log_offset.emi_base_offset = CONNLOG_EMI_BASE_OFFSET;
+ handler->log_offset.emi_size = cal_log_size;
+ handler->log_offset.emi_read = CONNLOG_EMI_READ;
+ handler->log_offset.emi_write = CONNLOG_EMI_WRITE;
+ handler->log_offset.emi_buf = CONNLOG_EMI_BUF;
+ handler->log_offset.emi_guard_pattern_offset = handler->log_offset.emi_buf + handler->log_offset.emi_size;
+
+ if (handler->virAddrEmiLogBase) {
+ pr_info("[%s] EMI mapping OK virtual(0x%p) physical(0x%x) size=%d\n",
+ type_to_title[conn_type],
+ handler->virAddrEmiLogBase,
+ (unsigned int)handler->phyAddrEmiBase,
+ handler->emi_size);
+ /* Clean it */
+ memset_io(handler->virAddrEmiLogBase, 0xff, handler->emi_size);
+ /* Clean control block as 0 */
+ memset_io(handler->virAddrEmiLogBase + CONNLOG_EMI_BASE_OFFSET, 0x0, CONNLOG_EMI_32_BYTE_ALIGNED);
+ /* Setup henader */
+ EMI_WRITE32(handler->virAddrEmiLogBase + 0, handler->log_offset.emi_base_offset);
+ EMI_WRITE32(handler->virAddrEmiLogBase + 4, handler->log_offset.emi_size);
+ /* Setup end pattern */
+ memcpy_toio(
+ handler->virAddrEmiLogBase + handler->log_offset.emi_guard_pattern_offset,
+ CONNLOG_EMI_END_PATTERN, CONNLOG_EMI_END_PATTERN_SIZE);
+ } else {
+ pr_err("[%s] EMI mapping fail\n", type_to_title[conn_type]);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* FUNCTION
+* connlog_emi_deinit
+* DESCRIPTION
+* Do iounmap for log buffer on EMI
+* PARAMETERS
+* void
+* RETURNS
+* void
+*****************************************************************************/
+static void connlog_emi_deinit(struct connlog_dev* handler)
+{
+ iounmap(handler->virAddrEmiLogBase);
+}
+
+static int connlog_buffer_init(struct connlog_dev* handler)
+{
+ /* Init ring emi */
+ ring_emi_init(
+ handler->virAddrEmiLogBase + handler->log_offset.emi_buf,
+ handler->log_offset.emi_size,
+ handler->virAddrEmiLogBase + handler->log_offset.emi_read,
+ handler->virAddrEmiLogBase + handler->log_offset.emi_write,
+ &handler->log_buffer.ring_emi);
+
+ /* init ring cache */
+ /* TODO: use emi size. Need confirm */
+ handler->log_buffer.cache_base = connlog_cache_allocate(handler->emi_size);
+ memset(handler->log_buffer.cache_base, 0, handler->emi_size);
+ ring_init(
+ handler->log_buffer.cache_base,
+ handler->log_offset.emi_size,
+ 0,
+ 0,
+ &handler->log_buffer.ring_cache);
+
+ return 0;
+}
+
+static int connlog_ring_buffer_init(struct connlog_dev* handler)
+{
+ if (!handler->virAddrEmiLogBase) {
+ pr_err("[%s] consys emi memory address phyAddrEmiBase invalid\n",
+ type_to_title[handler->conn_type]);
+ return -1;
+ }
+ connlog_buffer_init(handler);
+ /* TODO: use emi size. Need confirm */
+ handler->log_data = connlog_cache_allocate(handler->emi_size);
+ connlog_set_ring_ready(handler);
+ return 0;
+}
+
+/*****************************************************************************
+* FUNCTION
+* connlog_ring_buffer_deinit
+* DESCRIPTION
+* Initialize ring buffer setting for subsys
+* PARAMETERS
+* void
+* RETURNS
+* void
+*****************************************************************************/
+static void connlog_ring_buffer_deinit(struct connlog_dev* handler)
+{
+ kfree(handler->log_buffer.cache_base);
+ handler->log_buffer.cache_base = NULL;
+
+ kfree(handler->log_data);
+ handler->log_data = NULL;
+}
+
+/*****************************************************************************
+* FUNCTION
+* work_timer_handler
+* DESCRIPTION
+* IRQ is still on, do schedule_work again
+* PARAMETERS
+* data [IN] input data
+* RETURNS
+* void
+*****************************************************************************/
+static void work_timer_handler(unsigned long data)
+{
+ struct connlog_dev* handler = (struct connlog_dev*)data;
+ connlog_do_schedule_work(handler, false);
+}
+
+/*****************************************************************************
+* FUNCTION
+* connlog_dump_buf
+* DESCRIPTION
+* Dump EMI content. Output format:
+* xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx ................
+* 3 digits hex * 16 + 16 single char + 1 NULL terminate = 64+1 bytes
+* PARAMETERS
+*
+* RETURNS
+* void
+*****************************************************************************/
+void connsys_log_dump_buf(const char *title, const char *buf, ssize_t sz)
+{
+ int i;
+ char line[LOG_LINE_SIZE];
+
+ i = 0;
+ line[LOG_LINE_SIZE-1] = 0;
+ while (sz--) {
+ snprintf(line + i*3, 3, "%02x", *buf);
+ line[i*3 + 2] = ' ';
+
+ if (IS_VISIBLE_CHAR(*buf))
+ line[3*BYETES_PER_LINE + i] = *buf;
+ else
+ line[3*BYETES_PER_LINE + i] = '`';
+
+ i++;
+ buf++;
+
+ if (i >= BYETES_PER_LINE || !sz) {
+ if (i < BYETES_PER_LINE) {
+ memset(line+i*3, ' ', (BYETES_PER_LINE-i)*3);
+ memset(line+3*BYETES_PER_LINE+i, '.', BYETES_PER_LINE-i);
+ }
+ pr_info("%s: %s\n", title, line);
+ i = 0;
+ }
+ }
+}
+EXPORT_SYMBOL(connsys_log_dump_buf);
+
+/*****************************************************************************
+* FUNCTION
+* connlog_dump_emi
+* DESCRIPTION
+* dump EMI buffer for debug.
+* PARAMETERS
+* offset [IN] buffer offset
+* size [IN] dump buffer size
+* RETURNS
+* void
+*****************************************************************************/
+void connlog_dump_emi(struct connlog_dev* handler, int offset, int size)
+{
+ char title[100];
+ memset(title, 0, 100);
+ sprintf(title, "%s(%p)", "emi", handler->virAddrEmiLogBase + offset);
+ connsys_log_dump_buf(title, handler->virAddrEmiLogBase + offset, size);
+}
+
+/*****************************************************************************
+* FUNCTION
+* connlog_ring_emi_check
+* DESCRIPTION
+*
+* PARAMETERS
+*
+* RETURNS
+* void
+*****************************************************************************/
+static bool connlog_ring_emi_check(struct connlog_dev* handler)
+{
+ struct ring_emi *ring_emi = &handler->log_buffer.ring_emi;
+ char line[CONNLOG_EMI_END_PATTERN_SIZE + 1];
+
+ memcpy_fromio(
+ line,
+ handler->virAddrEmiLogBase + handler->log_offset.emi_guard_pattern_offset,
+ CONNLOG_EMI_END_PATTERN_SIZE);
+ line[CONNLOG_EMI_END_PATTERN_SIZE] = '\0';
+
+ /* Check ring_emi buffer memory. Dump EMI data if it is corruption. */
+ if (EMI_READ32(ring_emi->read) > handler->log_offset.emi_size ||
+ EMI_READ32(ring_emi->write) > handler->log_offset.emi_size ||
+ strncmp(line, CONNLOG_EMI_END_PATTERN, CONNLOG_EMI_END_PATTERN_SIZE) != 0) {
+ pr_err("[connlog] %s out of bound or guard pattern overwrited. Read(pos=%p)=[0x%x] write(pos=%p)=[0x%x] size=[0x%x]\n",
+ type_to_title[handler->conn_type],
+ ring_emi->read, EMI_READ32(ring_emi->read),
+ ring_emi->write, EMI_READ32(ring_emi->write),
+ handler->log_offset.emi_size);
+ connlog_dump_emi(handler, 0x0, 0x60);
+ connlog_dump_emi(handler, CONNLOG_EMI_BASE_OFFSET, 0x20);
+ connlog_dump_emi(
+ handler,
+ handler->log_offset.emi_guard_pattern_offset,
+ CONNLOG_EMI_END_PATTERN_SIZE);
+ return false;
+ }
+
+ return true;
+}
+
+/*****************************************************************************
+* FUNCTION
+* connlog_ring_emi_to_cache
+* DESCRIPTION
+*
+* PARAMETERS
+*
+* RETURNS
+* void
+*****************************************************************************/
+static void connlog_ring_emi_to_cache(struct connlog_dev* handler)
+{
+ struct ring_emi_segment ring_emi_seg;
+ struct ring_emi *ring_emi = &handler->log_buffer.ring_emi;
+ struct ring *ring_cache = &handler->log_buffer.ring_cache;
+ int total_size = 0;
+ int count = 0;
+ unsigned int cache_max_size = 0;
+#ifndef DEBUG_LOG_ON
+ static DEFINE_RATELIMIT_STATE(_rs, 10 * HZ, 1);
+ static DEFINE_RATELIMIT_STATE(_rs2, HZ, 1);
+#endif
+
+ if (RING_FULL(ring_cache)) {
+ #ifndef DEBUG_LOG_ON
+ if (__ratelimit(&_rs))
+ #endif
+ pr_warn("[connlog] %s cache is full.\n", type_to_title[handler->conn_type]);
+ return;
+ }
+
+ cache_max_size = RING_WRITE_REMAIN_SIZE(ring_cache);
+ if (RING_EMI_EMPTY(ring_emi) || !ring_emi_read_prepare(cache_max_size, &ring_emi_seg, ring_emi)) {
+ #ifndef DEBUG_LOG_ON
+ if(__ratelimit(&_rs))
+ #endif
+ pr_err("[connlog] %s no data.\n", type_to_title[handler->conn_type]);
+ return;
+ }
+
+ /* Check ring_emi buffer memory. Dump EMI data if it is corruption. */
+ if (connlog_ring_emi_check(handler) == false) {
+ pr_err("[connlog] %s emi check fail\n", type_to_title[handler->conn_type]);
+ /* TODO: trigger assert by callback? */
+ return;
+ }
+
+ RING_EMI_READ_ALL_FOR_EACH(ring_emi_seg, ring_emi) {
+ struct ring_segment ring_cache_seg;
+ unsigned int emi_buf_size = ring_emi_seg.sz;
+ unsigned int written = 0;
+
+#ifdef DEBUG_RING
+ ring_emi_dump(__func__, ring_emi);
+ ring_emi_dump_segment(__func__, &ring_emi_seg);
+#endif
+ RING_WRITE_FOR_EACH(ring_emi_seg.sz, ring_cache_seg, &handler->log_buffer.ring_cache) {
+#ifdef DEBUG_RING
+ ring_dump(__func__, &handler->log_buffer.ring_cache);
+ ring_dump_segment(__func__, &ring_cache_seg);
+#endif
+ #ifndef DEBUG_LOG_ON
+ if (__ratelimit(&_rs2))
+ #endif
+ pr_info("%s: ring_emi_seg.sz=%d, ring_cache_pt=%p, ring_cache_seg.sz=%d\n",
+ type_to_title[handler->conn_type], ring_emi_seg.sz, ring_cache_seg.ring_pt,
+ ring_cache_seg.sz);
+ memcpy_fromio(ring_cache_seg.ring_pt, ring_emi_seg.ring_emi_pt + ring_cache_seg.data_pos,
+ ring_cache_seg.sz);
+ emi_buf_size -= ring_cache_seg.sz;
+ written += ring_cache_seg.sz;
+ }
+
+ total_size += ring_emi_seg.sz;
+ count++;
+ }
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ * connlog_fw_log_parser
+ * DESCRIPTION
+ * Parse fw log and print to kernel
+ * PARAMETERS
+ * conn_type [IN] log type
+ * buf [IN] buffer to prase
+ * sz [IN] buffer size
+ * RETURNS
+ * void
+ *****************************************************************************/
+static void connlog_fw_log_parser(struct connlog_dev* handler, ssize_t sz)
+{
+ unsigned int systime = 0;
+ unsigned int utc_s = 0;
+ unsigned int utc_us = 0;
+ unsigned int buf_len = 0;
+ unsigned int print_len = 0;
+ char* log_line = handler->log_line;
+ const char* buf = handler->log_data;
+ int conn_type = handler->conn_type;
+
+ while (sz > LOG_HEAD_LENG) {
+ if (*buf == log_head[0]) {
+ if (!memcmp(buf, log_head, sizeof(log_head))) {
+ buf_len = buf[14] + (buf[15] << 8);
+ print_len = buf_len >= LOG_MAX_LEN ? LOG_MAX_LEN - 1 : buf_len;
+ memcpy(log_line, buf + LOG_HEAD_LENG, print_len);
+ log_line[print_len] = 0;
+ pr_info("%s: %s\n", type_to_title[conn_type], log_line);
+ sz -= (LOG_HEAD_LENG + buf_len);
+ buf += (LOG_HEAD_LENG + buf_len);
+ continue;
+ } else if (sz >= TIMESYNC_LENG &&
+ !memcmp(buf, timesync_head, sizeof(timesync_head))) {
+ memcpy(&systime, buf + 28, sizeof(systime));
+ memcpy(&utc_s, buf + 32, sizeof(utc_s));
+ memcpy(&utc_us, buf + 36, sizeof(utc_us));
+ pr_info("%s: timesync : (%u) %u.%06u\n",
+ type_to_title[conn_type], systime, utc_s, utc_us);
+ sz -= TIMESYNC_LENG;
+ buf += TIMESYNC_LENG;
+ continue;
+ }
+ }
+ sz--;
+ buf++;
+ }
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * connlog_ring_print
+ * DESCRIPTION
+ * print log data on kernel log
+ * PARAMETERS
+ * handler [IN] log handler
+ * RETURNS
+ * void
+ *****************************************************************************/
+static void connlog_ring_print(struct connlog_dev* handler)
+{
+ unsigned int written = 0;
+ unsigned int buf_size;
+ struct ring_emi_segment ring_emi_seg;
+ struct ring_emi *ring_emi = &handler->log_buffer.ring_emi;
+ int conn_type = handler->conn_type;
+
+ if (RING_EMI_EMPTY(ring_emi) || !ring_emi_read_all_prepare(&ring_emi_seg, ring_emi)) {
+ pr_err("type(%s) no data, possibly taken by concurrent reader.\n", type_to_title[conn_type]);
+ return;
+ }
+ buf_size = ring_emi_seg.remain;
+ memset(handler->log_data, 0, handler->emi_size);
+
+ /* Check ring_emi buffer memory. Dump EMI data if it is corruption. */
+ if (connlog_ring_emi_check(handler) == false) {
+ pr_err("[connlog] %s emi check fail\n", type_to_title[handler->conn_type]);
+ /* TODO: trigger assert by callback? */
+ return;
+ }
+
+ RING_EMI_READ_ALL_FOR_EACH(ring_emi_seg, ring_emi) {
+ memcpy_fromio(handler->log_data + written, ring_emi_seg.ring_emi_pt, ring_emi_seg.sz);
+ buf_size -= ring_emi_seg.sz;
+ written += ring_emi_seg.sz;
+ }
+
+ if (conn_type != CONN_DEBUG_TYPE_BT)
+ connlog_fw_log_parser(handler, written);
+}
+
+/*****************************************************************************
+* FUNCTION
+* connlog_log_data_handler
+* DESCRIPTION
+*
+* PARAMETERS
+*
+* RETURNS
+* void
+*****************************************************************************/
+static void connlog_log_data_handler(struct work_struct *work)
+{
+ struct connlog_dev* handler =
+ container_of(work, struct connlog_dev, logDataWorker);
+#ifndef DEBUG_LOG_ON
+ static DEFINE_RATELIMIT_STATE(_rs, 10 * HZ, 1);
+ static DEFINE_RATELIMIT_STATE(_rs2, 2 * HZ, 1);
+#endif
+
+ if (!RING_EMI_EMPTY(&handler->log_buffer.ring_emi)) {
+ if (atomic_read(&g_log_mode) == LOG_TO_FILE)
+ connlog_ring_emi_to_cache(handler);
+ else
+ connlog_ring_print(handler);
+ connlog_event_set(handler);
+ } else {
+#ifndef DEBUG_LOG_ON
+ if (__ratelimit(&_rs))
+#endif
+ pr_info("[connlog] %s emi ring is empty!\n",
+ type_to_title[handler->conn_type]);
+ }
+
+#ifndef DEBUG_LOG_ON
+ if (__ratelimit(&_rs2))
+#endif
+ pr_info("[connlog] %s irq counter = %d\n",
+ type_to_title[handler->conn_type],
+ EMI_READ32(handler->virAddrEmiLogBase + CONNLOG_IRQ_COUNTER_BASE));
+
+ spin_lock_irqsave(&handler->irq_lock, handler->flags);
+ if (handler->eirqOn)
+ mod_timer(&handler->workTimer, jiffies + 1);
+ spin_unlock_irqrestore(&handler->irq_lock, handler->flags);
+}
+
+static void connlog_do_schedule_work(struct connlog_dev* handler, bool count)
+{
+ spin_lock_irqsave(&handler->irq_lock, handler->flags);
+ if (count) {
+ handler->irq_counter++;
+ EMI_WRITE32(
+ handler->virAddrEmiLogBase + CONNLOG_IRQ_COUNTER_BASE,
+ handler->irq_counter);
+ }
+ handler->eirqOn = !schedule_work(&handler->logDataWorker);
+ spin_unlock_irqrestore(&handler->irq_lock, handler->flags);
+}
+
+/*****************************************************************************
+* FUNCTION
+* connsys_log_get_buf_size
+* DESCRIPTION
+* Get ring buffer unread size on EMI.
+* PARAMETERS
+* conn_type [IN] subsys type
+* RETURNS
+* unsigned int Ring buffer unread size
+*****************************************************************************/
+unsigned int connsys_log_get_buf_size(int conn_type)
+{
+ struct connlog_dev* handler;
+ if (conn_type < CONN_DEBUG_TYPE_WIFI || conn_type >= CONN_DEBUG_TYPE_END)
+ return 0;
+
+ handler = gLogDev[conn_type];
+ if (handler == NULL) {
+ pr_err("[%s][%s] didn't init\n", __func__, type_to_title[conn_type]);
+ return 0;
+ }
+
+ return RING_SIZE(&handler->log_buffer.ring_cache);
+}
+EXPORT_SYMBOL(connsys_log_get_buf_size);
+
+/*****************************************************************************
+ * FUNCTION
+ * connsys_log_read_internal
+ * DESCRIPTION
+ * Read log in ring_cache to buf
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+static ssize_t connlog_read_internal(
+ struct connlog_dev* handler, int conn_type,
+ char *buf, char __user *userbuf, size_t count, bool to_user)
+{
+ unsigned int written = 0;
+ unsigned int cache_buf_size;
+ struct ring_segment ring_seg;
+ struct ring *ring = &handler->log_buffer.ring_cache;
+ unsigned int size = 0;
+ int retval;
+ static DEFINE_RATELIMIT_STATE(_rs, 10 * HZ, 1);
+ static DEFINE_RATELIMIT_STATE(_rs2, 1 * HZ, 1);
+
+ size = count < RING_SIZE(ring) ? count : RING_SIZE(ring);
+ if (RING_EMPTY(ring) || !ring_read_prepare(size, &ring_seg, ring)) {
+ pr_err("type(%d) no data, possibly taken by concurrent reader.\n", conn_type);
+ goto done;
+ }
+ cache_buf_size = ring_seg.remain;
+
+ RING_READ_FOR_EACH(size, ring_seg, ring) {
+ if (to_user) {
+ retval = copy_to_user(userbuf + written, ring_seg.ring_pt, ring_seg.sz);
+ if (retval) {
+ if (__ratelimit(&_rs))
+ pr_err("copy to user buffer failed, ret:%d\n", retval);
+ goto done;
+ }
+ } else {
+ memcpy(buf + written, ring_seg.ring_pt, ring_seg.sz);
+ }
+ cache_buf_size -= ring_seg.sz;
+ written += ring_seg.sz;
+ if (__ratelimit(&_rs2))
+ pr_info("[%s] copy %d to %s\n",
+ type_to_title[conn_type],
+ ring_seg.sz,
+ (to_user? "user space" : "buffer"));
+ }
+done:
+ return written;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * connsys_log_read_to_user
+ * DESCRIPTION
+ * Read log in ring_cache to user space buf
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+ssize_t connsys_log_read_to_user(int conn_type, char __user *buf, size_t count)
+{
+ struct connlog_dev* handler;
+ unsigned int written = 0;
+
+ if (conn_type < CONN_DEBUG_TYPE_WIFI || conn_type >= CONN_DEBUG_TYPE_END)
+ goto done;
+ if (atomic_read(&g_log_mode) != LOG_TO_FILE)
+ goto done;
+
+ handler = gLogDev[conn_type];
+ if (handler == NULL) {
+ pr_err("[%s][%s] not init\n", __func__, type_to_title[conn_type]);
+ goto done;
+ }
+ written = connlog_read_internal(handler, conn_type, NULL, buf, count, true);
+done:
+ return written;
+}
+EXPORT_SYMBOL(connsys_log_read_to_user);
+
+/*****************************************************************************
+ * FUNCTION
+ * connsys_log_read
+ * DESCRIPTION
+ * Read log in ring_cache to buf
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+ssize_t connsys_log_read(int conn_type, char *buf, size_t count)
+{
+ unsigned int ret = 0;
+ struct connlog_dev* handler;
+
+ if (conn_type < CONN_DEBUG_TYPE_WIFI || conn_type >= CONN_DEBUG_TYPE_END)
+ goto done;
+ if (atomic_read(&g_log_mode) != LOG_TO_FILE)
+ goto done;
+
+ handler = gLogDev[conn_type];
+ ret = connlog_read_internal(handler, conn_type, buf, NULL, count, false);
+done:
+ return ret;
+}
+EXPORT_SYMBOL(connsys_log_read);
+
+
+/*****************************************************************************
+ * FUNCTION
+ * connsys_dedicated_log_set_log_mode
+ * DESCRIPTION
+ * set log mode.
+ * PARAMETERS
+ * mode [IN] log mode
+ * RETURNS
+ * void
+ *****************************************************************************/
+void connsys_dedicated_log_set_log_mode(int mode)
+{
+ atomic_set(&g_log_mode, (mode > 0 ? LOG_TO_FILE : PRINT_TO_KERNEL_LOG));
+}
+EXPORT_SYMBOL(connsys_dedicated_log_set_log_mode);
+
+/*****************************************************************************
+* FUNCTION
+* connsys_dedicated_log_get_log_mode
+* DESCRIPTION
+* get log mode.
+* PARAMETERS
+* void
+* RETURNS
+* int log mode
+*****************************************************************************/
+int connsys_dedicated_log_get_log_mode(void)
+{
+ return atomic_read(&g_log_mode);
+}
+EXPORT_SYMBOL(connsys_dedicated_log_get_log_mode);
+
+/*****************************************************************************
+* FUNCTION
+* connsys_log_irq_handler
+* DESCRIPTION
+*
+* PARAMETERS
+* void
+* RETURNS
+* int
+*****************************************************************************/
+int connsys_log_irq_handler(int conn_type)
+{
+ struct connlog_dev* handler;
+ if (conn_type < CONN_DEBUG_TYPE_WIFI || conn_type >= CONN_DEBUG_TYPE_END)
+ return -1;
+
+ handler = gLogDev[conn_type];
+ if (handler == NULL) {
+ pr_err("[%s][%s] didn't init\n", __func__, type_to_title[conn_type]);
+ return -1;
+ }
+
+ connlog_do_schedule_work(handler, true);
+ return 0;
+}
+EXPORT_SYMBOL(connsys_log_irq_handler);
+
+/*****************************************************************************
+* FUNCTION
+* connsys_log_register_event_cb
+* DESCRIPTION
+*·
+* PARAMETERS
+* void
+* RETURNS
+*
+*****************************************************************************/
+int connsys_log_register_event_cb(int conn_type, CONNLOG_EVENT_CB func)
+{
+ struct connlog_dev* handler;
+ if (conn_type < CONN_DEBUG_TYPE_WIFI || conn_type >= CONN_DEBUG_TYPE_END)
+ return -1;
+
+ handler = gLogDev[conn_type];
+ if (handler == NULL) {
+ pr_err("[%s][%s] didn't init\n", __func__, type_to_title[conn_type]);
+ return -1;
+ }
+
+ handler->callback.log_data_handler = func;
+ return 0;
+}
+EXPORT_SYMBOL(connsys_log_register_event_cb);
+
+/*****************************************************************************
+* FUNCTION
+* connlog_subsys_init
+* DESCRIPTION
+*
+* PARAMETERS
+* conn_type [IN] subsys type
+* emi_addr [IN] physical emi
+* emi_size [IN] emi size
+* RETURNS
+* struct connlog_dev* the handler
+*****************************************************************************/
+static struct connlog_dev* connlog_subsys_init(
+ int conn_type,
+ phys_addr_t emi_addr,
+ unsigned int emi_size)
+{
+ struct connlog_dev* handler = 0;
+
+ if (conn_type < CONN_DEBUG_TYPE_WIFI || conn_type >= CONN_DEBUG_TYPE_END)
+ return 0;
+
+ handler = (struct connlog_dev*)kmalloc(sizeof(struct connlog_dev), GFP_KERNEL);
+ if (!handler)
+ return 0;
+
+ handler->conn_type = conn_type;
+ if (connlog_emi_init(handler, emi_addr, emi_size)) {
+ pr_err("[%s] EMI init failed\n", type_to_title[conn_type]);
+ goto error_exit;
+ }
+
+ if (connlog_ring_buffer_init(handler)) {
+ pr_err("[%s] Ring buffer init failed\n", type_to_title[conn_type]);
+ goto error_exit;
+ }
+
+ init_timer(&handler->workTimer);
+ handler->workTimer.data = (unsigned long)handler;
+ handler->workTimer.function = work_timer_handler;
+ handler->irq_counter = 0;
+ spin_lock_init(&handler->irq_lock);
+ INIT_WORK(&handler->logDataWorker, connlog_log_data_handler);
+
+ /* alarm timer */
+ return handler;
+
+error_exit:
+ if (handler)
+ connlog_subsys_deinit(handler);
+ return 0;
+
+}
+
+/*****************************************************************************
+* FUNCTION
+* connsys_log_init
+* DESCRIPTION
+*
+* PARAMETERS
+* void
+* RETURNS
+* int
+*****************************************************************************/
+int connsys_log_init(int conn_type)
+{
+ struct connlog_dev* handler;
+ phys_addr_t log_start_addr;
+ unsigned int log_size;
+ struct connlog_emi_config* emi_config;
+
+ if (conn_type < CONN_DEBUG_TYPE_WIFI || conn_type >= CONN_DEBUG_TYPE_END) {
+ pr_err("[%s] invalid type:%d\n", __func__, conn_type);
+ return -1;
+ }
+ if (gLogDev[conn_type] != NULL) {
+ pr_err("[%s][%s] double init.\n", __func__, type_to_title[conn_type]);
+ return 0;
+ }
+
+ emi_config = get_connsyslog_platform_config(conn_type);
+ if (!emi_config) {
+ pr_err("[%s] get emi config fail.\n", __func__);
+ return -1;
+ }
+
+ log_start_addr = emi_config->log_offset + gPhyEmiBase;
+ log_size = emi_config->log_size;
+ pr_info("%s init. Base=%p size=%d\n",
+ type_to_title[conn_type], log_start_addr, log_size);
+
+ handler = connlog_subsys_init(conn_type, log_start_addr, log_size);
+ if (handler == NULL) {
+ pr_err("[%s][%s] failed.\n", __func__, type_to_title[conn_type]);
+ return -1;
+ }
+
+ gLogDev[conn_type] = handler;
+ return 0;
+}
+EXPORT_SYMBOL(connsys_log_init);
+
+/*****************************************************************************
+* Function
+* connlog_subsys_deinit
+* DESCRIPTION
+*
+* PARAMETERS
+*
+* RETURNS
+*
+*****************************************************************************/
+static void connlog_subsys_deinit(struct connlog_dev* handler)
+{
+ if (handler == NULL)
+ return;
+
+ connlog_emi_deinit(handler);
+ connlog_ring_buffer_deinit(handler);
+ kfree(handler);
+}
+
+/*****************************************************************************
+* Function
+* connsys_log_deinit
+* DESCRIPTION
+*
+* PARAMETERS
+*
+* RETURNS
+*
+*****************************************************************************/
+int connsys_log_deinit(int conn_type)
+{
+ struct connlog_dev* handler;
+ if (conn_type < CONN_DEBUG_TYPE_WIFI || conn_type >= CONN_DEBUG_TYPE_END)
+ return -1;
+
+ handler = gLogDev[conn_type];
+ if (handler == NULL) {
+ pr_err("[%s][%s] didn't init\n", __func__, type_to_title[conn_type]);
+ return -1;
+ }
+
+ connlog_subsys_deinit(gLogDev[conn_type]);
+ gLogDev[conn_type] = NULL;
+ return 0;
+}
+EXPORT_SYMBOL(connsys_log_deinit);
+
+/*****************************************************************************
+* FUNCTION
+* connsys_log_get_utc_time
+* DESCRIPTION
+* Return UTC time
+* PARAMETERS
+* second [IN] UTC seconds
+* usecond [IN] UTC usecons
+* RETURNS
+* void
+*****************************************************************************/
+void connsys_log_get_utc_time(
+ unsigned int *second, unsigned int *usecond)
+{
+ struct timeval time;
+
+ do_gettimeofday(&time);
+ *second = (unsigned int)time.tv_sec; /* UTC time second unit */
+ *usecond = (unsigned int)time.tv_usec; /* UTC time microsecond unit */
+}
+EXPORT_SYMBOL(connsys_log_get_utc_time);
+
+static inline bool connlog_is_alarm_enable(void)
+{
+ if ((gLogAlarm.alarm_state & CONNLOG_ALARM_STATE_ENABLE) > 0)
+ return true;
+ return false;
+}
+
+static int connlog_set_alarm_timer(void)
+{
+ ktime_t kt;
+
+ kt = ktime_set(gLogAlarm.alarm_sec, 0);
+ alarm_start_relative(&gLogAlarm.alarm_timer, kt);
+
+ pr_info("[connsys_log_alarm] alarm timer enabled timeout=[%d]", gLogAlarm.alarm_sec);
+ return 0;
+}
+
+static int connlog_cancel_alarm_timer(void)
+{
+ pr_info("[connsys_log_alarm] alarm timer cancel");
+ return alarm_cancel(&gLogAlarm.alarm_timer);
+}
+
+
+static enum alarmtimer_restart connlog_alarm_timer_handler(struct alarm *alarm,
+ ktime_t now)
+{
+ ktime_t kt;
+ struct rtc_time tm;
+ unsigned int tsec, tusec;
+ int i;
+
+ connsys_log_get_utc_time(&tsec, &tusec);
+ rtc_time_to_tm(tsec, &tm);
+ pr_info("[connsys_log_alarm] alarm_timer triggered [%d-%02d-%02d %02d:%02d:%02d.%09u]"
+ , tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday
+ , tm.tm_hour, tm.tm_min, tm.tm_sec, tusec);
+
+ for (i = 0; i < CONN_DEBUG_TYPE_END; i++) {
+ if (gLogDev[i]) {
+ connlog_do_schedule_work(gLogDev[i], false);
+ }
+ }
+
+ spin_lock_irqsave(&gLogAlarm.alarm_lock, gLogAlarm.flags);
+ kt = ktime_set(gLogAlarm.alarm_sec, 0);
+ alarm_start_relative(&gLogAlarm.alarm_timer, kt);
+ spin_unlock_irqrestore(&gLogAlarm.alarm_lock, gLogAlarm.flags);
+
+ return ALARMTIMER_NORESTART;
+}
+
+static int connlog_alarm_init(void)
+{
+ alarm_init(&gLogAlarm.alarm_timer, ALARM_REALTIME, connlog_alarm_timer_handler);
+ gLogAlarm.alarm_state = CONNLOG_ALARM_STATE_DISABLE;
+ spin_lock_init(&gLogAlarm.alarm_lock);
+
+ return 0;
+}
+
+/*****************************************************************************
+* FUNCTION
+* connsys_dedicated_log_path_alarm_enable
+* DESCRIPTION
+* Enable log timer.
+* When log timer is enable, it starts every sec seconds to fetch log from EMI
+* to file.
+* Usually enable log timer for debug.
+* PARAMETERS
+* sec [IN] timer config
+* RETURNS
+* int
+*****************************************************************************/
+int connsys_dedicated_log_path_alarm_enable(unsigned int sec)
+{
+ if (!gPhyEmiBase)
+ return -1;
+
+ spin_lock_irqsave(&gLogAlarm.alarm_lock, gLogAlarm.flags);
+
+ gLogAlarm.alarm_sec = sec;
+ if (!connlog_is_alarm_enable()) {
+ gLogAlarm.alarm_state = CONNLOG_ALARM_STATE_ENABLE;
+ pr_info("[connsys_log_alarm] alarm timer enabled timeout=[%d]", sec);
+ }
+ if (gLogAlarm.blank_state == 0)
+ connlog_set_alarm_timer();
+
+ spin_unlock_irqrestore(&gLogAlarm.alarm_lock, gLogAlarm.flags);
+ return 0;
+}
+EXPORT_SYMBOL(connsys_dedicated_log_path_alarm_enable);
+
+/*****************************************************************************
+* FUNCTION
+* connsys_dedicated_log_path_alarm_disable
+* DESCRIPTION
+* Disable log timer
+* PARAMETERS
+*
+* RETURNS
+* int
+*****************************************************************************/
+int connsys_dedicated_log_path_alarm_disable(void)
+{
+ int ret;
+
+ if (!gPhyEmiBase)
+ return -1;
+
+ spin_lock_irqsave(&gLogAlarm.alarm_lock, gLogAlarm.flags);
+
+ if (connlog_is_alarm_enable()) {
+ ret = connlog_cancel_alarm_timer();
+ gLogAlarm.alarm_state = CONNLOG_ALARM_STATE_ENABLE;
+ pr_info("[connsys_log_alarm] alarm timer disable ret=%d", ret);
+ }
+ spin_unlock_irqrestore(&gLogAlarm.alarm_lock, gLogAlarm.flags);
+ return 0;
+}
+EXPORT_SYMBOL(connsys_dedicated_log_path_alarm_disable);
+
+/****************************************************************************
+* FUNCTION
+* connsys_dedicated_log_path_blank_state_changed
+* DESCRIPTION
+*
+* PARAMETERS
+*
+* RETURNS
+* int
+*****************************************************************************/
+int connsys_dedicated_log_path_blank_state_changed(int blank_state)
+{
+ int ret = 0;
+
+ if (!gPhyEmiBase)
+ return -1;
+ spin_lock_irqsave(&gLogAlarm.alarm_lock, gLogAlarm.flags);
+ gLogAlarm.blank_state = blank_state;
+ if (connlog_is_alarm_enable()) {
+ if (blank_state == 0)
+ ret = connlog_set_alarm_timer();
+ else
+ ret = connlog_cancel_alarm_timer();
+ }
+
+ spin_unlock_irqrestore(&gLogAlarm.alarm_lock, gLogAlarm.flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(connsys_dedicated_log_path_blank_state_changed);
+
+/*****************************************************************************
+* FUNCTION
+* connsys_dedicated_log_path_apsoc_init
+* DESCRIPTION
+* Initialize API for common driver to initialize connsys dedicated log
+* for APSOC platform
+* PARAMETERS
+* emiaddr [IN] EMI physical base address
+* RETURNS
+* void
+****************************************************************************/
+int connsys_dedicated_log_path_apsoc_init(phys_addr_t emiaddr)
+{
+ if (gPhyEmiBase != 0 || emiaddr == 0) {
+ pr_err("Connsys log double init or invalid parameter(emiaddr=%p)\n", emiaddr);
+ return -1;
+ }
+
+ gPhyEmiBase = emiaddr;
+
+ connlog_alarm_init();
+ return 0;
+}
+EXPORT_SYMBOL(connsys_dedicated_log_path_apsoc_init);
+
+/*****************************************************************************
+* FUNCTION
+* connsys_dedicated_log_path_apsoc_deinit
+* DESCRIPTION
+* De-Initialize API for common driver to release cache, un-remap emi and free
+* irq for APSOC platform
+* PARAMETERS
+* void
+* RETURNS
+* void
+*****************************************************************************/
+int connsys_dedicated_log_path_apsoc_deinit(void)
+{
+ int i;
+
+ /* Check subsys */
+ for (i = 0; i < CONN_DEBUG_TYPE_END; i++) {
+ if (gLogDev[i] != NULL) {
+ pr_err("[%s] subsys %s should be deinit first.\n",
+ __func__, type_to_title[i]);
+ return -1;
+ }
+ }
+
+ gPhyEmiBase = 0;
+ return 0;
+}
+EXPORT_SYMBOL(connsys_dedicated_log_path_apsoc_deinit);
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/connsyslog.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/connsyslog.h
new file mode 100644
index 0000000..6e410ec
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/connsyslog.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _CONNSYSLOG_H_
+#define _CONNSYSLOG_H_
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+#include "connsys_debug_utility.h"
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+/* Close debug log */
+//#define DEBUG_LOG_ON 1
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+enum FW_LOG_MODE {
+ PRINT_TO_KERNEL_LOG = 0,
+ LOG_TO_FILE = 1,
+};
+
+typedef void (*CONNLOG_EVENT_CB) (void);
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+/* utility */
+void connsys_log_dump_buf(const char *title, const char *buf, ssize_t sz);
+void connsys_log_get_utc_time(
+ unsigned int *second, unsigned int *usecond);
+
+/* Global config */
+int connsys_dedicated_log_path_apsoc_init(phys_addr_t emiaddr);
+int connsys_dedicated_log_path_apsoc_deinit(void);
+void connsys_dedicated_log_set_log_mode(int mode);
+int connsys_dedicated_log_get_log_mode(void);
+int connsys_dedicated_log_path_alarm_enable(unsigned int sec);
+int connsys_dedicated_log_path_alarm_disable(void);
+int connsys_dedicated_log_path_blank_state_changed(int blank_state);
+
+/* For subsys */
+int connsys_log_init(int conn_type);
+int connsys_log_deinit(int conn_type);
+unsigned int connsys_log_get_buf_size(int conn_type);
+int connsys_log_register_event_cb(int conn_type, CONNLOG_EVENT_CB func);
+ssize_t connsys_log_read_to_user(int conn_type, char __user *buf, size_t count);
+ssize_t connsys_log_read(int conn_type, char *buf, size_t count);
+int connsys_log_irq_handler(int conn_type);
+
+#endif /*_CONNSYSLOG_H_*/
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/connsyslog_emi.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/connsyslog_emi.h
new file mode 100644
index 0000000..d2d823b
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/connsyslog_emi.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef _CONNSYSLOG_EMI_H_
+#define _CONNSYSLOG_EMI_H_
+
+#define CONNLOG_EMI_32_BYTE_ALIGNED 32 /* connsys EMI cache is 32-byte aligned */
+#define CONNLOG_CONTROL_RING_BUFFER_BASE_SIZE 64 /* Reserve for setup ring buffer base address */
+#define CONNLOG_CONTROL_RING_BUFFER_RESERVE_SIZE 32
+#define CONNLOG_IRQ_COUNTER_BASE 48
+#define CONNLOG_READY_PATTERN_BASE 56
+#define CONNLOG_READY_PATTERN_BASE_SIZE 8
+#define CONNLOG_EMI_END_PATTERN_SIZE CONNLOG_EMI_32_BYTE_ALIGNED
+#define CONNLOG_EMI_END_PATTERN "FWLOGENDFWLOGENDFWLOGENDFWLOGEND"
+
+#define CONNLOG_EMI_BASE_OFFSET CONNLOG_CONTROL_RING_BUFFER_BASE_SIZE
+#define CONNLOG_EMI_READ (CONNLOG_EMI_BASE_OFFSET + 0)
+#define CONNLOG_EMI_WRITE (CONNLOG_EMI_BASE_OFFSET + 4)
+#define CONNLOG_EMI_BUF (CONNLOG_EMI_BASE_OFFSET + \
+ CONNLOG_EMI_32_BYTE_ALIGNED)
+
+#endif /* _CONNSYSLOG_EMI_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/platform/include/connsyslog_hw_config.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/platform/include/connsyslog_hw_config.h
new file mode 100644
index 0000000..df226ec
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/platform/include/connsyslog_hw_config.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __CONNSYSLOG_HW_CONFIG_H__
+#define __CONNSYSLOG_HW_CONFIG_H__
+
+struct connlog_emi_config {
+ phys_addr_t log_offset;
+ unsigned int log_size;
+};
+
+#endif /* __CONNSYSLOG_HW_CONFIG_H__ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/platform/mt6885/mt6885.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/platform/mt6885/mt6885.c
new file mode 100644
index 0000000..e58b5b6
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/platform/mt6885/mt6885.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#include <linux/printk.h>
+
+#include "connsys_debug_utility.h"
+#include "connsyslog_hw_config.h"
+
+#ifdef CONFIG_FPGA_EARLY_PORTING
+#define CONNLOG_EMI_OFFSET_WIFI 0x0001F000
+#define CONNLOG_EMI_OFFSET_BT 0x0002F000
+#else
+#define CONNLOG_EMI_OFFSET_WIFI 0x0024F000
+#define CONNLOG_EMI_OFFSET_BT 0x0004b000
+#endif
+
+#define CONNLOG_EMI_SIZE_WIFI (192*1024)
+#define CONNLOG_EMI_SIZE_BT (64*1024)
+
+struct connlog_emi_config g_connsyslog_config[CONN_DEBUG_TYPE_END] = {
+ /* Wi-Fi config */
+ {CONNLOG_EMI_OFFSET_WIFI, CONNLOG_EMI_SIZE_WIFI},
+ {CONNLOG_EMI_OFFSET_BT, CONNLOG_EMI_SIZE_BT},
+};
+
+struct connlog_emi_config* get_connsyslog_platform_config(int conn_type)
+{
+ if (conn_type < 0 || conn_type >= CONN_DEBUG_TYPE_END) {
+ pr_err("Incorrect type: %d\n", conn_type);
+ return NULL;
+ }
+ return &g_connsyslog_config[conn_type];
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/ring.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/ring.c
new file mode 100644
index 0000000..240f538
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/ring.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include "ring.h"
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/bug.h>
+
+
+
+void ring_init(void *base, unsigned int max_size, unsigned int read,
+ unsigned int write, struct ring *ring)
+{
+ WARN_ON(!base);
+
+ /* making sure max_size is power of 2 */
+ WARN_ON(!max_size || (max_size & (max_size - 1)));
+
+ /* making sure write largger than read */
+ WARN_ON(read > write);
+
+ ring->base = base;
+ ring->read = read;
+ ring->write = write;
+ ring->max_size = max_size;
+}
+
+void ring_dump(const char *title, struct ring *ring)
+{
+ pr_info("[%s] ring:{write=%d, read=%d, max_size=%d}\n",
+ title, ring->write, ring->read, ring->max_size);
+}
+
+void ring_dump_segment(const char *title, struct ring_segment *seg)
+{
+ pr_info("[%s] seg:{ring_pt=0x%p, data_pos=%d, sz=%d, remain=%d}\n",
+ title, seg->ring_pt, seg->data_pos, seg->sz, seg->remain);
+}
+
+/*
+ * Function prepares the ring_segment and returns the number of valid bytes for read.
+ */
+unsigned int ring_read_prepare(unsigned int sz, struct ring_segment *seg, struct ring *ring)
+{
+ unsigned int wt = ring->write;
+ unsigned int rd = ring->read;
+
+ memset(seg, 0, sizeof(struct ring_segment));
+ if (sz > wt - rd)
+ sz = wt - rd;
+ seg->remain = sz;
+ /* ring_dump(__func__, ring); */
+ /* ring_dump_segment(__func__, seg); */
+ return seg->remain;
+}
+
+/*
+ * Function prepares the ring_segment and returns the number of bytes available for write.
+ */
+unsigned int ring_write_prepare(unsigned int sz, struct ring_segment *seg, struct ring *ring)
+{
+ unsigned int wt = ring->write;
+ unsigned int rd = ring->read;
+
+ memset(seg, 0, sizeof(struct ring_segment));
+ if (sz > ring->max_size - (wt - rd))
+ sz = ring->max_size - (wt - rd);
+ seg->remain = sz;
+ /* ring_dump(__func__, ring); */
+ /* ring_dump_segment(__func__, seg); */
+ return seg->remain;
+}
+
+unsigned int ring_overwrite_prepare(unsigned int sz, struct ring_segment *seg,
+ struct ring *ring)
+{
+ unsigned int wt = ring->write;
+ unsigned int rd = ring->read;
+
+ memset(seg, 0, sizeof(struct ring_segment));
+ if (sz > ring->max_size - (wt - rd))
+ ring->read += sz - (ring->max_size - (wt - rd));
+ seg->remain = sz;
+ /* ring_dump(__func__, ring); */
+ /* ring_dump_segment(__func__, seg); */
+ return seg->remain;
+}
+
+void __ring_segment_prepare(unsigned int from, unsigned int sz, struct ring_segment *seg,
+ struct ring *ring)
+{
+ unsigned int ring_pos = from & (ring->max_size - 1);
+
+ seg->ring_pt = ring->base + ring_pos;
+ seg->data_pos = (seg->sz ? seg->data_pos + seg->sz : 0);
+ if (ring_pos + sz <= ring->max_size)
+ seg->sz = sz;
+ else
+ seg->sz = ring->max_size - ring_pos;
+ seg->remain -= seg->sz;
+ /* ring_dump(__func__, ring); */
+ /* ring_dump_segment(__func__, seg); */
+}
+
+void _ring_segment_prepare(unsigned int from, struct ring_segment *seg, struct ring *ring)
+{
+ __ring_segment_prepare(from, seg->remain, seg, ring);
+}
+
+void _ring_segment_prepare_item(unsigned int from, struct ring_segment *seg, struct ring *ring)
+{
+ unsigned int size;
+
+ size = (seg->remain ? 1 : 0);
+ __ring_segment_prepare(from, size, seg, ring);
+}
+
+void _ring_read_commit(struct ring_segment *seg, struct ring *ring)
+{
+ ring->read += seg->sz;
+ /* ring_dump(__func__, ring); */
+ /* ring_dump_segment(__func__, seg); */
+}
+void _ring_write_commit(struct ring_segment *seg, struct ring *ring)
+{
+ ring->write += seg->sz;
+ /* ring_dump(__func__, ring); */
+ /* ring_dump_segment(__func__, seg); */
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/ring_emi.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/ring_emi.c
new file mode 100644
index 0000000..03115ad
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/ring_emi.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#include "ring_emi.h"
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/bug.h>
+
+void ring_emi_init(void *base, unsigned int max_size, void *read, void *write, struct ring_emi *ring_emi)
+{
+ WARN_ON(!base || !read || !write);
+
+ /* making sure max_size is power of 2 */
+ WARN_ON(!max_size || (max_size & (max_size - 1)));
+
+ /* making sure read & write pointers are 4 bytes aligned */
+ WARN_ON(((long)read & 0x3) != 0 || ((long)write & 0x3) != 0);
+
+ ring_emi->base = base;
+ ring_emi->read = read;
+ ring_emi->write = write;
+ EMI_WRITE32(ring_emi->write, 0);
+ EMI_WRITE32(ring_emi->read, 0);
+ ring_emi->max_size = max_size;
+ pr_info("write(%p) as 0, read(%p) as 0\n", ring_emi->write, ring_emi->read);
+ pr_info("base: %p, read: %p, write: %p, max_size: %d\n", base, read, write, max_size);
+}
+
+void ring_emi_dump(const char *title, struct ring_emi *ring_emi)
+{
+ pr_info("[%s] ring_emi:{base=0x%p, write=%d, read=%d, max_size=%d}\n",
+ title, ring_emi->base, EMI_READ32(ring_emi->write),
+ EMI_READ32(ring_emi->read), ring_emi->max_size);
+}
+
+void ring_emi_dump_segment(const char *title, struct ring_emi_segment *seg)
+{
+ pr_info("[%s] seg:{ring_emi_pt=0x%p, data_pos=%d, sz=%d, remain=%d}\n",
+ title, seg->ring_emi_pt, seg->data_pos, seg->sz, seg->remain);
+}
+
+/*
+ * Function prepares the ring_emi_segment and returns the number of valid bytes for read.
+ */
+unsigned int ring_emi_read_prepare(unsigned int sz, struct ring_emi_segment *seg, struct ring_emi *ring_emi)
+{
+ unsigned int wt = EMI_READ32(ring_emi->write);
+ unsigned int rd = EMI_READ32(ring_emi->read);
+
+ memset(seg, 0, sizeof(struct ring_emi_segment));
+#ifdef ROUND_REPEAT
+ if (wt >= rd) {
+ if (sz > wt - rd)
+ sz = wt - rd;
+ seg->remain = sz;
+ } else {
+ if (sz > ring_emi->max_size - (rd - wt))
+ sz = ring_emi->max_size - (rd - wt);
+ seg->remain = sz;
+ }
+#else
+ if (sz > wt - rd)
+ sz = wt - rd;
+ seg->remain = sz;
+#endif
+ /* ring_emi_dump(__func__, ring_emi); */
+ /* ring_emi_dump_segment(__func__, seg); */
+ return seg->remain;
+}
+
+/*
+ * Function prepares the ring_emi_segment and returns the number of bytes available for write.
+ */
+unsigned int ring_emi_write_prepare(unsigned int sz, struct ring_emi_segment *seg, struct ring_emi *ring_emi)
+{
+ unsigned int wt = EMI_READ32(ring_emi->write);
+ unsigned int rd = EMI_READ32(ring_emi->read);
+
+ memset(seg, 0, sizeof(struct ring_emi_segment));
+#ifdef ROUND_REPEAT
+ if (wt >= rd)
+ seg->remain = ring_emi->max_size - (wt - rd + 1);
+ else
+ seg->remain = ring_emi->max_size - (rd - wt + 1);
+
+ if (sz <= seg->remain)
+ seg->remain = sz;
+#else
+ if (sz > ring_emi->max_size - (wt - rd))
+ sz = ring_emi->max_size - (wt - rd);
+ seg->remain = sz;
+#endif
+ /* ring_emi_dump(__func__, ring_emi); */
+ /* ring_emi_dump_segment(__func__, seg); */
+ return seg->remain;
+}
+
+void _ring_emi_segment_prepare(unsigned int from, struct ring_emi_segment *seg, struct ring_emi *ring_emi)
+{
+#ifndef ROUND_REPEAT
+ unsigned int ring_emi_pos = from & (ring_emi->max_size - 1);
+
+ seg->ring_emi_pt = ring_emi->base + ring_emi_pos;
+#else
+ seg->ring_emi_pt = ring_emi->base + from;
+#endif
+ seg->data_pos = (seg->sz ? seg->data_pos + seg->sz : 0);
+ if (from + seg->remain <= ring_emi->max_size)
+ seg->sz = seg->remain;
+ else
+ seg->sz = ring_emi->max_size - from;
+ seg->remain -= seg->sz;
+ /* ring_emi_dump(__func__, ring_emi); */
+ /* ring_emi_dump_segment(__func__, seg); */
+}
+
+void _ring_emi_read_commit(struct ring_emi_segment *seg, struct ring_emi *ring_emi)
+{
+#ifdef ROUND_REPEAT
+#ifdef DEBUG_LOG_ON
+ pr_info("[%s] write %p as %d\n", __func__, ring_emi->read, (EMI_READ32(ring_emi->read) + seg->sz) & (ring_emi->max_size - 1));
+#endif
+ EMI_WRITE32(ring_emi->read, (EMI_READ32(ring_emi->read) + seg->sz) & (ring_emi->max_size - 1));
+#else
+#ifdef DEBUG_LOG_ON
+ pr_info("[%s] write %p as %d\n", __func__, ring_emi->read, EMI_READ32(ring_emi->read) + seg->sz);
+#endif
+ EMI_WRITE32(ring_emi->read, EMI_READ32(ring_emi->read) + seg->sz);
+#endif
+ /* *(ring_emi->read) += seg->sz; */
+ /* ring_emi_dump(__func__, ring_emi); */
+ /* ring_emi_dump_segment(__func__, seg); */
+}
+void _ring_emi_write_commit(struct ring_emi_segment *seg, struct ring_emi *ring_emi)
+{
+#ifdef ROUND_REPEAT
+#ifdef DEBUG_LOG_ON
+ pr_info("[%s] write %p as %d\n", __func__, (EMI_READ32(ring_emi->write) + seg->sz) & (ring_emi->max_size - 1));
+#endif
+ EMI_WRITE32(ring_emi->write, (EMI_READ32(ring_emi->write) + seg->sz) & (ring_emi->max_size - 1));
+#else
+#ifdef DEBUG_LOG_ON
+ pr_info("[%s] write %p as %d\n", __func__, ring_emi->write, EMI_READ32(ring_emi->write) + seg->sz);
+#endif
+ EMI_WRITE32(ring_emi->write, EMI_READ32(ring_emi->write) + seg->sz);
+#endif
+ /* ring_emi_dump(__func__, ring_emi); */
+ /* ring_emi_dump_segment(__func__, seg); */
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/ring_emi.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/ring_emi.h
new file mode 100644
index 0000000..5969fd9
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/connsyslog/ring_emi.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef _RING_EMI_H_
+#define _RING_EMI_H_
+
+#include <linux/io.h>
+#define ROUND_REPEAT
+#define EMI_READ32(addr) (readl(addr))
+#define EMI_WRITE32(addr, data) (writel(data, addr))
+
+struct ring_emi {
+ /* addr where ring buffer starts */
+ void *base;
+ /* addr storing the next writable pos, guaranteed to be >= read except when write overflow, but it's ok. */
+ void *write;
+ /* addr storing the next readable pos, except when read == write as buffer empty */
+ void *read;
+ /* must be power of 2 */
+ unsigned int max_size;
+};
+
+struct ring_emi_segment {
+ /* addr points into ring buffer for read/write */
+ void *ring_emi_pt;
+ /* size to read/write */
+ unsigned int sz;
+ /* pos in external data buffer to read/write */
+ unsigned int data_pos;
+ /* the size to be read/write after this segment completed */
+ unsigned int remain;
+};
+
+void ring_emi_init(void *base, unsigned int max_size, void *read, void *write, struct ring_emi *ring_emi);
+unsigned int ring_emi_read_prepare(unsigned int sz, struct ring_emi_segment *seg, struct ring_emi *ring_emi);
+#define ring_emi_read_all_prepare(seg, ring_emi) ring_emi_read_prepare((ring_emi)->max_size, seg, ring_emi)
+unsigned int ring_emi_write_prepare(unsigned int sz, struct ring_emi_segment *seg, struct ring_emi *ring_emi);
+
+/* making sure max_size is power of 2 */
+#define RING_EMI_VALIDATE_SIZE(max_size) WARN_ON(!max_size || (max_size & (max_size - 1)))
+
+#define RING_EMI_EMPTY(ring_emi) (EMI_READ32((ring_emi)->read) == EMI_READ32((ring_emi)->write))
+/* equation works even when write overflow */
+#define RING_EMI_SIZE(ring_emi) (EMI_READ32((ring_emi)->write) - EMI_READ32((ring_emi)->read))
+#ifdef ROUND_REPEAT
+#define RING_EMI_FULL(ring_emi) (((EMI_READ32((ring_emi)->write) + 1) & ((ring_emi)->max_size - 1)) \
+ == EMI_READ32((ring_emi)->read))
+#else
+#define RING_EMI_FULL(ring_emi) (RING_EMI_SIZE(ring_emi) == (ring_emi)->max_size)
+#endif
+
+#define RING_EMI_READ_FOR_EACH(_sz, _seg, _ring_emi) \
+ for (_ring_emi_segment_prepare(EMI_READ32((_ring_emi)->read), &(_seg), (_ring_emi)); \
+ (_seg).sz > 0; \
+ _ring_emi_read_commit(&(_seg), (_ring_emi)), \
+ _ring_emi_segment_prepare(EMI_READ32((_ring_emi)->read), &(_seg), (_ring_emi)))
+
+#define RING_EMI_READ_ALL_FOR_EACH(seg, ring_emi) RING_EMI_READ_FOR_EACH((ring_emi)->max_size, seg, ring_emi)
+
+#define RING_EMI_WRITE_FOR_EACH(_sz, _seg, _ring_emi) \
+ for (_ring_emi_segment_prepare(EMI_READ32((_ring_emi)->write), &(_seg), (_ring_emi)); \
+ (_seg).sz > 0; \
+ _ring_emi_write_commit(&(_seg), (_ring_emi)), \
+ _ring_emi_segment_prepare(EMI_READ32((_ring_emi)->write), &(_seg), (_ring_emi)))
+
+void ring_emi_dump(const char *title, struct ring_emi *ring_emi);
+void ring_emi_dump_segment(const char *title, struct ring_emi_segment *seg);
+
+
+/* Ring Buffer Internal API */
+void _ring_emi_segment_prepare(unsigned int from, struct ring_emi_segment *seg, struct ring_emi *ring_emi);
+void _ring_emi_read_commit(struct ring_emi_segment *seg, struct ring_emi *ring_emi);
+void _ring_emi_write_commit(struct ring_emi_segment *seg, struct ring_emi *ring_emi);
+
+#endif
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/conndump_netlink.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/conndump_netlink.c
new file mode 100755
index 0000000..7c96564
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/conndump_netlink.c
@@ -0,0 +1,535 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <net/sock.h>
+#include <net/netlink.h>
+#include <linux/skbuff.h>
+#include <net/genetlink.h>
+
+#include "connsys_debug_utility.h"
+#include "conndump_netlink.h"
+
+
+/*******************************************************************************
+* MACROS
+********************************************************************************
+*/
+#define MAX_BIND_PROCESS (4)
+
+#define CONNSYS_DUMP_NETLINK_FAMILY_NAME_WIFI "CONNDUMP_WIFI"
+#define CONNSYS_DUMP_NETLINK_FAMILY_NAME_BT "CONNDUMP_BT"
+
+#ifndef GENL_ID_GENERATE
+#define GENL_ID_GENERATE 0
+#endif
+
+#define CONNSYS_DUMP_PKT_SIZE NLMSG_DEFAULT_SIZE
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+enum {
+ __CONNDUMP_ATTR_INVALID,
+ CONNDUMP_ATTR_MSG,
+ CONNDUMP_ATTR_PORT,
+ CONNDUMP_ATTR_HEADER,
+ CONNDUMP_ATTR_MSG_SIZE,
+ CONNDUMP_ATTR_LAST,
+ __CONNDUMP_ATTR_MAX,
+};
+#define CONNDUMP_ATTR_MAX (__CONNDUMP_ATTR_MAX - 1)
+
+enum {
+ __CONNDUMP_COMMAND_INVALID,
+ CONNDUMP_COMMAND_BIND,
+ CONNDUMP_COMMAND_DUMP,
+ CONNDUMP_COMMAND_END,
+ CONNDUMP_COMMAND_RESET,
+ __CONNDUMP_COMMAND_MAX,
+};
+
+enum LINK_STATUS {
+ LINK_STATUS_INIT,
+ LINK_STATUS_INIT_DONE,
+ LINK_STATUS_MAX,
+};
+
+struct dump_netlink_ctx {
+ int conn_type;
+ pid_t bind_pid[MAX_BIND_PROCESS];
+ unsigned int num_bind_process;
+ struct genl_family gnl_family;
+ unsigned int seqnum;
+ struct mutex nl_lock;
+ enum LINK_STATUS status;
+ void* coredump_ctx;
+ struct netlink_event_cb cb;
+};
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+static int conndump_nl_bind_wifi(struct sk_buff *skb, struct genl_info *info);
+static int conndump_nl_dump_wifi(struct sk_buff *skb, struct genl_info *info);
+static int conndump_nl_dump_end_wifi(struct sk_buff *skb, struct genl_info *info);
+static int conndump_nl_reset_wifi(struct sk_buff *skb, struct genl_info *info);
+static int conndump_nl_bind_bt(struct sk_buff *skb, struct genl_info *info);
+static int conndump_nl_dump_bt(struct sk_buff *skb, struct genl_info *info);
+static int conndump_nl_dump_end_bt(struct sk_buff *skb, struct genl_info *info);
+static int conndump_nl_reset_bt(struct sk_buff *skb, struct genl_info *info);
+
+/*******************************************************************************
+* G L O B A L V A R I A B L E
+********************************************************************************
+*/
+
+/* attribute policy */
+static struct nla_policy conndump_genl_policy[CONNDUMP_ATTR_MAX + 1] = {
+ [CONNDUMP_ATTR_MSG] = {.type = NLA_NUL_STRING},
+ [CONNDUMP_ATTR_PORT] = {.type = NLA_U32},
+ [CONNDUMP_ATTR_HEADER] = {.type = NLA_NUL_STRING},
+ [CONNDUMP_ATTR_MSG_SIZE] = {.type = NLA_U32},
+ [CONNDUMP_ATTR_LAST] = {.type = NLA_U32},
+};
+
+
+/* operation definition */
+static struct genl_ops conndump_gnl_ops_array_wifi[] = {
+ {
+ .cmd = CONNDUMP_COMMAND_BIND,
+ .flags = 0,
+ .policy = conndump_genl_policy,
+ .doit = conndump_nl_bind_wifi,
+ .dumpit = NULL,
+ },
+ {
+ .cmd = CONNDUMP_COMMAND_DUMP,
+ .flags = 0,
+ .policy = conndump_genl_policy,
+ .doit = conndump_nl_dump_wifi,
+ .dumpit = NULL,
+ },
+ {
+ .cmd = CONNDUMP_COMMAND_END,
+ .flags = 0,
+ .policy = conndump_genl_policy,
+ .doit = conndump_nl_dump_end_wifi,
+ .dumpit = NULL,
+ },
+ {
+ .cmd = CONNDUMP_COMMAND_RESET,
+ .flags = 0,
+ .policy = conndump_genl_policy,
+ .doit = conndump_nl_reset_wifi,
+ .dumpit = NULL,
+ },
+};
+
+static struct genl_ops conndump_gnl_ops_array_bt[] = {
+ {
+ .cmd = CONNDUMP_COMMAND_BIND,
+ .flags = 0,
+ .policy = conndump_genl_policy,
+ .doit = conndump_nl_bind_bt,
+ .dumpit = NULL,
+ },
+ {
+ .cmd = CONNDUMP_COMMAND_DUMP,
+ .flags = 0,
+ .policy = conndump_genl_policy,
+ .doit = conndump_nl_dump_bt,
+ .dumpit = NULL,
+ },
+ {
+ .cmd = CONNDUMP_COMMAND_END,
+ .flags = 0,
+ .policy = conndump_genl_policy,
+ .doit = conndump_nl_dump_end_bt,
+ .dumpit = NULL,
+ },
+ {
+ .cmd = CONNDUMP_COMMAND_RESET,
+ .flags = 0,
+ .policy = conndump_genl_policy,
+ .doit = conndump_nl_reset_bt,
+ .dumpit = NULL,
+ },
+};
+
+struct dump_netlink_ctx g_netlink_ctx[2] = {
+ /* WIFI */
+ {
+ .conn_type = CONN_DEBUG_TYPE_WIFI,
+ .gnl_family = {
+ .id = GENL_ID_GENERATE,
+ .hdrsize = 0,
+ .name = CONNSYS_DUMP_NETLINK_FAMILY_NAME_WIFI,
+ .version = 1,
+ .maxattr = CONNDUMP_ATTR_MAX,
+ .ops = conndump_gnl_ops_array_wifi,
+ .n_ops = ARRAY_SIZE(conndump_gnl_ops_array_wifi),
+ },
+ .status = LINK_STATUS_INIT,
+ .num_bind_process = 0,
+ .seqnum = 0,
+ },
+ /* BT */
+ {
+ .conn_type = CONN_DEBUG_TYPE_BT,
+ .gnl_family = {
+ .id = GENL_ID_GENERATE,
+ .hdrsize = 0,
+ .name = CONNSYS_DUMP_NETLINK_FAMILY_NAME_BT,
+ .version = 1,
+ .maxattr = CONNDUMP_ATTR_MAX,
+ .ops = conndump_gnl_ops_array_bt,
+ .n_ops = ARRAY_SIZE(conndump_gnl_ops_array_bt),
+ },
+ .status = LINK_STATUS_INIT,
+ .num_bind_process = 0,
+ .seqnum = 0,
+ },
+};
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+static int conndump_nl_bind_internal(struct dump_netlink_ctx* ctx, struct sk_buff *skb, struct genl_info *info)
+{
+ int i;
+ struct nlattr *port_na;
+ unsigned int port;
+
+ if (info == NULL)
+ goto out;
+
+ if (mutex_lock_killable(&ctx->nl_lock))
+ return -1;
+
+ port_na = info->attrs[CONNDUMP_ATTR_PORT];
+ if (port_na) {
+ port = (unsigned int)nla_get_u32(port_na);
+ } else {
+ pr_err("%s:-> no port_na found\n");
+ return -1;
+ }
+
+ for (i = 0; i < MAX_BIND_PROCESS; i ++) {
+ if (ctx->bind_pid[i] == 0) {
+ ctx->bind_pid[i] = port;
+ ctx->num_bind_process++;
+ pr_info("%s():-> pid = %d\n", __func__, port);
+ break;
+ }
+ }
+ if (i == MAX_BIND_PROCESS) {
+ pr_err("%s(): exceeding binding limit %d\n", __func__, MAX_BIND_PROCESS);
+ }
+ mutex_unlock(&ctx->nl_lock);
+
+out:
+ return 0;
+}
+
+static int conndump_nl_dump_end_internal(struct dump_netlink_ctx* ctx, struct sk_buff *skb, struct genl_info *info)
+{
+ if (ctx && ctx->cb.coredump_end) {
+ pr_info("Get coredump end command, type=%d", ctx->conn_type);
+ ctx->cb.coredump_end(ctx->coredump_ctx);
+ }
+ return 0;
+}
+
+static int conndump_nl_bind_wifi(struct sk_buff *skb, struct genl_info *info)
+{
+ int ret = 0;
+
+ ret = conndump_nl_bind_internal(&g_netlink_ctx[CONN_DEBUG_TYPE_WIFI], skb, info);
+ return ret;
+}
+
+static int conndump_nl_dump_wifi(struct sk_buff *skb, struct genl_info *info)
+{
+ pr_err("%s(): should not be invoked\n", __func__);
+
+ return 0;
+}
+
+static int conndump_nl_dump_end_wifi(struct sk_buff *skb, struct genl_info *info)
+{
+ int ret = 0;
+
+ ret = conndump_nl_dump_end_internal(&g_netlink_ctx[CONN_DEBUG_TYPE_WIFI], skb, info);
+
+ return ret;
+}
+
+static int conndump_nl_reset_wifi(struct sk_buff *skb, struct genl_info *info)
+{
+ pr_err("%s(): should not be invoked\n", __func__);
+
+ return 0;
+}
+
+static int conndump_nl_bind_bt(struct sk_buff *skb, struct genl_info *info)
+{
+ int ret = 0;
+
+ ret = conndump_nl_bind_internal(&g_netlink_ctx[CONN_DEBUG_TYPE_BT], skb, info);
+ return ret;
+}
+
+static int conndump_nl_dump_bt(struct sk_buff *skb, struct genl_info *info)
+{
+ pr_err("%s(): should not be invoked\n", __func__);
+
+ return 0;
+}
+
+static int conndump_nl_dump_end_bt(struct sk_buff *skb, struct genl_info *info)
+{
+ int ret = 0;
+
+ ret = conndump_nl_dump_end_internal(&g_netlink_ctx[CONN_DEBUG_TYPE_BT], skb, info);
+
+ return ret;
+
+}
+
+static int conndump_nl_reset_bt(struct sk_buff *skb, struct genl_info *info)
+{
+ pr_err("%s(): should not be invoked\n", __func__);
+
+ return 0;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * conndump_netlink_init
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+int conndump_netlink_init(int conn_type, void* dump_ctx, struct netlink_event_cb* cb)
+{
+ int ret = 0;
+ struct dump_netlink_ctx* ctx;
+
+ if (conn_type < CONN_DEBUG_TYPE_WIFI || conn_type > CONN_DEBUG_TYPE_BT) {
+ pr_err("Incorrect type (%d)\n", conn_type);
+ return -1;
+ }
+
+ ctx = &g_netlink_ctx[conn_type];
+ mutex_init(&ctx->nl_lock);
+ ret = genl_register_family(&ctx->gnl_family);
+ if (ret != 0) {
+ pr_err("%s(): GE_NELINK family registration fail (ret=%d)\n", __func__, ret);
+ return -2;
+ }
+ ctx->status = LINK_STATUS_INIT_DONE;
+ memset(ctx->bind_pid, 0, sizeof(ctx->bind_pid));
+ ctx->coredump_ctx = dump_ctx;
+ memcpy(&(ctx->cb), cb, sizeof(struct netlink_event_cb));
+
+ return ret;
+}
+
+int conndump_netlink_msg_send(struct dump_netlink_ctx* ctx, char* tag, char* buf, unsigned int length, pid_t pid, unsigned int seq)
+{
+ struct sk_buff *skb;
+ void* msg_head = NULL;
+ int ret = 0;
+ int conn_type = ctx->conn_type;
+
+ /* Allocating a Generic Netlink message buffer */
+ skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (skb != NULL) {
+ /* Create message header */
+ msg_head = genlmsg_put(skb, 0, seq, &ctx->gnl_family, 0, CONNDUMP_COMMAND_DUMP);
+ if (msg_head == NULL) {
+ pr_err("%s(): genlmsg_put fail(conn_type=%d).\n", __func__, conn_type);
+ nlmsg_free(skb);
+ return -EMSGSIZE;
+ }
+ /* Add message attribute and content */
+ ret = nla_put_string(skb, CONNDUMP_ATTR_HEADER, tag);
+ if (ret != 0) {
+ pr_err("%s(): nla_put_string header fail(conn_type=%d): %d\n", __func__, conn_type, ret);
+ genlmsg_cancel(skb, msg_head);
+ nlmsg_free(skb);
+ return ret;
+ }
+ if (length) {
+ ret = nla_put(skb, CONNDUMP_ATTR_MSG, length, buf);
+ if (ret != 0) {
+ pr_err("%s(): nla_put fail(conn_type=%d): %d\n", __func__, conn_type, ret);
+ genlmsg_cancel(skb, msg_head);
+ nlmsg_free(skb);
+ return ret;
+ }
+ ret = nla_put_u32(skb, CONNDUMP_ATTR_MSG_SIZE, length);
+ if (ret != 0) {
+ pr_err("%s(): nal_put_u32 fail(conn_type=%d): %d\n", __func__, conn_type, ret);
+ genlmsg_cancel(skb, msg_head);
+ nlmsg_free(skb);
+ return ret;
+ }
+ }
+ /* finalize the message */
+ genlmsg_end(skb, msg_head);
+
+ /* sending message */
+ ret = genlmsg_unicast(&init_net, skb, pid);
+ } else {
+ pr_err("Allocate message error\n");
+ ret = -ENOMEM;
+ }
+
+ return ret;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * conndump_send_to_native
+ * DESCRIPTION
+ * Send dump content to native layer (AEE or dump service)
+ * PARAMETERS
+ * conn_type [IN] subsys type
+ * tag [IN] the tag for the content (null end string)
+ * [M] for coredump
+ * buf [IN] the content to dump (a buffer may not have end character)
+ * length [IN] dump length
+ * RETURNS
+ *
+ *****************************************************************************/
+int conndump_netlink_send_to_native_internal(struct dump_netlink_ctx* ctx, char* tag, char* buf, unsigned int length)
+{
+ int killed_num = 0;
+ int i, j, ret = 0;
+ unsigned int retry;
+
+ for (i = 0; i < ctx->num_bind_process; i++) {
+ ret =conndump_netlink_msg_send(ctx, tag, buf, length, ctx->bind_pid[i], ctx->seqnum);
+ if (ret != 0) {
+ pr_err("%s(): genlmsg_unicast fail (ret=%d): pid = %d seq=%d tag=%s\n",
+ __func__, ret, ctx->bind_pid[i], ctx->seqnum, tag);
+ if (ret == -EAGAIN) {
+ retry = 0;
+ while (retry < 100 && ret == -EAGAIN) {
+ msleep(10);
+ ret =conndump_netlink_msg_send(ctx, tag, buf, length, ctx->bind_pid[i], ctx->seqnum);
+ retry ++;
+ pr_err("%s(): genlmsg_unicast retry (%d)...: ret = %d pid = %d seq=%d tag=%s\n",
+ __func__, retry, ret, ctx->bind_pid[i], ctx->seqnum, tag);
+ }
+ if (ret) {
+ pr_err("%s(): genlmsg_unicast fail (ret=%d) after retry %d times: pid = %d seq=%d tag=%s\n",
+ __func__, ret, retry, ctx->bind_pid[i], ctx->seqnum, tag);
+ }
+ }
+ if (ret == -ECONNREFUSED) {
+ ctx->bind_pid[i] = 0;
+ killed_num++;
+ }
+ }
+ }
+
+ ctx->seqnum ++;
+
+ /* Clean up invalid bind_pid */
+ if (killed_num > 0) {
+ if (mutex_lock_killable(&ctx->nl_lock)) {
+ /* if fail to get lock, it is fine to update bind_pid[] later */
+ return ret;
+ }
+ for (i = 0; i < ctx->num_bind_process - killed_num; i++) {
+ if (ctx->bind_pid[i] == 0) {
+ for (j = ctx->num_bind_process - 1; j > i; j--) {
+ if (ctx->bind_pid[j] > 0) {
+ ctx->bind_pid[i] = ctx->bind_pid[j];
+ ctx->bind_pid[j] = 0;
+ }
+ }
+ }
+ }
+ ctx->num_bind_process -= killed_num;
+ mutex_unlock(&ctx->nl_lock);
+ }
+
+ return ret;
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ * conndump_send_to_native
+ * DESCRIPTION
+ * Send dump content to native layer (AEE or dump service)
+ * PARAMETERS
+ * conn_type [IN] subsys type
+ * tag [IN] the tag for the content (null end string)
+ * [M] for coredump
+ * buf [IN] the content to dump (a buffer may not have end character)
+ * length [IN] dump length
+ * RETURNS
+ *
+ *****************************************************************************/
+int conndump_netlink_send_to_native(int conn_type, char* tag, char* buf, unsigned int length)
+{
+ struct dump_netlink_ctx* ctx;
+ int idx = 0;
+ unsigned int send_len;
+ unsigned int remain_len = length;
+ int ret;
+
+ pr_info("[%s] conn_type=%d tag=%s buf=0x%x length=%d\n",
+ __func__, conn_type, tag, buf, length);
+ if ((conn_type < CONN_DEBUG_TYPE_WIFI || conn_type > CONN_DEBUG_TYPE_BT) || tag == NULL) {
+ pr_err("Incorrect type (%d), tag = %s\n", conn_type, tag);
+ return -1;
+ }
+
+ ctx = &g_netlink_ctx[conn_type];
+ if (ctx->status != LINK_STATUS_INIT_DONE) {
+ pr_err("%s(): netlink should be init (type=%d).\n", __func__, conn_type);
+ return -2;
+ }
+
+ if (ctx->num_bind_process == 0) {
+ pr_err("No bind service\n");
+ return -3;
+ }
+
+ while (remain_len) {
+ send_len = (remain_len > CONNSYS_DUMP_PKT_SIZE? CONNSYS_DUMP_PKT_SIZE : remain_len);
+ ret = conndump_netlink_send_to_native_internal(ctx, tag, &buf[idx], send_len);
+ if (ret) {
+ pr_err("[%s] from %d with len=%d fail, ret=%d\n", __func__, idx, send_len, ret);
+ break;
+ }
+ remain_len -= send_len;
+ idx += send_len;
+ }
+ return idx;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/conndump_netlink.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/conndump_netlink.h
new file mode 100755
index 0000000..70f3517
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/conndump_netlink.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef _CONNDUMP_NETLINK_H_
+#define _CONNDUMP_NETLINK_H_
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+#include "coredump/connsys_coredump.h"
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+struct netlink_event_cb {
+ void (*coredump_end)(void*);
+};
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+int conndump_netlink_init(int conn_type, void* dump_ctx, struct netlink_event_cb* cb);
+int conndump_netlink_send_to_native(int conn_type, char* tag, char* buf, unsigned int length);
+
+
+#endif /*_CONNDUMP_NETLINK_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/connsys_coredump.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/connsys_coredump.c
new file mode 100755
index 0000000..98d36b4
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/connsys_coredump.c
@@ -0,0 +1,1707 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/ratelimit.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/timer.h>
+#if defined(CONNINFRA_PLAT_ALPS) && CONNINFRA_PLAT_ALPS
+#include <aee.h>
+#endif
+#include "conninfra.h"
+#include "connsys_debug_utility.h"
+#include "connsys_coredump.h"
+#include "connsys_coredump_emi.h"
+#include "connsys_coredump_hw_config.h"
+#include "conndump_netlink.h"
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+#define DEBUG_MODE 1
+
+#define CONNSYS_DUMP_INFO_SIZE 180
+#define CONNSYS_ASSERT_INFO_SIZE 164
+#define CONNSYS_ASSERT_TYPE_SIZE 64
+#define CONNSYS_ASSERT_KEYWORD_SIZE 64
+#define CONNSYS_ASSERT_REASON_SIZE 128
+#define CONNSYS_AEE_INFO_SIZE 240
+
+#define INFO_HEAD ";CONSYS FW CORE,"
+#define WDT_INFO_HEAD "Watch Dog Timeout"
+
+enum fw_coredump_status {
+ FW_DUMP_STATE_NOT_START = 0,
+ FW_DUMP_STATE_PUTTING = 1,
+ FW_DUMP_STATE_PUT_DONE = 2,
+ FW_DUMP_STATE_END,
+};
+
+enum core_dump_state {
+ CORE_DUMP_INIT = 0,
+ CORE_DUMP_START,
+ CORE_DUMP_DOING,
+ CORE_DUMP_TIMEOUT, /* Coredump timeout */
+ CORE_DUMP_EMI_TIMEOUT, /* EMI dump timeout */
+ CORE_DUMP_EMI, /* start for EMI dump */
+ CORE_DUMP_DONE,
+ CORE_DUMP_INVALID,
+ CORE_DUMP_MAX,
+};
+
+enum connsys_issue_type {
+ CONNSYS_ISSUE_FW_ASSERT = 0,
+ CONNSYS_ISSUE_FW_EXCEPTION,
+ CONNSYS_ISSUE_DRIVER_ASSERT,
+ CONNSYS_ISSUE_MAX,
+};
+
+struct connsys_dump_info {
+ enum connsys_issue_type issue_type;
+ char dump_info[CONNSYS_DUMP_INFO_SIZE];
+ char assert_info[CONNSYS_ASSERT_INFO_SIZE];
+ unsigned int fw_task_id;
+ unsigned int fw_isr;
+ unsigned int fw_irq;
+ unsigned int exp_ipc;
+ unsigned int exp_eva;
+ char etype[CONNSYS_ASSERT_INFO_SIZE];
+ char assert_type[CONNSYS_ASSERT_TYPE_SIZE];
+ char exception_log[CONNSYS_AEE_INFO_SIZE];
+ int drv_type;
+ char reason[CONNSYS_ASSERT_REASON_SIZE];
+ char keyword[CONNSYS_ASSERT_KEYWORD_SIZE];
+};
+
+struct connsys_dump_ctx {
+ int conn_type;
+ phys_addr_t emi_phy_addr_base;
+ void __iomem *emi_virt_addr_base;
+ unsigned int emi_size;
+ unsigned int mcif_emi_size;
+ struct coredump_event_cb callback;
+ struct timer_list dmp_timer;
+ struct completion emi_dump;
+ enum core_dump_state sm;
+ char* page_dump_buf;
+ struct dump_region* dump_regions;
+ int dump_regions_num;
+ unsigned int dynamic_map_cr;
+ struct coredump_hw_config hw_config;
+ struct connsys_dump_info info;
+ unsigned int full_emi_size;
+};
+
+#define DUMP_REGION_NAME_LENGTH 10
+/* TODO: Need check */
+#define DUMP_REGION_DEFAULT_NUM 50
+
+enum dump_region_type {
+ DUMP_TYPE_CR = 0,
+ DUMP_TYPE_ROM,
+ DUMP_TYPE_ILM,
+ DUMP_TYPE_DLM,
+ DUMP_TYPE_SRAM,
+ DUMP_TYPE_SYS1,
+ DUMP_TYPE_SYS2,
+ DUMP_TYPE_MAX,
+};
+
+struct dump_region {
+ int dump_type;
+ char name[DUMP_REGION_NAME_LENGTH];
+ unsigned int base;
+ unsigned int length;
+};
+
+static atomic_t g_dump_mode = ATOMIC_INIT(DUMP_MODE_DAEMON);
+
+static const char* g_type_name[] = {
+ "Wi-Fi",
+ "BT",
+};
+
+/*******************************************************************************
+* MACROS
+********************************************************************************
+*/
+
+#if DEBUG_MODE
+#if defined(CONFIG_FPGA_EARLY_PORTING)
+/* For FPGA shorten the timer */
+#define CONNSYS_COREDUMP_TIMEOUT (1*10*1000)
+#define CONNSYS_EMIDUMP_TIMEOUT (10*1000)
+#else
+#define CONNSYS_COREDUMP_TIMEOUT (1*10*1000)
+#define CONNSYS_EMIDUMP_TIMEOUT (60*1000)
+#endif
+#else
+#define CONNSYS_COREDUMP_TIMEOUT (10*1000)
+#define CONNSYS_EMIDUMP_TIMEOUT (60*1000)
+#endif
+
+#define CONNSYS_DUMP_BUFF_SIZE (32*1024*sizeof(char))
+
+#define EMI_READ32(addr) (readl(addr))
+#define EMI_READ8(addr) (readb(addr))
+#define DUMP_LOG_BYTES_PER_LINE (128)
+#define IS_VISIBLE_CHAR(c) ((c) >= 32 && (c) <= 126)
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+static void conndump_set_dump_state(struct connsys_dump_ctx* ctx, enum core_dump_state state);
+static enum core_dump_state conndump_get_dump_state(struct connsys_dump_ctx* ctx);
+static void conndump_timeout_handler(unsigned long data);
+static inline int conndump_get_dmp_info(struct connsys_dump_ctx* ctx, unsigned int offset, bool log);
+/* Dynamic remap relative function */
+static unsigned int conndump_setup_dynamic_remap(struct connsys_dump_ctx* ctx, unsigned int base, unsigned int length);
+static void __iomem* conndump_remap(struct connsys_dump_ctx* ctx, unsigned int base, unsigned int length);
+static void conndump_unmap(struct connsys_dump_ctx* ctx, void __iomem* vir_addr);
+/* To dump different partition */
+static void conndump_dump_log(char* buf, int size);
+static int conndump_dump_print_buff(struct connsys_dump_ctx* ctx);
+static int conndump_dump_dump_buff(struct connsys_dump_ctx* ctx);
+static int conndump_dump_cr_regions(struct connsys_dump_ctx* ctx);
+static int conndump_dump_mem_regions(struct connsys_dump_ctx* ctx);
+static int conndump_dump_emi(struct connsys_dump_ctx* ctx);
+static int conndump_send_fake_coredump(struct connsys_dump_ctx* ctx);
+/* Utility */
+static bool conndump_check_cr_readable(struct connsys_dump_ctx* ctx);
+static int conndump_info_format(
+ struct connsys_dump_ctx* ctx,
+ char* buf, unsigned int max_len,
+ bool full_dump);
+static void conndump_exception_show(struct connsys_dump_ctx* ctx, bool full_dump);
+/* memory allocate/free */
+static void* conndump_malloc(unsigned int size);
+static void conndump_free(const void* dst);
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+/* Platform relative function */
+/* ------------------------------------------------------------------------------*/
+struct coredump_hw_config* __weak get_coredump_platform_config(int conn_type)
+{
+ pr_err("[%s] Miss platform ops!\n", __func__);
+ return NULL;
+}
+
+unsigned int __weak get_coredump_platform_chipid(void)
+{
+ pr_err("[%s] Miss platform ops!\n", __func__);
+ return 0;
+}
+
+char* __weak get_task_string(int conn_type, int task_id)
+{
+ pr_err("[%s] Miss platform ops!\n", __func__);
+ return "ERROR";
+}
+
+char* __weak get_sys_name(int conn_type)
+{
+ pr_err("[%s] Miss platform ops!\n", __func__);
+ return "ERROR";
+}
+
+bool __weak is_host_view_cr(unsigned int addr, unsigned int* host_view)
+{
+ pr_err("[%s] Miss platform ops!\n", __func__);
+ return false;
+}
+
+/*----------------------------------------------------------------------------*/
+
+
+static unsigned long timeval_to_ms(struct timeval *begin, struct timeval *end)
+{
+ unsigned long time_diff;
+
+ time_diff = (end->tv_sec - begin->tv_sec) * 1000;
+ time_diff += (end->tv_usec - begin->tv_usec) / 1000;
+
+ return time_diff;
+}
+
+static void* conndump_malloc(unsigned int size)
+{
+ void* p = NULL;
+
+ if (size > (PAGE_SIZE << 1))
+ p = vmalloc(size);
+ else
+ p = kmalloc(size, GFP_KERNEL);
+
+ /* If there is fragment, kmalloc may not get memory when size > one page.
+ * For this case, use vmalloc instead.
+ */
+ if (p == NULL && size > PAGE_SIZE)
+ p = vmalloc(size);
+ return p;
+}
+
+static void conndump_free(const void* dst)
+{
+ kvfree(dst);
+}
+
+
+static bool conndump_check_cr_readable(struct connsys_dump_ctx* ctx)
+{
+ int cb_ret = 0;
+
+ /* Check reg readable */
+ if (ctx->callback.reg_readable) {
+ cb_ret = ctx->callback.reg_readable();
+ if (cb_ret == 1) {
+ return true;
+ }
+ pr_err("[%s] reg_readable callback ret = %d\n",
+ g_type_name[ctx->conn_type], cb_ret);
+ return false;
+ }
+
+ pr_err("[%s] reg_readable callback is not implement! Return false\n", g_type_name[ctx->conn_type]);
+ return false;
+}
+
+static void conndump_set_dump_state(
+ struct connsys_dump_ctx* ctx, enum core_dump_state state)
+{
+ if (ctx)
+ ctx->sm = state;
+}
+
+static enum core_dump_state conndump_get_dump_state(struct connsys_dump_ctx* ctx)
+{
+ if (ctx)
+ return ctx->sm;
+ pr_err("%s ctx is null\n", __func__);
+ return CORE_DUMP_INVALID;
+}
+
+static void conndump_timeout_handler(unsigned long data)
+{
+ struct connsys_dump_ctx* ctx = (struct connsys_dump_ctx*)data;
+
+ pr_info("[%s] coredump timeout\n", ctx->conn_type);
+ conndump_set_dump_state(ctx, CORE_DUMP_TIMEOUT);
+}
+
+static inline void conndump_get_dmp_char(struct connsys_dump_ctx* ctx, unsigned int offset, unsigned int byte_num, char* dest)
+{
+ int i;
+ char ret;
+
+ if (!dest)
+ return;
+
+ for (i = 0; i < byte_num; i++) {
+ ret = EMI_READ8(ctx->emi_virt_addr_base + offset + i);
+ dest[i] = ret;
+ }
+}
+
+static inline int conndump_get_dmp_info(struct connsys_dump_ctx* ctx, unsigned int offset, bool log)
+{
+ int ret;
+
+ ret = EMI_READ32(ctx->emi_virt_addr_base + offset);
+ if (log)
+ pr_info("EMI[0x%x] = 0x%08x\n", offset, ret);
+
+ return ret;
+}
+
+static void conndump_dump_log(char* buf, int size)
+{
+ int i = 0;
+ char line[DUMP_LOG_BYTES_PER_LINE + 1];
+
+ while (size--) {
+ if (IS_VISIBLE_CHAR(*buf))
+ line[i] = *buf;
+ else
+ line[i] = '.';
+ i++;
+ buf++;
+
+ if (i >= DUMP_LOG_BYTES_PER_LINE || !size) {
+ line[i] = 0;
+ pr_info("page_trace: %s\n", line);
+ i = 0;
+ }
+ }
+}
+
+static int conndump_info_format(
+ struct connsys_dump_ctx* ctx,
+ char* buf,
+ unsigned int max_len,
+ bool full_dump)
+{
+#define FORMAT_STRING(buf, len, max_len, sec_len, fmt, arg...) \
+do { \
+ sec_len = snprintf(buf + len, max_len, fmt, ##arg); \
+ max_len -= sec_len; \
+ len += sec_len; \
+ if (max_len <= 0) \
+ goto format_finish; \
+} while (0)
+
+ int len = 0;
+ int ret;
+ int idx;
+ int sec_len;
+ char* drv_name[CONNDRV_TYPE_MAX] = {
+ "DRV_BT",
+ "DRV_FM",
+ "DRV_GPS",
+ "DRV_WIFI",
+ "DRV_CONNINFRA",
+ };
+ /* Align with connac1.x and previous version */
+ char* task_drv_name[CONNDRV_TYPE_MAX] = {
+ "Task_DrvBT",
+ "Task_DrvFM",
+ "Task_DrvGPS",
+ "Task_DrvWifi",
+ "Task_DrvConninfra",
+ };
+ char* task_drv_name2[CONN_DEBUG_TYPE_END] = {
+ "Task_DrvWifi",
+ "Task_DrvBT",
+ };
+
+ if (!buf) {
+ pr_err("Invalid input, buf = %p", buf);
+ return 0;
+ }
+
+ /* Init buffer */
+ memset(buf, '\0', max_len);
+ FORMAT_STRING(buf, len, max_len, sec_len, "<main>\n");
+ FORMAT_STRING(buf, len, max_len, sec_len, "\t<chipid>MT%x</chipid>\n", get_coredump_platform_chipid());
+
+ /* <issue> section */
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t<issue>\n\t\t<classification>\n\t\t\t%s\n\t\t</classification>\n",
+ ctx->info.assert_info);
+ if (ctx->info.issue_type == CONNSYS_ISSUE_FW_EXCEPTION) {
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t<rc>\n\t\t\tFW Exception: %s\n\t\t</rc>\n", ctx->info.etype);
+ } else if (ctx->info.issue_type == CONNSYS_ISSUE_FW_ASSERT) {
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t<rc>\n\t\t\t%s\n\t\t</rc>\n", ctx->info.assert_type);
+ } else if (ctx->info.issue_type == CONNSYS_ISSUE_DRIVER_ASSERT) {
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t<rc>\n\t\t\t%s trigger assert\n\t\t</rc>\n", drv_name[ctx->info.drv_type]);
+ } else {
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t<rc>\n\t\t\tUnknown\n\t\t</rc>\n");
+ }
+ /* <hint><client> section @{*/
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t</issue>\n\t<hint>\n\t\t<client>\n");
+
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t\t<subsys>%s</subsys>\n", ctx->hw_config.name);
+ if (ctx->info.issue_type == CONNSYS_ISSUE_DRIVER_ASSERT) {
+ /* Driver trigger assert */
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t\t<task>%s</task>\n",
+ task_drv_name[ctx->info.drv_type]);
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t\t<irqx>NULL</irqx>\n");
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t\t<isr>NULL</isr>\n");
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t\t<drv_type>%s</drv_type>\n",
+ drv_name[ctx->info.drv_type]);
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t\t<reason>%s</reason>\n",
+ ctx->info.reason);
+ } else {
+ /* FW assert */
+ if (full_dump) {
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t\t<task>%s</task>\n",
+ get_task_string(ctx->conn_type, ctx->info.fw_task_id));
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t\t<irqx>IRQ_0x%x_%s</irqx>\n",
+ ctx->info.fw_irq,
+ get_sys_name(ctx->conn_type));
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t\t<isr>0x%x</isr>\n",
+ ctx->info.fw_isr);
+ } else {
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t\t<task>%s</task>\n",
+ task_drv_name2[ctx->conn_type]);
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t\t<irqx>NULL</irqx>\n");
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t\t<isr>NULL</isr>\n");
+ }
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t\t<drv_type>%s</drv_type>\n",
+ "NULL");
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t\t<reason>%s</reason>\n",
+ "NULL");
+ }
+ if (strlen(ctx->info.keyword) != 0) {
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t\t<keyword>%s</keyword>\n",
+ ctx->info.keyword);
+ } else {
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t\t<keyword>NULL</keyword>\n");
+
+ }
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t</client>\n\t</hint>\n");
+ /*<hint><client> section @}*/
+ /* <map> section start @{ */
+ FORMAT_STRING(buf, len, max_len, sec_len, "\t<map>\n");
+ for (idx = 0; idx < ctx->dump_regions_num; idx++) {
+ /* Non-empty name means memory regions */
+ if (ctx->dump_regions[idx].name[0] != 0) {
+ FORMAT_STRING(buf, len, max_len, sec_len,
+ "\t\t<%s>\n\t\t\t<offset>0x%x</offset>\n\t\t\t<size>0x%x</size>\n\t\t</%s>\n",
+ ctx->dump_regions[idx].name,
+ ctx->dump_regions[idx].base,
+ ctx->dump_regions[idx].length,
+ ctx->dump_regions[idx].name);
+ }
+ }
+ FORMAT_STRING(buf, len, max_len, sec_len, "\t</map>\n");
+ /* <map> section end @} */
+ FORMAT_STRING(buf, len, max_len, sec_len, "</main>\n");
+
+format_finish:
+ pr_info("== Issue info ==\n", buf);
+ pr_info("%s\n", buf);
+ pr_info("===== END =====\n");
+ ret = conndump_netlink_send_to_native(ctx->conn_type, "INFO", buf, len);
+ if (ret < 0)
+ pr_err("Send issue info to native fail, ret=%d\n", ret);
+ return len;
+}
+
+static void conndump_info_analysis(
+ struct connsys_dump_ctx* ctx,
+ unsigned int buf_len)
+{
+ const char* parser_sub_string[] = {
+ "<ASSERT> ",
+ "id=",
+ "isr=",
+ "irq=",
+ "rc=",
+ };
+ const char* exception_sub_string[] = {
+ "<EXCEPTION> ",
+ "ipc=",
+ "eva=",
+ "etype:",
+ };
+ char* pStr = ctx->page_dump_buf;
+ char* pDtr = NULL;
+ char* pTemp = NULL;
+ char* pTemp2 = NULL;
+ unsigned int len;
+ int remain_array_len = 0, sec_len = 0, idx = 0;
+ char tempBuf[CONNSYS_ASSERT_TYPE_SIZE] = { 0 };
+ int ret, res;
+ char* type_str;
+
+ /* Check <ASSERT> */
+ memset(&ctx->info.assert_info[0], '\0', CONNSYS_ASSERT_INFO_SIZE);
+ type_str = (char*)parser_sub_string[0];
+ pDtr = strstr(pStr, type_str);
+ if (pDtr != NULL) {
+ if (ctx->info.issue_type != CONNSYS_ISSUE_DRIVER_ASSERT)
+ ctx->info.issue_type = CONNSYS_ISSUE_FW_ASSERT;
+ pDtr += strlen(type_str);
+ pTemp = strchr(pDtr, ' ');
+
+ if (pTemp != NULL) {
+ idx = 0;
+ remain_array_len = CONNSYS_ASSERT_INFO_SIZE -1;
+ sec_len = strlen("assert@");
+ memcpy(&ctx->info.assert_info[0], "assert@", sec_len);
+ idx += sec_len;
+ remain_array_len -= sec_len;
+
+ len = pTemp - pDtr;
+ sec_len = (len < remain_array_len ? len : remain_array_len);
+ if (sec_len > remain_array_len)
+ goto check_task_id;
+ memcpy(&ctx->info.assert_info[idx], pDtr, sec_len);
+ remain_array_len -= sec_len;
+ idx += sec_len;
+
+ sec_len = strlen("_");
+ if (sec_len > remain_array_len)
+ goto check_task_id;
+ ctx->info.assert_info[idx] = '_';
+ remain_array_len -= sec_len;
+ idx += sec_len;
+
+ pTemp = strchr(pDtr, '#');
+ if (pTemp != NULL) {
+ pTemp += 1;
+ pTemp2 = strchr(pTemp, ' ');
+ if (pTemp2 == NULL) {
+ pr_err("parser ' ' is not find\n");
+ pTemp2 = pTemp + 1;
+ }
+ pr_info("(pTemp2 - pTemp)=%d\n", (pTemp2 - pTemp));
+ if ((remain_array_len) > (pTemp2 - pTemp)) {
+ pr_info("Copy %d\n", pTemp2 - pTemp);
+ memcpy(
+ &ctx->info.assert_info[idx],
+ pTemp,
+ pTemp2 - pTemp);
+ } else {
+ pr_info("copy %d\n", (remain_array_len - 1));
+ memcpy(
+ &ctx->info.assert_info[idx],
+ pTemp,
+ remain_array_len);
+ }
+ }
+ pr_info("assert info:%s\n", ctx->info.assert_info);
+ }
+ } else {
+ /* FW exception */
+ type_str = (char*)exception_sub_string[0];
+ pDtr = strstr(pStr, type_str);
+ if (pDtr == NULL)
+ goto check_task_id;
+
+ if (ctx->info.issue_type != CONNSYS_ISSUE_DRIVER_ASSERT)
+ ctx->info.issue_type = CONNSYS_ISSUE_FW_EXCEPTION;
+ idx = 0;
+ remain_array_len = CONNSYS_ASSERT_INFO_SIZE;
+ sec_len = snprintf(&ctx->info.assert_info[idx], remain_array_len,
+ "%s", "Exception:");
+ remain_array_len -= sec_len;
+ idx += sec_len;
+
+ /* Check ipc */
+ type_str = (char*)exception_sub_string[1];
+ pDtr = strstr(pDtr, type_str);
+ if (pDtr == NULL) {
+ pr_err("Exception substring (%s) not found\n", type_str);
+ goto check_task_id;
+ }
+ pDtr += strlen(type_str);
+ pTemp = strchr(pDtr, ',');
+ if (pTemp != NULL) {
+ len = pTemp - pDtr;
+ len = (len >= CONNSYS_ASSERT_TYPE_SIZE) ? CONNSYS_ASSERT_TYPE_SIZE - 1 : len;
+ memcpy(&tempBuf[0], pDtr, len);
+ tempBuf[len] = '\0';
+ ret = kstrtouint(tempBuf, 16, &res);
+ if (ret) {
+ pr_err("Convert to uint fail, ret=%d, buf=%s\n",
+ ret, tempBuf);
+ } else {
+ ctx->info.exp_ipc = res;
+ pr_info("exp_ipc=0x%x\n", ctx->info.exp_ipc);
+ }
+ if (remain_array_len > 0) {
+ sec_len = snprintf(&ctx->info.assert_info[idx], remain_array_len,
+ " ipc=0x%x", ctx->info.exp_ipc);
+ remain_array_len -= sec_len;
+ idx += sec_len;
+ }
+ }
+
+ /* Check eva */
+ type_str = (char*)exception_sub_string[2];
+ pDtr = strstr(pDtr, type_str);
+ if (pDtr == NULL) {
+ pr_err("substring (%s) not found\n", type_str);
+ goto check_task_id;
+ }
+ pDtr += strlen(type_str);
+ pTemp = strchr(pDtr, ',');
+ if (pTemp != NULL) {
+ len = pTemp - pDtr;
+ len = (len >= CONNSYS_ASSERT_TYPE_SIZE) ? CONNSYS_ASSERT_TYPE_SIZE - 1 : len;
+ memcpy(&tempBuf[0], pDtr, len);
+ tempBuf[len] = '\0';
+ ret = kstrtouint(tempBuf, 16, &res);
+ if (ret) {
+ pr_err("Convert to uint fail, ret=%d, buf=%s\n",
+ ret, tempBuf);
+ } else {
+ ctx->info.exp_eva = res;
+ pr_info("eva addr=0x%x\n", ctx->info.exp_eva);
+ }
+ if (remain_array_len > 0) {
+ sec_len = snprintf(
+ &ctx->info.assert_info[idx], remain_array_len,
+ " eva=0x%x", ctx->info.exp_eva);
+ remain_array_len -= sec_len;
+ idx += sec_len;
+ }
+ }
+
+ /* Check etype */
+ type_str = (char*)exception_sub_string[3];
+ pDtr = strstr(pDtr, type_str);
+ if (pDtr == NULL) {
+ pr_err("Substring(%s) not found\n", type_str);
+ goto check_task_id;
+ }
+ pDtr += strlen(type_str);
+ pTemp = strchr(pDtr, ',');
+ if (pTemp != NULL) {
+ len = pTemp - pDtr;
+ len = (len >= CONNSYS_ASSERT_TYPE_SIZE) ? CONNSYS_ASSERT_TYPE_SIZE - 1 : len;
+ memcpy(ctx->info.etype, pDtr, len);
+ ctx->info.etype[len] = '\0';
+ pr_info("etype=%s\n", ctx->info.etype);
+ if (remain_array_len > 0) {
+ sec_len = snprintf(
+ &ctx->info.assert_info[idx], remain_array_len,
+ " etype=%s", ctx->info.etype);
+ remain_array_len -= sec_len;
+ idx += sec_len;
+ }
+ }
+ }
+
+check_task_id:
+ /* Check id */
+ ctx->info.fw_task_id = 0;
+ type_str = (char*)parser_sub_string[1];
+ pDtr = strstr(pStr, type_str);
+ if (pDtr == NULL) {
+ pr_err("parser str is NULL,substring(%s)\n", type_str);
+
+ } else {
+ pDtr += strlen(type_str);
+ pTemp = strchr(pDtr, ' ');
+
+ if (pTemp == NULL) {
+ pr_err("delimiter( ) is not found,substring(%s)\n",
+ type_str);
+ } else {
+ len = pTemp - pDtr;
+ len = (len >= CONNSYS_ASSERT_TYPE_SIZE) ? CONNSYS_ASSERT_TYPE_SIZE - 1 : len;
+ memcpy(&tempBuf[0], pDtr, len);
+ tempBuf[len] = '\0';
+ ret = kstrtouint(tempBuf, 16, &res);
+ if (ret) {
+ pr_err("Convert to uint fail, ret=%d\n, buf=%s\n",
+ ret, tempBuf);
+ } else {
+ ctx->info.fw_task_id = res;
+ pr_info("fw task id: %x\n", ctx->info.fw_task_id);
+ }
+ }
+ }
+
+ /* Check ISR */
+ ctx->info.fw_isr = 0;
+ type_str = (char*)parser_sub_string[2];
+ pDtr = strstr(pStr, type_str);
+ if (pDtr == NULL) {
+ pr_err("parser str is NULL,substring(%s)\n", type_str);
+ } else {
+ pDtr += strlen(type_str);
+ pTemp = strchr(pDtr, ',');
+
+ if (pTemp == NULL) {
+ pr_err("delimiter(,) is not found,substring(%s)\n", type_str);
+ } else {
+ len = pTemp - pDtr;
+ len = (len >= CONNSYS_ASSERT_TYPE_SIZE) ? CONNSYS_ASSERT_TYPE_SIZE - 1 : len;
+ memcpy(&tempBuf[0], pDtr, len);
+ tempBuf[len] = '\0';
+
+ ret = kstrtouint(tempBuf, 16, &res);
+ if (ret) {
+ pr_err("Get fw isr id fail, ret=%d, buf=%s\n", ret, tempBuf);
+ } else {
+ ctx->info.fw_isr = res;
+ pr_info("fw isr str:%x\n", ctx->info.fw_isr);
+ }
+ }
+ }
+
+ /* Check IRQ */
+ ctx->info.fw_irq = 0;
+ type_str = (char*)parser_sub_string[3];
+ pDtr = strstr(pStr, type_str);
+ if (pDtr == NULL) {
+ pr_err("parser str is NULL,substring(%s)\n", type_str);
+ } else {
+ pDtr += strlen(type_str);
+ pTemp = strchr(pDtr, ',');
+ if (pTemp == NULL) {
+ pr_err("delimiter(,) is not found,substring(%s)\n", type_str);
+ } else {
+ len = pTemp - pDtr;
+ len = (len >= CONNSYS_ASSERT_TYPE_SIZE) ? CONNSYS_ASSERT_TYPE_SIZE - 1 : len;
+ memcpy(&tempBuf[0], pDtr, len);
+ tempBuf[len] = '\0';
+ ret = kstrtouint(tempBuf, 16, &res);
+ if (ret) {
+ pr_err("get fw irq id fail ret=%d, buf=%s\n", ret, tempBuf);
+ } else {
+ ctx->info.fw_irq = res;
+ pr_info("fw irq value:%x\n", ctx->info.fw_irq);
+ }
+ }
+ }
+
+ /* Check assert type */
+ memset(&ctx->info.assert_type[0], '\0', CONNSYS_ASSERT_TYPE_SIZE);
+ type_str = (char*)parser_sub_string[4];
+ pDtr = strstr(pStr, type_str);
+ if (pDtr == NULL) {
+ pr_err("parser str is NULL,substring(%s)\n", type_str);
+ } else {
+ pDtr += strlen(type_str);
+ pTemp = strchr(pDtr, ',');
+
+ if (pTemp == NULL) {
+ pr_err("delimiter(,) is not found,substring(%s)\n", type_str);
+ } else {
+ len = pTemp - pDtr;
+ len = (len >= CONNSYS_ASSERT_TYPE_SIZE) ? CONNSYS_ASSERT_TYPE_SIZE - 1 : len;
+ memcpy(&tempBuf[0], pDtr, len);
+ tempBuf[len] = '\0';
+
+ if (memcmp(tempBuf, "*", strlen("*")) == 0)
+ memcpy(
+ &ctx->info.assert_type[0],
+ "general assert",
+ strlen("general assert"));
+ if (memcmp(tempBuf, WDT_INFO_HEAD, strlen(WDT_INFO_HEAD)) == 0)
+ memcpy(
+ &ctx->info.assert_type[0], "wdt", strlen("wdt"));
+ if (memcmp(tempBuf, "RB_FULL", strlen("RB_FULL")) == 0) {
+ memcpy(&ctx->info.assert_type[0], tempBuf, len);
+ pDtr = strstr(&ctx->info.assert_type[0], "RB_FULL(");
+ if (pDtr == NULL) {
+ pr_err("parser str is NULL,substring(RB_FULL()\n");
+ } else {
+ pDtr += strlen("RB_FULL(");
+ pTemp = strchr(pDtr, ')');
+ len = pTemp - pDtr;
+ len = (len >= CONNSYS_ASSERT_TYPE_SIZE) ? CONNSYS_ASSERT_TYPE_SIZE - 1 : len;
+ memcpy(&tempBuf[0], pDtr, len);
+ tempBuf[len] = '\0';
+ ret = kstrtouint(tempBuf, 16, &res);
+ if (ret) {
+ pr_err("get fw task id fail(%d)\n", ret);
+ } else {
+ snprintf(
+ ctx->info.keyword,
+ CONNSYS_ASSERT_KEYWORD_SIZE,
+ "RB_FULL_%d_%s", res,
+ ctx->hw_config.name);
+ }
+ }
+ }
+ }
+ pr_info("fw asert type:%s\n", ctx->info.assert_type);
+ }
+
+ /* Store first several characters */
+ len = strlen(ctx->page_dump_buf);
+ len = (len >= CONNSYS_DUMP_INFO_SIZE) ? CONNSYS_DUMP_INFO_SIZE - 1 : len;
+ strncpy(ctx->info.dump_info, ctx->page_dump_buf, CONNSYS_DUMP_INFO_SIZE);
+ ctx->info.dump_info[len] = '\0';
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * conndump_dump_print_buff
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+static int conndump_dump_print_buff(struct connsys_dump_ctx* ctx)
+{
+ int ret = 0;
+ unsigned int buff_start, buff_len;
+ int section_len;
+
+ buff_start = CONNSYS_DUMP_PRINT_BUFF_OFFSET;
+ buff_len = conndump_get_dmp_info(ctx, CONNSYS_DUMP_CTRL_BLOCK_OFFSET + EXP_CTRL_PRINT_BUFF_IDX, true);
+
+ if (buff_len > CONNSYS_DUMP_PRINT_BUFF_SIZE) {
+ pr_err("Get print buff idx = %d, but the length is %d\n", buff_len, CONNSYS_DUMP_PRINT_BUFF_SIZE);
+ buff_len = CONNSYS_DUMP_PRINT_BUFF_SIZE;
+ }
+
+ pr_info("-- paged trace ascii output start --\n");
+ while (buff_len > 0) {
+ memset(ctx->page_dump_buf, '\0', CONNSYS_DUMP_BUFF_SIZE);
+ section_len = (buff_len > (CONNSYS_DUMP_BUFF_SIZE - 1)) ? (CONNSYS_DUMP_BUFF_SIZE - 1) : buff_len;
+ memcpy_fromio(ctx->page_dump_buf, ctx->emi_virt_addr_base + buff_start, section_len);
+
+ pr_info("-- paged trace ascii output --\n");
+ conndump_dump_log(ctx->page_dump_buf, section_len);
+
+ buff_len -= section_len;
+ buff_start += section_len;
+ }
+ pr_info("-- paged trace ascii output end --\n");
+ return ret;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * conndump_dump_dump_buff
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+static int conndump_dump_dump_buff(struct connsys_dump_ctx* ctx)
+{
+ int ret = 0;
+ unsigned int buff_start, buff_len;
+ int section_len;
+ bool first = true;
+
+ buff_start = CONNSYS_DUMP_DUMP_BUFF_OFFSET;
+ buff_len = conndump_get_dmp_info(ctx, CONNSYS_DUMP_CTRL_BLOCK_OFFSET + EXP_CTRL_DUMP_BUFF_IDX, true);
+
+ if (buff_len > CONNSYS_DUMP_DUMP_BUFF_SIZE) {
+ pr_err("Get dump buff idx = %d, but the size is %d\n", buff_len, CONNSYS_DUMP_DUMP_BUFF_SIZE);
+ buff_len = CONNSYS_DUMP_DUMP_BUFF_SIZE;
+ }
+
+ if (buff_len == 0) {
+ ret = conndump_send_fake_coredump(ctx);
+ return ret;
+ }
+
+ while (buff_len > 0) {
+ memset(ctx->page_dump_buf, '\0', CONNSYS_DUMP_BUFF_SIZE);
+ section_len = (buff_len > (CONNSYS_DUMP_BUFF_SIZE - 1)) ? (CONNSYS_DUMP_BUFF_SIZE - 1): buff_len;
+ memcpy_fromio(ctx->page_dump_buf, ctx->emi_virt_addr_base + buff_start, section_len);
+
+ /* pack it */
+ ret = conndump_netlink_send_to_native(ctx->conn_type, "[M]", ctx->page_dump_buf, section_len);
+ /* For 1st package, analysis it */
+ if (first) {
+ conndump_info_analysis(ctx, section_len);
+ first = false;
+ }
+
+ buff_len -= section_len;
+ buff_start += section_len;
+ }
+ return ret;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * conndump_setup_dynamic_remap
+ * DESCRIPTION
+ * Setup dynamic remap region
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+static unsigned int conndump_setup_dynamic_remap(struct connsys_dump_ctx* ctx, unsigned int base, unsigned int length)
+{
+
+#define DYNAMIC_MAP_MAX_SIZE 0x300000
+ unsigned int map_len = (length > DYNAMIC_MAP_MAX_SIZE? DYNAMIC_MAP_MAX_SIZE : length);
+ void __iomem* vir_addr = 0;
+
+ if (is_host_view_cr(base, NULL)) {
+ pr_info("Host view CR: 0x%x, skip dynamic remap\n", base);
+ return length;
+ }
+
+ /* Expand to request size */
+ vir_addr = ioremap_nocache(ctx->hw_config.seg1_cr, 4);
+ if (vir_addr) {
+ iowrite32(ctx->hw_config.seg1_phy_addr + map_len, vir_addr);
+ iounmap(vir_addr);
+ } else {
+ return 0;
+ }
+ /* Setup map base */
+ vir_addr = ioremap_nocache(ctx->hw_config.seg1_start_addr, 4);
+ if (vir_addr) {
+ iowrite32(base, vir_addr);
+ iounmap(vir_addr);
+ } else {
+ return 0;
+ }
+ return map_len;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * conndump_remap
+ * DESCRIPTION
+ * Map dynamic remap CR region to virtual address
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+static void __iomem* conndump_remap(struct connsys_dump_ctx* ctx, unsigned int base, unsigned int length)
+{
+ void __iomem* vir_addr = 0;
+ unsigned int host_cr;
+
+ if (is_host_view_cr(base, &host_cr)) {
+ pr_info("Map 0x%x to 0x%x\n", base, host_cr);
+ vir_addr = ioremap_nocache(host_cr, length);
+ } else {
+ vir_addr = ioremap_nocache(ctx->hw_config.seg1_phy_addr, length);
+ }
+ return vir_addr;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * conndump_unmap
+ * DESCRIPTION
+ * Unmap virtual address
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+static void conndump_unmap(struct connsys_dump_ctx* ctx, void __iomem* vir_addr)
+{
+ iounmap(vir_addr);
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ * conndump_dump_cr_regions
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+static int conndump_dump_cr_regions(struct connsys_dump_ctx* ctx)
+{
+#define CR_PER_LINE 11
+ int ret = 0;
+ int idx;
+ unsigned int map_length;
+ void __iomem *map_base;
+ unsigned int buff_size = CONNSYS_DUMP_BUFF_SIZE;
+ /* format is [addr,valu] */
+ char per_cr[CR_PER_LINE];
+ int i;
+ int addr, value;
+ unsigned int buff_idx = 0;
+
+ if (!conndump_check_cr_readable(ctx)) {
+ pr_err("CR not readable, skip cr dump\n");
+ return -1;
+ }
+
+ for (idx = 0; idx < ctx->dump_regions_num; idx++) {
+ /* empty name means cr regions */
+ if (ctx->dump_regions[idx].name[0] == 0 &&
+ (ctx->dump_regions[idx].base > 0) &&
+ (ctx->dump_regions[idx].base & 0x3) == 0 &&
+ (ctx->dump_regions[idx].length & 0x3) == 0) {
+ pr_info("[%s][Region %d] base=0x%x size=0x%x\n", __func__, idx, ctx->dump_regions[idx].base, ctx->dump_regions[idx].length);
+ map_length = conndump_setup_dynamic_remap(
+ ctx, ctx->dump_regions[idx].base, ctx->dump_regions[idx].length);
+ /* For CR region, we assume region size should < dynamic remap region. */
+ if (map_length != ctx->dump_regions[idx].length) {
+ pr_err("Expect_size=0x%x map_length=0x%x\n", ctx->dump_regions[idx].length, map_length);
+ } else {
+ map_base = conndump_remap(ctx, ctx->dump_regions[idx].base, map_length);
+ if (!map_base) {
+ pr_err("[%s][Region %d] remap fail, break\n", __func__, idx);
+ break;
+ }
+ for (i = 0, addr = ctx->dump_regions[idx].base; i < map_length; i+=4, addr+=4) {
+ value = (*((volatile unsigned int *)(map_base + i)));
+ per_cr[0] = '[';
+ memcpy(&per_cr[1], &addr, 4);
+ per_cr[5] = ',';
+ memcpy(&per_cr[6], &value, 4);
+ per_cr[10] = ']';
+ if (buff_size < CR_PER_LINE) {
+ pr_info("[%s] Dump buffer full (%d-th cr), flush to native space.\n", __func__, i);
+ /* pack it! */
+ conndump_netlink_send_to_native(ctx->conn_type, "[M]", ctx->page_dump_buf, buff_idx);
+
+ /* start from buffer start */
+ buff_size = CONNSYS_DUMP_BUFF_SIZE;
+ buff_idx = 0;
+ memset(ctx->page_dump_buf, 0, CONNSYS_DUMP_BUFF_SIZE);
+ }
+ memcpy(&ctx->page_dump_buf[buff_idx], per_cr, CR_PER_LINE);
+ buff_size -= CR_PER_LINE;
+ buff_idx += CR_PER_LINE;
+ }
+ conndump_unmap(ctx, map_base);
+ }
+ }
+ }
+
+ /* pack remaining item */
+ if (buff_idx) {
+ pr_info("[%s] send remain %d bytes\n", __func__, buff_idx);
+ conndump_netlink_send_to_native(ctx->conn_type, "[M]", ctx->page_dump_buf, buff_idx);
+ }
+
+ return ret;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * conndump_nfra_get_phy_addr(&emi_addr, &emi_size);
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+static int conndump_dump_mem_regions(struct connsys_dump_ctx* ctx)
+{
+#define MEM_REGION_TAG_LENGTH 32
+#define MEM_REGION_MAX_COPY_LENGTH (CONNSYS_DUMP_BUFF_SIZE - MEM_REGION_TAG_LENGTH)
+ int ret = 0;
+ int idx;
+ unsigned int map_length;
+ void __iomem *map_base;
+ unsigned int* dump_buff = NULL;
+ unsigned int copy_idx;
+
+ pr_info("[%s] dump_regions_num=%d\n", __func__, ctx->dump_regions_num);
+ /* Check reg readable */
+ if (!conndump_check_cr_readable(ctx)) {
+ pr_err("CR not readable, skip memory region dump\n");
+ return -1;
+ }
+ for (idx = 0; idx < ctx->dump_regions_num; idx++) {
+ /* Non-empty name means memory regions */
+ if (ctx->dump_regions[idx].name[0] != 0 &&
+ (ctx->dump_regions[idx].length > 0) &&
+ (ctx->dump_regions[idx].length & 0x3) == 0 &&
+ (ctx->dump_regions[idx].base & 0x3) == 0) {
+ pr_info("[%s][Region %d][%s] base=0x%x size=0x%x\n",
+ __func__, idx, ctx->dump_regions[idx].name,
+ ctx->dump_regions[idx].base, ctx->dump_regions[idx].length);
+ /* variable init */
+ ret = 0;
+ dump_buff = (unsigned int*)conndump_malloc(ctx->dump_regions[idx].length);
+ if (!dump_buff) {
+ pr_err("Allocate buffer for %s fail.\n",
+ ctx->dump_regions[idx].name);
+ goto next_mem_region;
+ }
+ /* Change dynamic window */
+ map_length = conndump_setup_dynamic_remap(
+ ctx, ctx->dump_regions[idx].base, ctx->dump_regions[idx].length);
+ if (map_length != ctx->dump_regions[idx].length) {
+ pr_err("Setup dynamic remap for %s fail. Expect 0x%x but 0x%x",
+ ctx->dump_regions[idx].name,
+ ctx->dump_regions[idx].length,
+ map_length);
+ goto next_mem_region;
+ }
+ map_base = conndump_remap(ctx, ctx->dump_regions[idx].base, map_length);
+ if (!map_base) {
+ pr_err("Remap %s fail.\n", ctx->dump_regions[idx].name);
+ goto next_mem_region;
+ }
+ for (copy_idx = 0; copy_idx < map_length; copy_idx += 4) {
+ dump_buff[(copy_idx >> 2)] = (*((volatile unsigned int *)(map_base + copy_idx)));
+ }
+ conndump_unmap(ctx, map_base);
+ ret = conndump_netlink_send_to_native(
+ ctx->conn_type,
+ ctx->dump_regions[idx].name,
+ (char*)dump_buff,
+ ctx->dump_regions[idx].length);
+ if (ret != ctx->dump_regions[idx].length) {
+ pr_err("[%s][%s] Send fail, length = 0x%x but only 0x%x send\n",
+ __func__, ctx->dump_regions[idx].name,
+ ctx->dump_regions[idx].length, ret);
+ }
+ }
+next_mem_region:
+ if (dump_buff) {
+ conndump_free((void*)dump_buff);
+ dump_buff = NULL;
+ }
+ }
+ return ret;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * conndump_dump_emi
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+static int conndump_dump_emi(struct connsys_dump_ctx* ctx)
+{
+#define EMI_COMMAND_LENGTH 64
+ int ret;
+ unsigned long comp_ret;
+ // format: emi_size=aaaaaaaa, mcif_emi_size=bbbbbbbb
+ char emi_dump_command[EMI_COMMAND_LENGTH];
+
+ snprintf(emi_dump_command, EMI_COMMAND_LENGTH, "emi_size=%d,mcif_emi_size=%d", ctx->full_emi_size, ctx->mcif_emi_size);
+ pr_info("[%s] dump command: %s\n", __func__, emi_dump_command);
+ conndump_set_dump_state(ctx, CORE_DUMP_EMI);
+ ret = conndump_netlink_send_to_native(ctx->conn_type, "[EMI]", emi_dump_command, strlen(emi_dump_command));
+
+ if (ret < 0) {
+ pr_err("Start EMI dump fail, ret = %d\n", ret);
+ return -1;
+ }
+
+ comp_ret = wait_for_completion_timeout(
+ &ctx->emi_dump,
+ msecs_to_jiffies(CONNSYS_EMIDUMP_TIMEOUT));
+
+ if (comp_ret == 0) {
+ pr_err("EMI dump timeout\n");
+ conndump_set_dump_state(ctx, CORE_DUMP_EMI_TIMEOUT);
+ } else {
+ pr_info("EMI dump end");
+ conndump_set_dump_state(ctx, CORE_DUMP_DONE);
+ }
+
+ return 0;
+}
+
+static int connsys_coredump_init_dump_regions(struct connsys_dump_ctx* ctx, int num)
+{
+ int size = sizeof(struct dump_region)*num;
+
+ ctx->dump_regions = (struct dump_region*)conndump_malloc(size);
+ if (!ctx->dump_regions) {
+ ctx->dump_regions_num = 0;
+ pr_err("ctx->dump_regions create fail!\n");
+ return 0;
+ }
+ memset(ctx->dump_regions, 0, size);
+ ctx->dump_regions_num = num;
+ return num;
+}
+
+static void connsys_coredump_deinit_dump_regions(struct connsys_dump_ctx* ctx)
+{
+ conndump_free(ctx->dump_regions);
+ ctx->dump_regions = 0;
+ ctx->dump_regions_num = 0;
+}
+
+static void conndump_coredump_end(void* handler)
+{
+ struct connsys_dump_ctx* ctx = (struct connsys_dump_ctx*)handler;
+
+ if (conndump_get_dump_state(ctx) == CORE_DUMP_EMI) {
+ pr_info("Wake up emi_dump\n");
+ complete(&ctx->emi_dump);
+ }
+}
+
+static int conndump_send_fake_coredump(struct connsys_dump_ctx* ctx)
+{
+ pr_info("Send fake coredump\n");
+ return conndump_netlink_send_to_native(ctx->conn_type, "[M]", "FORCE_COREDUMP", 13);
+}
+
+static void conndump_exception_show(struct connsys_dump_ctx* ctx, bool full_dump)
+{
+ if (full_dump) {
+ snprintf(
+ ctx->info.exception_log, CONNSYS_AEE_INFO_SIZE,
+ "%s %s %s %s",
+ INFO_HEAD, ctx->hw_config.name,
+ ctx->info.assert_type, ctx->info.dump_info);
+ } else {
+ snprintf(
+ ctx->info.exception_log, CONNSYS_AEE_INFO_SIZE,
+ "%s %s",
+ INFO_HEAD, ctx->hw_config.name);
+ }
+
+#if defined(CONNINFRA_PLAT_ALPS) && CONNINFRA_PLAT_ALPS
+ pr_info("par1: [%s] pars: [%s] par3: [%d]\n",
+ ctx->hw_config.exception_tag_name,
+ ctx->info.exception_log,
+ strlen(ctx->info.exception_log));
+ /* Call AEE API */
+ aed_common_exception_api(
+ ctx->hw_config.exception_tag_name,
+ NULL, 0,
+ (const int*)ctx->info.exception_log, strlen(ctx->info.exception_log),
+ ctx->info.exception_log, 0);
+#endif
+}
+
+/*****************************************************************************
+ * FUNCTION
+ * connsys_coredump_clean
+ * DESCRIPTION
+ * To clean coredump EMI region
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+void connsys_coredump_clean(void* handler)
+{
+ struct connsys_dump_ctx* ctx = (struct connsys_dump_ctx*)handler;
+
+ if (ctx == NULL)
+ return;
+
+ pr_info("[%s] Clear %p size=%d as zero\n", __func__, ctx->emi_virt_addr_base, ctx->emi_size);
+ memset_io(ctx->emi_virt_addr_base, 0, ctx->emi_size);
+
+ conndump_set_dump_state(ctx, CORE_DUMP_INIT);
+}
+EXPORT_SYMBOL(connsys_coredump_clean);
+
+
+/*****************************************************************************
+ * FUNCTION
+ * connsys_coredump_setup_dump_region
+ * DESCRIPTION
+ * Parse dump region in EMI (including CR regions, IDLM, SYSRAM, ...)
+ * The number would be record in ctx->dump_regions_num
+ * The data would be stored in ctx->dump_regions
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+int connsys_coredump_setup_dump_region(void* handler)
+{
+ int ret = 0;
+ int cr_regions_idx = 0;
+ int total_mem_region;
+ int total_count;
+ int i, idx = 0, offset;
+ struct connsys_dump_ctx* ctx = (struct connsys_dump_ctx*)handler;
+ struct dump_region* curr_region = 0;
+
+ total_mem_region = conndump_get_dmp_info(
+ ctx, CONNSYS_DUMP_CTRL_BLOCK_OFFSET + EXP_CTRL_TOTAL_MEM_REGION, false);
+
+ /* Get idx first. The number is idx/8 */
+ cr_regions_idx = conndump_get_dmp_info(
+ ctx, CONNSYS_DUMP_CTRL_BLOCK_OFFSET + EXP_CTRL_CR_REGION_IDX, false);
+ if (cr_regions_idx & 0x7) {
+ pr_err("cr_regions_idx should be multiple of 8. But it is %d.\n", cr_regions_idx);
+ }
+ cr_regions_idx = (cr_regions_idx >> 3);
+ total_count = total_mem_region + cr_regions_idx;
+ pr_info("CR region=%d. Memory region=%d total dump regions is %d.\n",
+ cr_regions_idx, total_mem_region, total_count);
+
+ if (ctx->dump_regions) {
+ connsys_coredump_deinit_dump_regions(ctx);
+ }
+ if (total_count == 0) {
+ pr_info("Total dump regions is %d.\n", total_count);
+ return 0;
+ }
+
+ ret = connsys_coredump_init_dump_regions(ctx, total_count);
+ if (ret != total_count) {
+ pr_err("[%s] allocate %d dump regions failed\n", __func__, total_count);
+ return 0;
+ }
+
+ /* Setup memory region */
+ offset = CONNSYS_DUMP_CTRL_BLOCK_OFFSET + EXP_CTRL_MEM_REGION_NAME_1;
+ for (i = 0, curr_region = ctx->dump_regions; i < total_mem_region && idx < total_count; i++, idx++, offset += 12, curr_region++) {
+ conndump_get_dmp_char(ctx, offset, 4, curr_region->name);
+ curr_region->base = conndump_get_dmp_info(ctx, offset + 4, false);
+ curr_region->length = conndump_get_dmp_info(ctx, offset + 8, false);
+ pr_info("[%d][Memory region] name: %s, base: %x, length: %x\n",
+ idx,
+ curr_region->name,
+ curr_region->base,
+ curr_region->length);
+ }
+
+ offset = CONNSYS_DUMP_CR_REGION_OFFSET;
+ for (i = 0; i < cr_regions_idx && idx < total_count; i++, idx++, offset+=8) {
+ ctx->dump_regions[idx].base = conndump_get_dmp_info(ctx, offset, false);
+ ctx->dump_regions[idx].length = conndump_get_dmp_info(ctx, offset + 4, false);
+ pr_info("[%d][CR region] base: 0x%x, length: %d\n",
+ idx, ctx->dump_regions[idx].base, ctx->dump_regions[idx].length);
+ }
+ return ctx->dump_regions_num;
+}
+EXPORT_SYMBOL(connsys_coredump_setup_dump_region);
+
+/*****************************************************************************
+ * FUNCTION
+ * connsys_coredump_start
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+int connsys_coredump_start(
+ void* handler,
+ unsigned int dump_property,
+ int drv,
+ char* reason)
+{
+ struct connsys_dump_ctx* ctx = (struct connsys_dump_ctx*)handler;
+ int ret = 0;
+ bool full_dump = false;
+ struct timeval begin, end, put_done;
+ struct timeval mem_start, mem_end, cr_start, cr_end, emi_dump_start, emi_dump_end;
+
+ static DEFINE_RATELIMIT_STATE(_rs, HZ, 1);
+
+ if (ctx == NULL)
+ return 0;
+
+ /* TODO: Check coredump mode */
+ if (connsys_coredump_get_mode() == DUMP_MODE_RESET_ONLY) {
+ pr_info("Chip reset only, skip coredump\n");
+ return 0;
+ }
+
+ pr_info("[COREDUMP] dump_property=[0x%x] drv=[%d] reason=[%s]\n", dump_property, drv, reason);
+ do_gettimeofday(&begin);
+ conndump_set_dump_state(ctx, CORE_DUMP_START);
+ /* Reset assert info */
+ memset(&ctx->info, 0, sizeof(struct connsys_dump_info));
+ if (drv >= CONNDRV_TYPE_BT && drv < CONNDRV_TYPE_MAX) {
+ ctx->info.issue_type = CONNSYS_ISSUE_DRIVER_ASSERT;
+ ctx->info.drv_type = drv;
+ snprintf(ctx->info.reason, CONNSYS_ASSERT_REASON_SIZE, "%s", reason);
+ }
+
+ /* Start coredump timer */
+ mod_timer(&ctx->dmp_timer, jiffies + (CONNSYS_COREDUMP_TIMEOUT) / (1000 / HZ));
+
+ /* Check coredump status */
+ while (1) {
+ if (conndump_get_dmp_info(ctx, CONNSYS_DUMP_CTRL_BLOCK_OFFSET + EXP_CTRL_DUMP_STATE, false) == FW_DUMP_STATE_PUT_DONE) {
+ pr_info("coredump put done\n");
+ del_timer(&ctx->dmp_timer);
+ full_dump = true;
+ break;
+ } else if (conndump_get_dump_state(ctx) == CORE_DUMP_TIMEOUT) {
+ pr_err("Coredump timeout\n");
+ if (ctx->callback.poll_cpupcr) {
+ pr_info("Debug dump:\n");
+ ctx->callback.poll_cpupcr(5, 1);
+ }
+ conndump_send_fake_coredump(ctx);
+ goto partial_dump;
+ }
+ if (__ratelimit(&_rs)) {
+ pr_info("Wait coredump state, EMI[0]=0x%x EMI[4]=0x%x\n",
+ conndump_get_dmp_info(ctx, 0, false),
+ conndump_get_dmp_info(ctx, 4, false));
+ }
+ if (dump_property & CONNSYS_DUMP_PROPERTY_NO_WAIT) {
+ pr_info("Don't wait dump status, go to partial dump\n");
+ if (ctx->callback.poll_cpupcr) {
+ pr_info("Debug dump:\n");
+ ctx->callback.poll_cpupcr(5, 1);
+ }
+ conndump_send_fake_coredump(ctx);
+ goto partial_dump;
+ }
+ msleep(1);
+ }
+ do_gettimeofday(&put_done);
+ conndump_set_dump_state(ctx, CORE_DUMP_DOING);
+
+ /* Get print_buff */
+ conndump_dump_print_buff(ctx);
+
+ /* Get dump_buff and send to pack it */
+ conndump_dump_dump_buff(ctx);
+
+partial_dump:
+ /* TODO: move to init or other suitable place */
+ ret = connsys_coredump_setup_dump_region(ctx);
+ if (!ret)
+ pr_err("No dump region found\n");
+
+ conndump_set_dump_state(ctx, CORE_DUMP_DOING);
+ /* Memory region and CR region should be setup when MCU init */
+ /* Parse CR region and send to pack it */
+ do_gettimeofday(&cr_start);
+ conndump_dump_cr_regions(ctx);
+ do_gettimeofday(&cr_end);
+
+ /* Construct assert info and send to native */
+ conndump_info_format(ctx, ctx->page_dump_buf, CONNSYS_DUMP_BUFF_SIZE, full_dump);
+
+ /* Read memory region on ctrl block */
+ do_gettimeofday(&mem_start);
+ conndump_dump_mem_regions(ctx);
+ do_gettimeofday(&mem_end);
+
+
+ /* Start EMI dump */
+ do_gettimeofday(&emi_dump_start);
+ conndump_dump_emi(ctx);
+ do_gettimeofday(&emi_dump_end);
+
+ /* All process finished, set to init status */
+ conndump_set_dump_state(ctx, CORE_DUMP_INIT);
+
+ conndump_exception_show(ctx, full_dump);
+ do_gettimeofday(&end);
+ pr_info("Coredump end\n");
+ if (full_dump) {
+ pr_info("%s coredump summary: full dump total=[%lu] put_done=[%lu] cr=[%lu] mem=[%lu] emi=[%lu]\n",
+ g_type_name[ctx->conn_type],
+ timeval_to_ms(&begin, &end),
+ timeval_to_ms(&begin, &put_done),
+ timeval_to_ms(&cr_start, &cr_end),
+ timeval_to_ms(&mem_start, &mem_end),
+ timeval_to_ms(&emi_dump_start, &emi_dump_end));
+ } else {
+ pr_info("%s coredump summary: partial dump total=[%lu] cr=[%lu] mem=[%lu] emi=[%lu]\n",
+ g_type_name[ctx->conn_type],
+ timeval_to_ms(&begin, &end),
+ timeval_to_ms(&cr_start, &cr_end),
+ timeval_to_ms(&mem_start, &mem_end),
+ timeval_to_ms(&emi_dump_start, &emi_dump_end));
+ }
+ return 0;
+}
+EXPORT_SYMBOL(connsys_coredump_start);
+
+/*****************************************************************************
+ * FUNCTION
+ * connsys_coredump_get_start_offset
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+phys_addr_t connsys_coredump_get_start_offset(int conn_type)
+{
+ struct coredump_hw_config *config = get_coredump_platform_config(conn_type);
+
+ if (config)
+ return config->start_offset;
+ return 0;
+}
+EXPORT_SYMBOL(connsys_coredump_get_start_offset);
+
+/*****************************************************************************
+ * FUNCTION
+ * connsys_coredump_init
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+void* connsys_coredump_init(
+ int conn_type,
+ struct coredump_event_cb* cb)
+{
+ struct connsys_dump_ctx* ctx = 0;
+ struct netlink_event_cb nl_cb;
+ struct coredump_hw_config *config = get_coredump_platform_config(conn_type);
+ phys_addr_t emi_base;
+ unsigned int emi_size, mcif_emi_size;
+
+ /* Get EMI config */
+ if (config == NULL) {
+ pr_err("Get coredump EMI config fail\n");
+ goto error_exit;
+ }
+
+ ctx = (struct connsys_dump_ctx*)conndump_malloc(sizeof(struct connsys_dump_ctx));
+ if (!ctx) {
+ pr_err("Allocate connsys_dump_ctx fail");
+ goto error_exit;
+ }
+
+ /* clean it */
+ memset(ctx, 0, sizeof(struct connsys_dump_ctx));
+ memcpy(&ctx->hw_config, config, sizeof(struct coredump_hw_config));
+
+ ctx->page_dump_buf = (char*)conndump_malloc(CONNSYS_DUMP_BUFF_SIZE);
+ if (!ctx->page_dump_buf) {
+ pr_err("Create dump buffer fail.\n");
+ goto error_exit;
+ }
+
+ ctx->conn_type = conn_type;
+ if (cb)
+ memcpy(&ctx->callback, cb, sizeof(struct coredump_event_cb));
+ else
+ pr_info("[%s][%d] callback is null\n", __func__, conn_type);
+
+ /* EMI init */
+ conninfra_get_emi_phy_addr(CONNSYS_EMI_FW, &emi_base, &emi_size);
+ conninfra_get_emi_phy_addr(CONNSYS_EMI_MCIF, NULL, &mcif_emi_size);
+ pr_info("Get emi_base=0x%x emi_size=%d\n", emi_base, emi_size);
+ ctx->full_emi_size = emi_size;
+ ctx->emi_phy_addr_base = config->start_offset + emi_base;
+ ctx->emi_size = config->size;
+ ctx->mcif_emi_size = mcif_emi_size;
+
+ ctx->emi_virt_addr_base =
+ ioremap_nocache(ctx->emi_phy_addr_base, ctx->emi_size);
+ if (ctx->emi_virt_addr_base == 0) {
+ pr_err("Remap emi fail (0x%08x) size=%d",
+ ctx->emi_phy_addr_base, ctx->emi_size);
+ goto error_exit;
+ }
+
+ pr_info("Clear %p size=%d as zero\n", ctx->emi_virt_addr_base, ctx->emi_size);
+ memset_io(ctx->emi_virt_addr_base, 0, ctx->emi_size);
+
+ /* Setup timer */
+ init_timer(&ctx->dmp_timer);
+ ctx->dmp_timer.function = conndump_timeout_handler;
+ ctx->dmp_timer.data = (unsigned long)ctx;
+ init_completion(&ctx->emi_dump);
+
+ conndump_set_dump_state(ctx, CORE_DUMP_INIT);
+
+ /* Init netlink */
+ nl_cb.coredump_end = conndump_coredump_end;
+ conndump_netlink_init(ctx->conn_type, ctx, &nl_cb);
+ return ctx;
+
+error_exit:
+ if (ctx)
+ connsys_coredump_deinit(ctx);
+
+ return 0;
+}
+EXPORT_SYMBOL(connsys_coredump_init);
+
+/*****************************************************************************
+ * FUNCTION
+ * connsys_coredump_deinit
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+void connsys_coredump_deinit(void* handler)
+{
+ struct connsys_dump_ctx* ctx = (struct connsys_dump_ctx*)handler;
+
+ if (handler == NULL)
+ return;
+
+ if (ctx->emi_virt_addr_base) {
+ iounmap(ctx->emi_virt_addr_base);
+ ctx->emi_virt_addr_base = NULL;
+ }
+
+ if (ctx->page_dump_buf) {
+ conndump_free(ctx->page_dump_buf);
+ ctx->page_dump_buf = NULL;
+ }
+
+ if (ctx->dump_regions) {
+ connsys_coredump_deinit_dump_regions(ctx);
+ ctx->dump_regions = NULL;
+ }
+
+ conndump_free(ctx);
+}
+EXPORT_SYMBOL(connsys_coredump_deinit);
+
+
+/*****************************************************************************
+ * FUNCTION
+ * connsys_coredump_get_mode
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+enum connsys_coredump_mode connsys_coredump_get_mode(void)
+{
+ return atomic_read(&g_dump_mode);
+}
+EXPORT_SYMBOL(connsys_coredump_get_mode);
+
+/*****************************************************************************
+ * FUNCTION
+ * connsys_coredump_set_dump_mode
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *
+ * RETURNS
+ *
+ *****************************************************************************/
+void connsys_coredump_set_dump_mode(enum connsys_coredump_mode mode)
+{
+ if (mode < DUMP_MODE_MAX)
+ atomic_set(&g_dump_mode, mode);
+}
+EXPORT_SYMBOL(connsys_coredump_set_dump_mode);
+
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/connsys_coredump.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/connsys_coredump.h
new file mode 100755
index 0000000..609f60b
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/connsys_coredump.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef _CONNSYS_COREDUMP_H_
+#define _CONNSYS_COREDUMP_H_
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+/* Coredump property */
+#define CONNSYS_DUMP_PROPERTY_NO_WAIT 0x1
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+enum connsys_coredump_mode {
+ DUMP_MODE_RESET_ONLY = 0,
+ DUMP_MODE_AEE = 1,
+ DUMP_MODE_DAEMON = 2,
+ DUMP_MODE_MAX,
+};
+
+struct coredump_event_cb {
+ int (*reg_readable)(void);
+ void (*poll_cpupcr)(unsigned int times, unsigned int sleep);
+};
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+/* subsys usage */
+void* connsys_coredump_init(
+ int conn_type,
+ struct coredump_event_cb* cb);
+void connsys_coredump_deinit(void* handler);
+
+phys_addr_t connsys_coredump_get_start_offset(int conn_type);
+
+int connsys_coredump_setup_dump_region(void* handler);
+int connsys_coredump_start(
+ void* handler,
+ unsigned int dump_property,
+ int drv,
+ char *reason);
+void connsys_coredump_clean(void* handler);
+
+
+/* config relative */
+enum connsys_coredump_mode connsys_coredump_get_mode(void);
+void connsys_coredump_set_dump_mode(enum connsys_coredump_mode mode);
+
+#endif
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/connsys_coredump_emi.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/connsys_coredump_emi.h
new file mode 100755
index 0000000..b521404
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/connsys_coredump_emi.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _CONNSYS_COREDUMP_EMI_H_
+#define _CONNSYS_COREDUMP_EMI_H_
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+
+/* Block and size definition */
+#define CONNSYS_DUMP_CTRL_BLOCK_SIZE 0x80
+#define CONNSYS_DUMP_DEBUG_BLOCK_SIZE 0x80
+#define CONNSYS_DUMP_PRINT_BUFF_SIZE 0x7f00
+#define CONNSYS_DUMP_DUMP_BUFF_SIZE 0x8000
+#define CONNSYS_DUMP_CR_REGION_SIZE 0x8000
+
+#define CONNSYS_DUMP_CTRL_BLOCK_OFFSET 0x0
+#define CONNSYS_DUMP_DEBUG_BLOCK_OFFSET (CONNSYS_DUMP_CTRL_BLOCK_OFFSET + CONNSYS_DUMP_CTRL_BLOCK_SIZE)
+#define CONNSYS_DUMP_PRINT_BUFF_OFFSET (CONNSYS_DUMP_DEBUG_BLOCK_OFFSET + CONNSYS_DUMP_DEBUG_BLOCK_SIZE)
+#define CONNSYS_DUMP_DUMP_BUFF_OFFSET (CONNSYS_DUMP_PRINT_BUFF_OFFSET + CONNSYS_DUMP_PRINT_BUFF_SIZE)
+#define CONNSYS_DUMP_CR_REGION_OFFSET (CONNSYS_DUMP_DUMP_BUFF_OFFSET + CONNSYS_DUMP_DUMP_BUFF_SIZE)
+
+/* Control block definition */
+enum connsys_dump_ctrl_block_offset {
+ EXP_CTRL_DUMP_STATE = 0x4,
+ EXP_CTRL_OUTBAND_ASSERT_W1 = 0x8,
+ EXP_CTRL_PRINT_BUFF_IDX = 0xC,
+ EXP_CTRL_DUMP_BUFF_IDX = 0x10,
+ EXP_CTRL_CR_REGION_IDX = 0x14,
+ EXP_CTRL_TOTAL_MEM_REGION = 0x18,
+ EXP_CTRL_MEM_REGION_NAME_1 = 0x1C,
+ EXP_CTRL_MEM_REGION_START_1 = 0x20,
+ EXP_CTRL_MEM_REGION_LEN_1 = 0x24,
+ EXP_CTRL_MEM_REGION_NAME_2 = 0x28,
+ EXP_CTRL_MEM_REGION_START_2 = 0x2c,
+ EXP_CTRL_MEM_REGION_LEN_2 = 0x30,
+ EXP_CTRL_MEM_REGION_NAME_3 = 0x34,
+ EXP_CTRL_MEM_REGION_START_3 = 0x38,
+ EXP_CTRL_MEM_REGION_LEN_3 = 0x3c,
+ EXP_CTRL_MEM_REGION_NAME_4 = 0x40,
+ EXP_CTRL_MEM_REGION_START_4 = 0x44,
+ EXP_CTRL_MEM_REGION_LEN_4 = 0x48,
+ EXP_CTRL_MEM_REGION_NAME_5 = 0x4C,
+ EXP_CTRL_MEM_REGION_START_5 = 0x50,
+ EXP_CTRL_MEM_REGION_LEN_5 = 0x54,
+};
+
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+
+#endif /*_CONNSYS_COREDUMP_EMI_H_*/
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/platform/include/connsys_coredump_hw_config.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/platform/include/connsys_coredump_hw_config.h
new file mode 100755
index 0000000..d150804
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/platform/include/connsys_coredump_hw_config.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _CONNSYS_COREDUMP_HW_CONFIG_H_
+#define _CONNSYS_COREDUMP_HW_CONFIG_H_
+
+
+struct coredump_hw_config {
+ char* name;
+ phys_addr_t start_offset;
+ unsigned int size;
+ unsigned int seg1_cr;
+ unsigned int seg1_value_end;
+ unsigned int seg1_start_addr;
+ unsigned int seg1_phy_addr;
+ unsigned int task_table_size;
+ char** task_map_table;
+ char* exception_tag_name;
+};
+
+#endif
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/platform/mt6885/mt6885.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/platform/mt6885/mt6885.c
new file mode 100755
index 0000000..3ebcf97
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/coredump/platform/mt6885/mt6885.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/printk.h>
+
+#include "connsys_debug_utility.h"
+#include "connsys_coredump_hw_config.h"
+
+static char* wifi_task_str[] = {
+ "Task_WIFI",
+ "Task_TST_WFSYS",
+ "Task_Idle_WFSYS",
+};
+
+static char* bt_task_str[] = {
+ "Task_WMT",
+ "Task_BT",
+ "Task_TST_BTSYS",
+ "Task_BT2",
+ "Task_Idle_BTSYS",
+};
+
+struct coredump_hw_config g_coredump_config[CONN_DEBUG_TYPE_END] = {
+ /* Wi-Fi config */
+ {
+ .name = "WFSYS",
+#ifdef CONFIG_FPGA_EARLY_PORTING
+ .start_offset = 0x0004f000,
+#else
+ .start_offset = 0x027f000,
+#endif
+ .size = 0x18000,
+ .seg1_cr = 0x1800112c,
+ .seg1_value_end = 0x187fffff,
+ .seg1_start_addr = 0x18001120,
+ .seg1_phy_addr = 0x18500000,
+ .task_table_size = sizeof(wifi_task_str)/sizeof(char*),
+ .task_map_table = wifi_task_str,
+ .exception_tag_name = "combo_wifi",
+ },
+ /* BT config */
+ {
+ .name = "BTSYS",
+ .start_offset = 0x33000,
+ .size = 0x18000,
+ .seg1_cr = 0x18001110,
+ .seg1_value_end = 0x18bfffff,
+ .seg1_start_addr = 0x18001104,
+ .seg1_phy_addr = 0x18900000,
+ .task_table_size = sizeof(bt_task_str)/sizeof(char*),
+ .task_map_table = bt_task_str,
+ .exception_tag_name = "combo_bt",
+ },
+};
+
+struct coredump_hw_config* get_coredump_platform_config(int conn_type)
+{
+ if (conn_type < 0 || conn_type >= CONN_DEBUG_TYPE_END) {
+ pr_err("Incorrect type: %d\n", conn_type);
+ return NULL;
+ }
+ return &g_coredump_config[conn_type];
+}
+
+unsigned int get_coredump_platform_chipid(void)
+{
+ return 0x6885;
+}
+
+char* get_task_string(int conn_type, unsigned int task_id)
+{
+ if (conn_type < 0 || conn_type >= CONN_DEBUG_TYPE_END) {
+ pr_err("Incorrect type: %d\n", conn_type);
+ return NULL;
+ }
+
+ if (task_id > g_coredump_config[conn_type].task_table_size) {
+ pr_err("[%s] Incorrect task: %d\n",
+ g_coredump_config[conn_type].name, task_id);
+ return NULL;
+ }
+
+ return g_coredump_config[conn_type].task_map_table[task_id];
+}
+
+char* get_sys_name(int conn_type)
+{
+ if (conn_type < 0 || conn_type >= CONN_DEBUG_TYPE_END) {
+ pr_err("Incorrect type: %d\n", conn_type);
+ return NULL;
+ }
+ return g_coredump_config[conn_type].name;
+}
+
+bool is_host_view_cr(unsigned int addr, unsigned int* host_view)
+{
+ if (addr >= 0x7C000000 && addr <= 0x7Cffffff) {
+ if (host_view) {
+ *host_view = ((addr - 0x7c000000) + 0x18000000);
+ }
+ return true;
+ } else if (addr >= 0x18000000 && addr <= 0x18ffffff) {
+ if (host_view) {
+ *host_view = addr;
+ }
+ return true;
+ }
+ return false;
+}
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/include/connsys_debug_utility.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/include/connsys_debug_utility.h
new file mode 100644
index 0000000..897bda5
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/include/connsys_debug_utility.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef _CONNSYS_DEBUG_UTILITY_H_
+#define _CONNSYS_DEBUG_UTILITY_H_
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+#include "coredump/connsys_coredump.h"
+#include "connsyslog/connsyslog.h"
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+enum CONN_DEBUG_TYPE {
+ CONN_DEBUG_TYPE_WIFI = 0,
+ CONN_DEBUG_TYPE_BT = 1,
+ CONN_DEBUG_TYPE_END,
+};
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+
+#endif /*_CONNSYS_DEBUG_UTILITY_H_*/
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/CONNINFRA_STEP.cfg b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/CONNINFRA_STEP.cfg
new file mode 100755
index 0000000..ab2beca
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/CONNINFRA_STEP.cfg
@@ -0,0 +1,112 @@
+// Action | symbol | Param1 | Param2 | Param3 | Param4 | Param5
+// Read EMI | _EMI | R(0) | Begin offset | End offset
+// Read EMI to temp register | _EMI | R(0) | offset | Temp Reg ID($)
+// Read EMI to temp register | _EMI | R(0) | offset | mask | Temp Reg ID ($)
+// Read CR | _REG | R(0) | Pre-define base-addr ID | offset | times | delay time(ms)
+// Read CR | _REG | R(0) | AP Physical address | offset | times | delay time(ms)
+// Read CR to temp register | _REG | R(0) | Pre-define base-addr ID | offset | Temp Reg ID($)
+// Read CR to temp register | _REG | R(0) | AP Physical address | offset | Temp Reg ID($)
+// Read CR to temp register | _REG | R(0) | Pre-define base-addr ID | offset | mask | Temp Reg ID($)
+// Read CR to temp register | _REG | R(0) | AP Physical address | offset | mask | Temp Reg ID($)
+// Write CR | _REG | W(1) | Pre-define base-addr ID | offset | value
+// Write CR | _REG | W(1) | AP Physical address | offset | value
+// Write CR some bit | _REG | W(1) | Pre-define base-addr ID | offset | value | mask
+// Write CR some bit | _REG | W(1) | AP Physical address | offset | value | mask
+// Read GPIO | GPIO | R(0) | Pin number
+
+// Show message | SHOW | String(No space)
+
+// Check condition to result temp register | COND | Result Temp Reg ID($) | Left Temp Reg ID($) | Operator | Right Temp Reg ID($)
+// Check condition to result temp register | COND | Result Temp Reg ID($) | Left Temp Reg ID($) | Operator | Value(Dec or Hex)
+// Save value to temp register | _VAL | Temp Reg ID($) | Value
+//
+// Condition Action | symbol | Param1 | Param2 | Param3 | Param4 | Param5 | Param6
+// Read EMI with Condition | CEMI | Condition Temp Reg ID($) | R(0) | Begin offset | End offset
+// Read EMI to temp register with Condition | CEMI | Condition Temp Reg ID($) | R(0) | Begin offset | Temp Reg ID($)
+// Read EMI to temp register with Condition | CEMI | Condition Temp Reg ID($) | R(0) | Begin offset | mask | Temp Reg ID($)
+// Read CR with Condition | CREG | Condition Temp Reg ID($) | R(0) | Pre-define base-addr ID | offset | times | delay time(ms)
+// Read CR with Condition | CREG | Condition Temp Reg ID($) | R(0) | AP Physical address | offset | times | delay time(ms)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | Pre-define base-addr ID | offset | Temp Reg ID($)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | AP Physical address | offset | Temp Reg ID($)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | Pre-define base-addr ID | offset | mask | Temp Reg ID($)
+// Read CR to temp register with Condition | CREG | Condition Temp Reg ID($) | R(0) | AP Physical address | offset | mask | Temp Reg ID($)
+// Write CR with Condition | CREG | Condition Temp Reg ID($) | W(1) | Pre-define base-addr ID | offset | value
+// Write CR with Condition | CREG | Condition Temp Reg ID($) | W(1) | AP Physical address | offset | value
+// Write CR some bit with Condition | CREG | Condition Temp Reg ID($) | W(1) | Pre-define base-addr ID | offset | value | mask
+// Write CR some bit with Condition | CREG | Condition Temp Reg ID($) | W(1) | AP Physical address | offset | value | mask
+//
+// Periodic dump: Add PD in trigger point
+// [TP x] Trigger point
+// [PD+] ms
+// [AT] xxxx
+// [AT] xxxx
+// [PD-]
+//
+// Temp Reg ID: ($0 ~ $9)
+//
+// Operator: ==, !=, >, >=, <, <=, &&, ||
+//
+// Pre-define base-addr ID: (You can find address and size in DTS file)
+// alps/kernel-4.9/arch/arm64/boot/dts/mediatek/mt6885.dts
+// base / size
+// #1 ==> conn_infra_rgu 0x18000000 / 0x1000
+// #2 ==> conn_infra_cfg 0x18001000 / 0x1000
+// #3 ==> conn_host_csr_top 0x18060000 / 0x10000
+// #4 ==> infracfg_ao 0x10001000 / 0x1000
+// #5 ==> TOP RGU 0x10007000 / 0x1000
+// #6 ==> SPM 0x10006000 / 0x1000
+// #7 ==> INFRACFG 0x1020e000 / 0x1000
+// #8 ==> conn_wt_slp_ctl_reg 0x18005000 / 0x1000
+// #9 ==> conn_afe_ctl 0x18003000 / 0x1000
+// #10 ==> conn_infra_sysram 0x18050000 / 0x10000
+// #11 ==> GPIO 0x10005000 / 0x1000
+// #12 ==> conn_rf_spi_mst_reg 0x18004000 / 0x1000
+// #13 ==> conn_semaphore 0x18070000 / 0x10000
+// #14 ==> conn_top_therm_ctl 0x18002000 / 0x1000
+// #15 ==> IOCFG_RT 0x11ea0000 / 0x1000
+
+// ********************** CONNINFRA ************************* //
+[TP CONNINFRA 1] Before Chip reset
+ [AT] _REG 0 #2 0x000 1 0
+
+[TP CONNINFRA 2] After Chip reset
+
+[TP CONNINFRA 3] Before read consys thermal
+ [AT] _REG 0 #2 0x000 1 0
+
+[TP CONNINFRA 4] Power on sequence(0): Start power on
+
+[TP CONNINFRA 5] Power on sequence(1): Before can get connsys id
+
+[TP CONNINFRA 6] Power on sequence(6): End power on
+
+[TP CONNINFRA 7] Before CONNINFRA power off
+
+[TP CONNINFRA 8] When AP suspend
+
+[TP CONNINFRA 9] When AP resume
+ [AT] _REG 0 #2 0x000 1 0
+
+
+// ********************** WF ************************* //
+[TP WF 1] Command timeout
+[TP WF 2] Before Chip reset
+[TP WF 3] After Chip reset
+
+
+// ********************** BT ************************* //
+[TP BT 1] Command timeout
+[TP BT 2] Before Chip reset
+[TP BT 3] After Chip reset
+
+
+// ********************** GPS ************************ //
+[TP GPS 1] Command timeout
+[TP GPS 2] Before Chip reset
+[TP GPS 3] After Chip reset
+
+
+// ********************** FM ************************* //
+[TP FM 1] Command timeout
+[TP FM 2] Before Chip reset
+[TP FM 3] After Chip reset
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/conninfra_step.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/conninfra_step.c
new file mode 100755
index 0000000..e0beee7
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/conninfra_step.c
@@ -0,0 +1,1145 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <connectivity_build_in_adapter.h>
+
+#include <linux/firmware.h>
+#include <asm/delay.h>
+#include <linux/slab.h>
+
+#include "osal.h"
+#include "conninfra_step.h"
+#include "conninfra_step_parse_act.h"
+#include "conninfra_core.h"
+#include "consys_hw.h"
+#include "emi_mng.h"
+#include "consys_reg_mng.h"
+#include "consys_reg_util.h"
+
+/*******************************************************************************
+ * F U N C T I O N D E C L A R A T I O N S
+********************************************************************************/
+
+static void conninfra_step_remove_emi_action(struct step_action *p_act);
+static void conninfra_step_remove_register_action(struct step_action *p_act);
+static void conninfra_step_remove_gpio_action(struct step_action *p_act);
+static void conninfra_step_remove_periodic_dump_action(struct step_action *p_act);
+static void conninfra_step_remove_show_string_action(struct step_action *p_act);
+static void conninfra_step_remove_sleep_action(struct step_action *p_act);
+static void conninfra_step_remove_condition_action(struct step_action *p_act);
+static void conninfra_step_remove_value_action(struct step_action *p_act);
+static void conninfra_step_remove_condition_emi_action(struct step_action *p_act);
+static void conninfra_step_remove_condition_register_action(struct step_action *p_act);
+
+
+static int conninfra_step_operator_result_greater(int l_val, int r_val);
+static int conninfra_step_operator_result_greater_equal(int l_val, int r_val);
+static int conninfra_step_operator_result_less(int l_val, int r_val);
+static int conninfra_step_operator_result_less_equal(int l_val, int r_val);
+static int conninfra_step_operator_result_equal(int l_val, int r_val);
+static int conninfra_step_operator_result_not_equal(int l_val, int r_val);
+static int conninfra_step_operator_result_and(int l_val, int r_val);
+static int conninfra_step_operator_result_or(int l_val, int r_val);
+
+
+/*******************************************************************************
+ * D E F I N E
+********************************************************************************/
+
+/*******************************************************************************
+ * P R I V A T E D A T A
+********************************************************************************/
+struct step_env_struct g_infra_step_env;
+
+struct step_drv_type_def g_step_drv_type_def[STEP_DRV_TYPE_MAX] = {
+ [STEP_DRV_TYPE_NO_DEFINE] = {"NoDefine", -1, NULL, NULL},
+ [STEP_DRV_TYPE_CONNINFRA] = {"CONNINFRA", STEP_CONNINFRA_TP_MAX, NULL, &g_infra_step_env.conninfra_actions[0]},
+ [STEP_DRV_TYPE_BT] = {"BT", STEP_BT_TP_MAX, NULL, &g_infra_step_env.bt_actions[0]},
+ [STEP_DRV_TYPE_FM] = {"FM", STEP_FM_TP_MAX, NULL, &g_infra_step_env.fm_actions[0]},
+ [STEP_DRV_TYPE_GPS] = {"GPS", STEP_GPS_TP_MAX, NULL, &g_infra_step_env.gps_actions[0]},
+ [STEP_DRV_TYPE_WIFI] = {"WF", STEP_WF_TP_MAX, NULL, &g_infra_step_env.wf_actions[0]},
+};
+
+
+
+static const struct step_action_contrl conninfra_step_action_map[] = {
+ [STEP_ACTION_INDEX_EMI] = {
+ conninfra_step_create_emi_action,
+ conninfra_step_do_emi_action,
+ conninfra_step_remove_emi_action
+ },
+ [STEP_ACTION_INDEX_REGISTER] = {
+ conninfra_step_create_register_action,
+ conninfra_step_do_register_action,
+ conninfra_step_remove_register_action
+ },
+ [STEP_ACTION_INDEX_GPIO] = {
+ conninfra_step_create_gpio_action,
+ conninfra_step_do_gpio_action,
+ conninfra_step_remove_gpio_action
+ },
+ [STEP_ACTION_INDEX_PERIODIC_DUMP] = {
+ conninfra_step_create_periodic_dump_action,
+ conninfra_step_do_periodic_dump_action,
+ conninfra_step_remove_periodic_dump_action,
+ },
+ [STEP_ACTION_INDEX_SHOW_STRING] = {
+ conninfra_step_create_show_string_action,
+ conninfra_step_do_show_string_action,
+ conninfra_step_remove_show_string_action
+ },
+ [STEP_ACTION_INDEX_SLEEP] = {
+ conninfra_step_create_sleep_action,
+ conninfra_step_do_sleep_action,
+ conninfra_step_remove_sleep_action
+ },
+ [STEP_ACTION_INDEX_CONDITION] = {
+ conninfra_step_create_condition_action,
+ conninfra_step_do_condition_action,
+ conninfra_step_remove_condition_action
+ },
+ [STEP_ACTION_INDEX_VALUE] = {
+ conninfra_step_create_value_action,
+ conninfra_step_do_value_action,
+ conninfra_step_remove_value_action
+ },
+ [STEP_ACTION_INDEX_CONDITION_EMI] = {
+ conninfra_step_create_condition_emi_action,
+ conninfra_step_do_condition_emi_action,
+ conninfra_step_remove_condition_emi_action
+ },
+ [STEP_ACTION_INDEX_CONDITION_REGISTER] = {
+ conninfra_step_create_condition_register_action,
+ conninfra_step_do_condition_register_action,
+ conninfra_step_remove_condition_register_action
+ },
+};
+
+typedef int (*STEP_OPERATOR_RESULT) (int, int);
+static const STEP_OPERATOR_RESULT conninfra_step_operator_result_map[] = {
+ [STEP_OPERATOR_GREATER] = conninfra_step_operator_result_greater,
+ [STEP_OPERATOR_GREATER_EQUAL] = conninfra_step_operator_result_greater_equal,
+ [STEP_OPERATOR_LESS] = conninfra_step_operator_result_less,
+ [STEP_OPERATOR_LESS_EQUAL] = conninfra_step_operator_result_less_equal,
+ [STEP_OPERATOR_EQUAL] = conninfra_step_operator_result_equal,
+ [STEP_OPERATOR_NOT_EQUAL] = conninfra_step_operator_result_not_equal,
+ [STEP_OPERATOR_AND] = conninfra_step_operator_result_and,
+ [STEP_OPERATOR_OR] = conninfra_step_operator_result_or,
+};
+
+/*******************************************************************************
+ * I N T E R N A L F U N C T I O N S
+********************************************************************************/
+
+static void conninfra_step_init_list(void)
+{
+ unsigned int i = 0;
+
+ for (i = 0; i < STEP_CONNINFRA_TP_MAX; i++)
+ INIT_LIST_HEAD(&(g_infra_step_env.conninfra_actions[i].list));
+
+ for (i = 0; i < STEP_WF_TP_MAX; i++)
+ INIT_LIST_HEAD(&(g_infra_step_env.wf_actions[i].list));
+
+ for (i = 0; i < STEP_BT_TP_MAX; i++)
+ INIT_LIST_HEAD(&(g_infra_step_env.bt_actions[i].list));
+
+ for (i = 0; i < STEP_GPS_TP_MAX; i++)
+ INIT_LIST_HEAD(&(g_infra_step_env.gps_actions[i].list));
+
+ for (i = 0; i < STEP_FM_TP_MAX; i++)
+ INIT_LIST_HEAD(&(g_infra_step_env.fm_actions[i].list));
+
+}
+
+static unsigned char __iomem *conninfra_step_get_emi_base_address(void)
+{
+ struct consys_emi_addr_info* emi_addr_info = NULL;
+
+ if (g_infra_step_env.emi_base_addr == NULL) {
+ emi_addr_info = emi_mng_get_phy_addr();
+ if (emi_addr_info != NULL) {
+ g_infra_step_env.emi_base_addr = ioremap_nocache(emi_addr_info->emi_ap_phy_addr,
+ emi_addr_info->emi_size);
+ g_infra_step_env.emi_size = emi_addr_info->emi_size;
+ }
+ }
+
+ return g_infra_step_env.emi_base_addr;
+}
+
+static void conninfra_step_clear_action_list(struct step_action_list *action_list)
+{
+ struct step_action *p_act, *p_act_next;
+
+ list_for_each_entry_safe(p_act, p_act_next, &(action_list->list), list) {
+ list_del_init(&p_act->list);
+ conninfra_step_remove_action(p_act);
+ }
+}
+
+static void conninfra_step_clear_list(void)
+{
+ unsigned int i = 0;
+
+ for (i = 0; i < STEP_CONNINFRA_TP_MAX; i++)
+ conninfra_step_clear_action_list(&g_infra_step_env.conninfra_actions[i]);
+
+ for (i = 0; i < STEP_WF_TP_MAX; i++)
+ conninfra_step_clear_action_list(&g_infra_step_env.wf_actions[i]);
+
+ for (i = 0; i < STEP_BT_TP_MAX; i++)
+ conninfra_step_clear_action_list(&g_infra_step_env.bt_actions[i]);
+
+ for (i = 0; i < STEP_GPS_TP_MAX; i++)
+ conninfra_step_clear_action_list(&g_infra_step_env.gps_actions[i]);
+
+ for (i = 0; i < STEP_FM_TP_MAX; i++)
+ conninfra_step_clear_action_list(&g_infra_step_env.fm_actions[i]);
+
+#if 0
+ for (i = 0; i < STEP_DRV_TYPE_MAX; i++)
+ for (j = 0; j < STEP_TRIGGER_POINT_MAX; j++)
+ conninfra_step_clear_action_list(&g_infra_step_env.actions[i][j]);
+#endif
+}
+
+static void conninfra_step_unioremap_emi(void)
+{
+ if (g_infra_step_env.emi_base_addr != NULL) {
+ iounmap(g_infra_step_env.emi_base_addr);
+ g_infra_step_env.emi_base_addr = NULL;
+ }
+}
+
+static unsigned char *conninfra_step_get_emi_virt_addr(unsigned char *emi_base_addr, unsigned int offset)
+{
+ unsigned char *p_virtual_addr = NULL;
+
+ if (offset > g_infra_step_env.emi_size) {
+ pr_err("STEP failed: offset size %d over MAX size(%d)\n", offset,
+ g_infra_step_env.emi_size);
+ return NULL;
+ }
+ p_virtual_addr = emi_base_addr + offset;
+
+ return p_virtual_addr;
+}
+
+static int conninfra_step_get_cfg(const char *p_patch_name, osal_firmware **pp_patch)
+{
+ osal_firmware *fw = NULL;
+
+ *pp_patch = NULL;
+ if (request_firmware((const struct firmware **)&fw, p_patch_name, NULL) != 0)
+ return -1;
+
+ pr_debug("Load step cfg %s ok!!\n", p_patch_name);
+ *pp_patch = fw;
+
+ return 0;
+}
+
+static int conninfra_step_release_cfg(osal_firmware ** ppPatch)
+{
+ if (ppPatch != NULL) {
+ release_firmware((const struct firmware *)*ppPatch);
+ *ppPatch = NULL;
+ }
+ return 0;
+}
+
+static void conninfra_step_sleep_or_delay(int ms)
+{
+ /* msleep < 20ms can sleep for up to 20ms */
+ if (ms < 20)
+ udelay(ms * 1000);
+ else
+ osal_sleep_ms(ms);
+}
+
+struct step_action_list *conninfra_step_get_tp_list(enum step_drv_type drv_type, int tp_id)
+{
+ if (drv_type <= STEP_DRV_TYPE_NO_DEFINE || drv_type >= STEP_DRV_TYPE_MAX) {
+ pr_err("STEP failed: incorrect drv type: %d\n", drv_type);
+ return NULL;
+ }
+
+ if (tp_id <= STEP_TP_NO_DEFINE || tp_id >= g_step_drv_type_def[drv_type].tp_max) {
+ pr_err("STEP failed: Write action to drv_type [%d] tp_id: [%d]\n",
+ drv_type, tp_id);
+ return NULL;
+ }
+
+ return &g_step_drv_type_def[drv_type].action_list[tp_id];
+}
+
+static void _conninfra_step_do_actions(struct step_action_list *action_list)
+{
+ struct step_action *p_act, *p_act_next;
+
+ list_for_each_entry_safe(p_act, p_act_next, &action_list->list, list) {
+ if (p_act->action_id <= STEP_ACTION_INDEX_NO_DEFINE || p_act->action_id >= STEP_ACTION_INDEX_MAX) {
+ pr_err("STEP failed: Wrong action id %d\n", (int)p_act->action_id);
+ continue;
+ }
+
+ if (conninfra_step_action_map[p_act->action_id].func_do_action != NULL)
+ conninfra_step_action_map[p_act->action_id].func_do_action(p_act, NULL);
+ else
+ pr_err("STEP failed: Action is NULL\n");
+ }
+}
+
+static void conninfra_step_start_work(struct step_pd_entry *p_entry)
+{
+ unsigned int timeout;
+ int result = 0;
+
+ if (!g_infra_step_env.pd_struct.step_pd_wq) {
+ pr_err("STEP failed: step wq doesn't run\n");
+ result = -1;
+ }
+
+ if (p_entry == NULL) {
+ pr_err("STEP failed: entry is null\n");
+ result = -1;
+ }
+
+ if (result == 0) {
+ timeout = p_entry->expires_ms;
+ queue_delayed_work(g_infra_step_env.pd_struct.step_pd_wq, &p_entry->pd_work, timeout);
+ }
+}
+
+static void conninfra_step_pd_work(struct work_struct *work)
+{
+ struct step_pd_entry *p_entry;
+ struct delayed_work *delayed_work;
+ int result = 0;
+
+ if (down_read_trylock(&g_infra_step_env.init_rwsem)) {
+ if (!g_infra_step_env.is_enable) {
+ pr_err("STEP failed: step doesn`t enable\n");
+ result = -1;
+ }
+
+ delayed_work = to_delayed_work(work);
+ if (delayed_work == NULL) {
+ pr_err("STEP failed: work is NULL\n");
+ result = -1;
+ }
+
+ if (result == 0) {
+ p_entry = container_of(delayed_work, struct step_pd_entry, pd_work);
+
+ pr_info("STEP show: Periodic dump: %d ms\n", p_entry->expires_ms);
+ _conninfra_step_do_actions(&p_entry->action_list);
+ conninfra_step_start_work(p_entry);
+ }
+
+ up_read(&g_infra_step_env.init_rwsem);
+ }
+}
+
+static struct step_pd_entry *conninfra_step_create_periodic_dump_entry(unsigned int expires)
+{
+ struct step_pd_entry *p_pd_entry = NULL;
+
+ p_pd_entry = kzalloc(sizeof(struct step_pd_entry), GFP_KERNEL);
+ if (p_pd_entry == NULL) {
+ pr_err("STEP failed: kzalloc fail\n");
+ return NULL;
+ }
+ p_pd_entry->expires_ms = expires;
+
+ INIT_DELAYED_WORK(&p_pd_entry->pd_work, conninfra_step_pd_work);
+ INIT_LIST_HEAD(&(p_pd_entry->action_list.list));
+
+ return p_pd_entry;
+}
+
+static void conninfra_step_print_trigger_time(enum consys_conninfra_step_trigger_point tp_id, char *reason)
+{
+ const char *p_trigger_name = NULL;
+
+ /* TODO: print trigger point name */
+ //p_trigger_name = STEP_TRIGGER_TIME_NAME[tp_id];
+ p_trigger_name = "";
+ if (reason != NULL)
+ pr_info("STEP show: Trigger point: %s reason: %s\n", p_trigger_name, reason);
+ else
+ pr_info("STEP show: Trigger point: %s\n", p_trigger_name);
+}
+
+void conninfra_step_do_actions_from_tp(enum step_drv_type drv_type,
+ unsigned int tp_id, char *reason)
+{
+ int result = 0;
+
+ if (down_read_trylock(&g_infra_step_env.init_rwsem)) {
+ if (g_infra_step_env.is_enable == 0)
+ result = -1;
+
+
+ if (tp_id <= STEP_TP_NO_DEFINE || tp_id >= g_step_drv_type_def[drv_type].tp_max) {
+ pr_err("STEP failed: Do actions from tp_id: %d\n", tp_id);
+ result = -1;
+ //} else if (list_empty(&g_infra_step_env.actions[tp_id].list)) {
+ } else if (list_empty(&g_step_drv_type_def[drv_type].action_list[tp_id].list)) {
+ result = -1;
+ }
+
+ if (result == 0) {
+ conninfra_step_print_trigger_time(tp_id, reason);
+ _conninfra_step_do_actions(&g_step_drv_type_def[drv_type].action_list[tp_id]);
+ }
+
+ up_read(&g_infra_step_env.init_rwsem);
+ }
+}
+
+static int conninfra_step_write_action(struct step_action_list *p_list, enum step_drv_type drv_type,
+ enum step_action_id act_id, int param_num, char *params[])
+{
+ struct step_action *p_action;
+
+ if (p_list == NULL) {
+ pr_err("STEP failed: p_list is null\n");
+ return -1;
+ }
+
+ p_action = conninfra_step_create_action(drv_type, act_id, param_num, params);
+ if (p_action != NULL) {
+ list_add_tail(&(p_action->list), &(p_list->list));
+ return 0;
+ }
+
+ return -1;
+}
+
+static int conninfra_step_operator_result_greater(int l_val, int r_val)
+{
+ return (l_val > r_val);
+}
+
+static int conninfra_step_operator_result_greater_equal(int l_val, int r_val)
+{
+ return (l_val >= r_val);
+}
+
+static int conninfra_step_operator_result_less(int l_val, int r_val)
+{
+ return (l_val < r_val);
+}
+
+static int conninfra_step_operator_result_less_equal(int l_val, int r_val)
+{
+ return (l_val <= r_val);
+}
+
+static int conninfra_step_operator_result_equal(int l_val, int r_val)
+{
+ return (l_val == r_val);
+}
+
+static int conninfra_step_operator_result_not_equal(int l_val, int r_val)
+{
+ return (l_val != r_val);
+}
+
+static int conninfra_step_operator_result_and(int l_val, int r_val)
+{
+ return (l_val && r_val);
+}
+
+static int conninfra_step_operator_result_or(int l_val, int r_val)
+{
+ return (l_val || r_val);
+}
+
+
+void conninfra_step_create_emi_cb(int mode, int write,
+ unsigned int begin, unsigned int mask, unsigned int reg_id) {
+}
+
+static int conninfra_step_do_write_register_action(struct step_register_info *p_reg_info,
+ STEP_DO_EXTRA func_do_extra)
+{
+ phys_addr_t phy_addr;
+ void __iomem *p_addr = NULL;
+
+ phy_addr = p_reg_info->address + p_reg_info->offset;
+
+ if (phy_addr & 0x3) {
+ pr_err("STEP failed: phy_addr(0x%08x) page failed\n", phy_addr);
+ return -1;
+ }
+
+ p_addr = ioremap_nocache(phy_addr, 0x4);
+ if (p_addr) {
+ CONSYS_REG_WRITE_MASK((unsigned int *)p_addr, p_reg_info->value, p_reg_info->mask);
+ pr_info(
+ "STEP show: reg write Phy addr(0x%08x): 0x%08x\n",
+ (unsigned int)phy_addr, CONSYS_REG_READ(p_addr));
+ if (func_do_extra != NULL)
+ func_do_extra(1, CONSYS_REG_READ(p_addr));
+ iounmap(p_addr);
+ } else {
+ pr_err("STEP failed: ioremap(0x%08x) is NULL\n", phy_addr);
+ return -1;
+ }
+ return 0;
+}
+
+static void _conninfra_step_do_read_register_action(struct step_register_info *p_reg_info,
+ STEP_DO_EXTRA func_do_extra, char *info, int value)
+{
+ int i;
+
+ for (i = 0; i < p_reg_info->times; i++) {
+ if (i > 0)
+ conninfra_step_sleep_or_delay(p_reg_info->delay_time);
+
+ if (p_reg_info->output_mode == STEP_OUTPUT_REGISTER) {
+ g_infra_step_env.temp_register[p_reg_info->temp_reg_id] = value & p_reg_info->mask;
+
+ pr_info("[%s] value=[%d] mask=[%d]", __func__, value, p_reg_info->mask);
+ } else
+ pr_info("%s", info);
+
+ if (func_do_extra != NULL)
+ func_do_extra(1, value);
+ }
+}
+
+static int conninfra_step_do_read_register_action(struct step_register_info *p_reg_info,
+ STEP_DO_EXTRA func_do_extra)
+{
+ phys_addr_t phy_addr;
+ void __iomem *p_addr = NULL;
+ char buf[128];
+
+ phy_addr = p_reg_info->address + p_reg_info->offset;
+
+ if (phy_addr & 0x3) {
+ pr_err("STEP failed: phy_addr(0x%08x) page failed\n", phy_addr);
+ return -1;
+ }
+
+ p_addr = ioremap_nocache(phy_addr, 0x4);
+ if (p_addr) {
+ sprintf(buf, "STEP show: reg read Phy addr(0x%08x): 0x%08x\n",
+ (unsigned int)phy_addr, CONSYS_REG_READ(p_addr));
+ _conninfra_step_do_read_register_action(p_reg_info, func_do_extra, buf,
+ CONSYS_REG_READ(p_addr));
+ iounmap(p_addr);
+ } else {
+ pr_err("STEP failed: ioremap(0x%08x) is NULL\n", phy_addr);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void conninfra_step_remove_emi_action(struct step_action *p_act)
+{
+ struct step_emi_action *p_emi_act = NULL;
+
+ p_emi_act = clist_entry_action(emi, p_act);
+ kfree(p_emi_act);
+}
+
+static void conninfra_step_remove_register_action(struct step_action *p_act)
+{
+ struct step_register_action *p_reg_act = NULL;
+
+ p_reg_act = clist_entry_action(register, p_act);
+ kfree(p_reg_act);
+}
+
+static void conninfra_step_remove_gpio_action(struct step_action *p_act)
+{
+ struct step_gpio_action *p_gpio_act = NULL;
+
+ p_gpio_act = clist_entry_action(gpio, p_act);
+ kfree(p_gpio_act);
+}
+
+static void conninfra_step_remove_periodic_dump_action(struct step_action *p_act)
+{
+ struct step_periodic_dump_action *p_pd = NULL;
+
+ p_pd = clist_entry_action(periodic_dump, p_act);
+ kfree(p_pd);
+}
+
+static void conninfra_step_remove_show_string_action(struct step_action *p_act)
+{
+ struct step_show_string_action *p_show = NULL;
+
+ p_show = clist_entry_action(show_string, p_act);
+ if (p_show->content != NULL)
+ kfree(p_show->content);
+
+ kfree(p_show);
+}
+
+static void conninfra_step_remove_sleep_action(struct step_action *p_act)
+{
+ struct step_sleep_action *p_sleep = NULL;
+
+ p_sleep = clist_entry_action(sleep, p_act);
+ kfree(p_sleep);
+}
+
+static void conninfra_step_remove_condition_action(struct step_action *p_act)
+{
+ struct step_condition_action *p_cond = NULL;
+
+ p_cond = clist_entry_action(condition, p_act);
+ kfree(p_cond);
+}
+
+static void conninfra_step_remove_value_action(struct step_action *p_act)
+{
+ struct step_value_action *p_val = NULL;
+
+ p_val = clist_entry_action(value, p_act);
+ kfree(p_val);
+}
+
+static void conninfra_step_remove_condition_emi_action(struct step_action *p_act)
+{
+ struct step_condition_emi_action *p_cond_emi_act = NULL;
+
+ p_cond_emi_act = clist_entry_action(condition_emi, p_act);
+ kfree(p_cond_emi_act);
+}
+
+static void conninfra_step_remove_condition_register_action(struct step_action *p_act)
+{
+ struct step_condition_register_action *p_cond_reg_act = NULL;
+
+ p_cond_reg_act = clist_entry_action(condition_register, p_act);
+ kfree(p_cond_reg_act);
+}
+
+static int _conninfra_step_do_emi_action(struct step_emi_info *p_emi_info, STEP_DO_EXTRA func_do_extra)
+{
+ unsigned char *p_emi_begin_addr = NULL, *p_emi_end_addr = NULL;
+ unsigned char __iomem *emi_base_addr = NULL;
+ unsigned int dis = 0, temp = 0, i = 0;
+ struct consys_emi_addr_info *emi_addr_info = NULL;
+
+ if (p_emi_info->is_write != 0) {
+ pr_err("STEP failed: Only support dump EMI region\n");
+ return -1;
+ }
+
+ if (p_emi_info->begin_offset > p_emi_info->end_offset) {
+ temp = p_emi_info->begin_offset;
+ p_emi_info->begin_offset = p_emi_info->end_offset;
+ p_emi_info->end_offset = temp;
+ }
+ dis = p_emi_info->end_offset - p_emi_info->begin_offset;
+
+ emi_base_addr = conninfra_step_get_emi_base_address();
+ if (emi_base_addr == NULL) {
+ pr_err("STEP failed: EMI base address is NULL\n");
+ return -1;
+ }
+
+ if (p_emi_info->begin_offset & 0x3) {
+ pr_err("STEP failed: begin offset(0x%08x) page failed\n",
+ p_emi_info->begin_offset);
+ return -1;
+ }
+
+ p_emi_begin_addr = conninfra_step_get_emi_virt_addr(emi_base_addr, p_emi_info->begin_offset);
+ p_emi_end_addr = conninfra_step_get_emi_virt_addr(emi_base_addr, p_emi_info->end_offset);
+ if (!p_emi_begin_addr) {
+ pr_err("STEP failed: Get NULL begin virtual address 0x%08x\n",
+ p_emi_info->begin_offset);
+ return -1;
+ }
+
+ if (!p_emi_end_addr) {
+ pr_err("STEP failed: Get NULL end virtual address 0x%08x\n",
+ p_emi_info->end_offset);
+ return -1;
+ }
+
+ for (i = 0; i < dis; i += 0x4) {
+ if (p_emi_info->output_mode == STEP_OUTPUT_REGISTER) {
+ g_infra_step_env.temp_register[p_emi_info->temp_reg_id] =
+ (CONSYS_REG_READ(p_emi_begin_addr + i) & p_emi_info->mask);
+ } else {
+ emi_addr_info = emi_mng_get_phy_addr();
+ //if (emi_mng_get_phy_addr(&phy_addr, &phy_size) != 0)
+ if (emi_addr_info == NULL)
+ pr_warn("STEP show: get phy addr fail");
+
+ pr_info("STEP show: EMI action, Phy address(0x%08x): 0x%08x\n",
+ (unsigned int) (emi_addr_info->emi_ap_phy_addr + p_emi_info->begin_offset + i),
+ CONSYS_REG_READ(p_emi_begin_addr + i));
+ }
+
+ if (func_do_extra != NULL)
+ func_do_extra(1, CONSYS_REG_READ(p_emi_begin_addr + i));
+ }
+
+ return 0;
+}
+
+static bool conninfra_step_reg_readable(struct step_register_info *p_reg_info)
+{
+ phys_addr_t phy_addr;
+ enum step_drv_type drv_type = p_reg_info->drv_type;
+
+ if (p_reg_info->address_type == 0) {
+ phy_addr = p_reg_info->address + p_reg_info->offset;
+ switch (drv_type) {
+ case STEP_DRV_TYPE_CONNINFRA:
+ return consys_reg_mng_reg_readable();
+ case STEP_DRV_TYPE_BT:
+ case STEP_DRV_TYPE_FM:
+ case STEP_DRV_TYPE_GPS:
+ case STEP_DRV_TYPE_WIFI:
+ if (g_step_drv_type_def[drv_type].drv_cb == NULL)
+ return 0;
+ return g_step_drv_type_def[drv_type].drv_cb->readable_cb(phy_addr);
+ default:
+ pr_err("STEP: reg readable drv type(%d) incorrect", drv_type);
+ };
+ } else {
+ return consys_reg_mng_reg_readable();
+ }
+ return 0;
+}
+
+int _conninfra_step_do_register_action(struct step_register_info *p_reg_info, STEP_DO_EXTRA func_do_extra)
+{
+ int ret = 0, r;
+
+ ret = conninfra_core_force_conninfra_wakeup();
+ if (ret) {
+ pr_err("STEP failed: wakeup conninfra fail\n");
+ return -3;
+ }
+
+ if (!conninfra_step_reg_readable(p_reg_info)) {
+ pr_err("STEP failed: register cannot read\n");
+ ret = -1;
+ goto err;
+ }
+
+ if (p_reg_info->is_write == 1)
+ ret = conninfra_step_do_write_register_action(p_reg_info, func_do_extra);
+ else
+ ret = conninfra_step_do_read_register_action(p_reg_info, func_do_extra);
+
+err:
+ r = conninfra_core_force_conninfra_sleep();
+ if (r)
+ pr_err("STEP failed: sleep conninfra fail\n");
+
+ return ret;
+}
+
+void conninfra_step_setup(void)
+{
+ if (!g_infra_step_env.is_setup) {
+ g_infra_step_env.is_setup = true;
+ init_rwsem(&g_infra_step_env.init_rwsem);
+ }
+}
+
+/*******************************************************************************
+ * I N T E R N A L F U N C T I O N S W I T H U T
+********************************************************************************/
+int conninfra_step_do_emi_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra)
+{
+ struct step_emi_action *p_emi_act = NULL;
+ struct step_emi_info *p_emi_info = NULL;
+
+ p_emi_act = clist_entry_action(emi, p_act);
+ p_emi_info = &p_emi_act->info;
+ return _conninfra_step_do_emi_action(p_emi_info, func_do_extra);
+}
+
+int conninfra_step_do_condition_emi_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra)
+{
+ struct step_condition_emi_action *p_cond_emi_act = NULL;
+ struct step_emi_info *p_emi_info = NULL;
+
+ p_cond_emi_act = clist_entry_action(condition_emi, p_act);
+ p_emi_info = &p_cond_emi_act->info;
+
+ if (g_infra_step_env.temp_register[p_cond_emi_act->cond_reg_id] == 0) {
+ pr_info("STEP show: Dont do emi, condition %c%d is %d\n",
+ STEP_TEMP_REGISTER_SYMBOL, p_emi_info->temp_reg_id,
+ g_infra_step_env.temp_register[p_cond_emi_act->cond_reg_id]);
+ return -1;
+ }
+
+ return _conninfra_step_do_emi_action(p_emi_info, func_do_extra);
+}
+
+int conninfra_step_do_register_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra)
+{
+ struct step_register_action *p_reg_act = NULL;
+ struct step_register_info *p_reg_info = NULL;
+
+ p_reg_act = clist_entry_action(register, p_act);
+ p_reg_info = &p_reg_act->info;
+
+ return _conninfra_step_do_register_action(p_reg_info, func_do_extra);
+}
+
+int conninfra_step_do_condition_register_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra)
+{
+ struct step_condition_register_action *p_cond_reg_act = NULL;
+ struct step_register_info *p_reg_info = NULL;
+
+ p_cond_reg_act = clist_entry_action(condition_register, p_act);
+ p_reg_info = &p_cond_reg_act->info;
+
+ if (g_infra_step_env.temp_register[p_cond_reg_act->cond_reg_id] == 0) {
+ pr_info("STEP show: Dont do register, condition %c%d is %d\n",
+ STEP_TEMP_REGISTER_SYMBOL, p_reg_info->temp_reg_id,
+ g_infra_step_env.temp_register[p_cond_reg_act->cond_reg_id]);
+ return -1;
+ }
+
+ return _conninfra_step_do_register_action(p_reg_info, func_do_extra);
+}
+
+int conninfra_step_do_gpio_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra)
+{
+ struct step_gpio_action *p_gpio_act = NULL;
+
+ p_gpio_act = clist_entry_action(gpio, p_act);
+ if (p_gpio_act->is_write == 1) {
+ pr_err("STEP failed: Only support dump GPIO\n");
+ return -1;
+ }
+
+#ifdef KERNEL_gpio_dump_regs_range
+ KERNEL_gpio_dump_regs_range(p_gpio_act->pin_symbol, p_gpio_act->pin_symbol);
+#else
+ pr_info("STEP show: No support gpio dump\n");
+#endif
+ if (func_do_extra != NULL)
+ func_do_extra(0);
+
+ return 0;
+}
+
+int conninfra_step_do_periodic_dump_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra)
+{
+ struct step_periodic_dump_action *p_pd_act = NULL;
+
+ p_pd_act = clist_entry_action(periodic_dump, p_act);
+ if (p_pd_act->pd_entry->is_enable == 0) {
+ pr_info("STEP show: Start periodic dump(%d ms)\n",
+ p_pd_act->pd_entry->expires_ms);
+ conninfra_step_start_work(p_pd_act->pd_entry);
+ p_pd_act->pd_entry->is_enable = 1;
+ }
+
+ if (func_do_extra != NULL)
+ func_do_extra(0);
+
+ return 0;
+}
+
+int conninfra_step_do_show_string_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra)
+{
+ struct step_show_string_action *p_show_act = NULL;
+
+ p_show_act = clist_entry_action(show_string, p_act);
+
+ pr_info("STEP show: %s\n", p_show_act->content);
+
+ if (func_do_extra != NULL)
+ func_do_extra(1, p_show_act->content);
+
+ return 0;
+}
+
+int conninfra_step_do_sleep_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra)
+{
+ struct step_sleep_action *p_sleep_act = NULL;
+
+ p_sleep_act = clist_entry_action(sleep, p_act);
+
+ conninfra_step_sleep_or_delay(p_sleep_act->ms);
+
+ if (func_do_extra != NULL)
+ func_do_extra(0);
+
+ return 0;
+}
+
+int conninfra_step_do_condition_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra)
+{
+ struct step_condition_action *p_cond_act = NULL;
+ int result, l_val, r_val;
+
+ p_cond_act = clist_entry_action(condition, p_act);
+
+ l_val = g_infra_step_env.temp_register[p_cond_act->l_temp_reg_id];
+
+ if (p_cond_act->mode == STEP_CONDITION_RIGHT_REGISTER)
+ r_val = g_infra_step_env.temp_register[p_cond_act->r_temp_reg_id];
+ else
+ r_val = p_cond_act->value;
+
+ if (conninfra_step_operator_result_map[p_cond_act->operator_id]) {
+ result = conninfra_step_operator_result_map[p_cond_act->operator_id] (l_val, r_val);
+ g_infra_step_env.temp_register[p_cond_act->result_temp_reg_id] = result;
+
+ pr_info("STEP show: Condition %d(%c%d) op %d(%c%d) => %d(%c%d)\n",
+ l_val, STEP_TEMP_REGISTER_SYMBOL, p_cond_act->l_temp_reg_id,
+ r_val, STEP_TEMP_REGISTER_SYMBOL, p_cond_act->r_temp_reg_id,
+ result, STEP_TEMP_REGISTER_SYMBOL, p_cond_act->result_temp_reg_id);
+ } else {
+ pr_err("STEP failed: operator no define id: %d\n", p_cond_act->operator_id);
+ }
+
+ if (func_do_extra != NULL)
+ func_do_extra(1, g_infra_step_env.temp_register[p_cond_act->result_temp_reg_id]);
+
+ return 0;
+}
+
+int conninfra_step_do_value_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra)
+{
+ struct step_value_action *p_val_act = NULL;
+
+ p_val_act = clist_entry_action(value, p_act);
+
+ g_infra_step_env.temp_register[p_val_act->temp_reg_id] = p_val_act->value;
+
+ if (func_do_extra != NULL)
+ func_do_extra(1, g_infra_step_env.temp_register[p_val_act->temp_reg_id]);
+
+ return 0;
+}
+
+struct step_action *conninfra_step_create_action(enum step_drv_type drv_type, enum step_action_id act_id,
+ int param_num, char *params[])
+{
+ struct step_action *p_act = NULL;
+
+ if (act_id <= STEP_ACTION_INDEX_NO_DEFINE || act_id >= STEP_ACTION_INDEX_MAX) {
+ pr_err("STEP failed: Create action id: %d\n", act_id);
+ return NULL;
+ }
+
+ if (conninfra_step_action_map[act_id].func_create_action != NULL)
+ p_act = conninfra_step_action_map[act_id].func_create_action(drv_type, param_num, params);
+ else
+ pr_err("STEP failed: Create no define id: %d\n", act_id);
+
+ if (p_act != NULL)
+ p_act->action_id = act_id;
+
+ return p_act;
+}
+
+int conninfra_step_init_pd_env(void)
+{
+ g_infra_step_env.pd_struct.step_pd_wq = create_workqueue(STEP_PERIODIC_DUMP_WORK_QUEUE);
+ if (!g_infra_step_env.pd_struct.step_pd_wq) {
+ pr_err("create_workqueue fail\n");
+ return -1;
+ }
+ pr_info("[%s] step_pd_wq [%p]", __func__, g_infra_step_env.pd_struct.step_pd_wq);
+ INIT_LIST_HEAD(&g_infra_step_env.pd_struct.pd_list);
+
+ return 0;
+}
+
+int conninfra_step_deinit_pd_env(void)
+{
+ struct step_pd_entry *p_current;
+ struct step_pd_entry *p_next;
+
+ if (!g_infra_step_env.pd_struct.step_pd_wq)
+ return -1;
+
+ list_for_each_entry_safe(p_current, p_next, &g_infra_step_env.pd_struct.pd_list, list) {
+ cancel_delayed_work(&p_current->pd_work);
+ conninfra_step_clear_action_list(&p_current->action_list);
+ }
+ pr_info("[%s] step_pd_wq [%p]", __func__, g_infra_step_env.pd_struct.step_pd_wq);
+
+ destroy_workqueue(g_infra_step_env.pd_struct.step_pd_wq);
+ g_infra_step_env.pd_struct.step_pd_wq = NULL;
+
+ return 0;
+}
+
+struct step_pd_entry *conninfra_step_get_periodic_dump_entry(unsigned int expires)
+{
+ struct step_pd_entry *p_current;
+
+ if (expires <= 0)
+ return NULL;
+
+ if (!g_infra_step_env.pd_struct.step_pd_wq) {
+ if (conninfra_step_init_pd_env() != 0)
+ return NULL;
+ }
+
+ p_current = conninfra_step_create_periodic_dump_entry(expires);
+ if (p_current == NULL)
+ return NULL;
+ list_add_tail(&(p_current->list), &(g_infra_step_env.pd_struct.pd_list));
+
+ return p_current;
+}
+
+int conninfra_step_read_file(const char *file_name)
+{
+ int ret = -1;
+ const osal_firmware *p_step_cfg = NULL;
+
+ if (g_infra_step_env.is_enable == 1)
+ return 0;
+
+ if (0 == conninfra_step_get_cfg(file_name, (osal_firmware **) &p_step_cfg)) {
+ if (0 == conninfra_step_parse_data((const char *)p_step_cfg->data, p_step_cfg->size,
+ conninfra_step_write_action)) {
+ ret = 0;
+ } else {
+ ret = -1;
+ }
+
+ conninfra_step_release_cfg((osal_firmware **) &p_step_cfg);
+
+ return ret;
+ }
+
+ pr_info("STEP read file, %s is not exist\n", file_name);
+
+ return ret;
+}
+
+void conninfra_step_remove_action(struct step_action *p_act)
+{
+ if (p_act != NULL) {
+ if (p_act->action_id <= STEP_ACTION_INDEX_NO_DEFINE || p_act->action_id >= STEP_ACTION_INDEX_MAX) {
+ pr_err("STEP failed: Wrong action id %d\n", (int)p_act->action_id);
+ return;
+ }
+
+ if (conninfra_step_action_map[p_act->action_id].func_remove_action != NULL)
+ conninfra_step_action_map[p_act->action_id].func_remove_action(p_act);
+ } else {
+ pr_err("STEP failed: Action is NULL\n");
+ }
+}
+
+void conninfra_step_print_version(void)
+{
+ pr_info("STEP version: %d\n", STEP_VERSION);
+}
+
+/*******************************************************************************
+ * E X T E R N A L F U N C T I O N S
+********************************************************************************/
+
+void conninfra_step_init(void)
+{
+ if (g_infra_step_env.is_enable)
+ return;
+
+ conninfra_step_setup();
+ conninfra_step_init_list();
+ if (conninfra_step_read_file(STEP_CONFIG_NAME) == 0) {
+ conninfra_step_print_version();
+ down_write(&g_infra_step_env.init_rwsem);
+ g_infra_step_env.is_enable = 1;
+ up_write(&g_infra_step_env.init_rwsem);
+ }
+}
+
+void conninfra_step_deinit(void)
+{
+ down_write(&g_infra_step_env.init_rwsem);
+ g_infra_step_env.is_enable = 0;
+ up_write(&g_infra_step_env.init_rwsem);
+ conninfra_step_clear_list();
+ conninfra_step_unioremap_emi();
+ conninfra_step_deinit_pd_env();
+}
+
+void conninfra_step_do_actions(enum consys_conninfra_step_trigger_point tp_id)
+{
+#ifdef CFG_CONNINFRA_STEP
+ conninfra_step_do_actions_from_tp(STEP_DRV_TYPE_CONNINFRA, tp_id, NULL);
+#endif
+}
+
+void consys_step_bt_register(struct consys_step_register_cb *cb)
+{
+#ifdef CFG_CONNINFRA_STEP
+ g_step_drv_type_def[STEP_DRV_TYPE_BT].drv_cb = cb;
+#endif
+}
+
+void consys_step_bt_do_action(enum consys_bt_step_trigger_point tp_id)
+{
+#ifdef CFG_CONNINFRA_STEP
+ conninfra_step_do_actions_from_tp(STEP_DRV_TYPE_BT, tp_id, NULL);
+#endif
+}
+
+void consys_step_wf_register(struct consys_step_register_cb *cb)
+{
+#ifdef CFG_CONNINFRA_STEP
+ g_step_drv_type_def[STEP_DRV_TYPE_WIFI].drv_cb = cb;
+#endif
+}
+
+void consys_step_wf_do_action(enum consys_wf_step_trigger_point tp_id)
+{
+#ifdef CFG_CONNINFRA_STEP
+ conninfra_step_do_actions_from_tp(STEP_DRV_TYPE_WIFI, tp_id, NULL);
+#endif
+}
+
+void consys_step_gps_register(struct consys_step_register_cb *cb)
+{
+#ifdef CFG_CONNINFRA_STEP
+ g_step_drv_type_def[STEP_DRV_TYPE_GPS].drv_cb = cb;
+#endif
+}
+
+void consys_step_gps_do_action(enum consys_gps_step_trigger_point tp_id)
+{
+#ifdef CFG_CONNINFRA_STEP
+ conninfra_step_do_actions_from_tp(STEP_DRV_TYPE_GPS, tp_id, NULL);
+#endif
+}
+
+void consys_step_fm_register(struct consys_step_register_cb *cb)
+{
+#ifdef CFG_CONNINFRA_STEP
+ g_step_drv_type_def[STEP_DRV_TYPE_FM].drv_cb = cb;
+#endif
+}
+
+void consys_step_fm_do_action(enum consys_fm_step_trigger_point tp_id)
+{
+#ifdef CFG_CONNINFRA_STEP
+ conninfra_step_do_actions_from_tp(STEP_DRV_TYPE_FM, tp_id, NULL);
+#endif
+}
+
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/conninfra_step_parse.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/conninfra_step_parse.c
new file mode 100755
index 0000000..fd4d62f
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/conninfra_step_parse.c
@@ -0,0 +1,417 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <connectivity_build_in_adapter.h>
+
+#include <linux/firmware.h>
+#include <asm/delay.h>
+#include <linux/slab.h>
+
+#include "osal.h"
+#include "conninfra_step.h"
+#include "conninfra_step_parse_act.h"
+
+/*******************************************************************************
+ * F U N C T I O N D E C L A R A T I O N S
+********************************************************************************/
+
+static int conninfra_step_access_line_state_init(char *tok,
+ struct step_target_act_list_info *p_parse_info,
+ struct step_parse_line_data_param_info *p_parse_line_info);
+static int conninfra_step_access_line_state_tp(char *tok,
+ struct step_target_act_list_info *p_parse_info,
+ struct step_parse_line_data_param_info *p_parse_line_info);
+
+static int conninfra_step_access_line_state_tp_id(char *tok,
+ struct step_target_act_list_info *p_parse_info,
+ struct step_parse_line_data_param_info *p_parse_line_info);
+static int conninfra_step_access_line_state_at(char *tok,
+ struct step_target_act_list_info *p_parse_info,
+ struct step_parse_line_data_param_info *p_parse_line_info);
+static int conninfra_step_access_line_state_at_op(char *tok,
+ struct step_target_act_list_info *p_parse_info,
+ struct step_parse_line_data_param_info *p_parse_line_info);
+static int conninfra_step_access_line_state_pd(char *tok,
+ struct step_target_act_list_info *p_parse_info,
+ struct step_parse_line_data_param_info *p_parse_line_info);
+
+
+/*******************************************************************************
+ * D E F I N E
+********************************************************************************/
+#define STEP_EMI_ACT_INT (int)(*(int *)STEP_ACTION_NAME_EMI)
+#define STEP_REG_ACT_INT (int)(*(int *)STEP_ACTION_NAME_REGISTER)
+#define STEP_GPIO_ACT_INT (int)(*(int *)STEP_ACTION_NAME_GPIO)
+#define STEP_DISABLE_RESET_ACT_INT (int)(*(int *)STEP_ACTION_NAME_DISABLE_RESET)
+#define STEP_CHIP_RESET_ACT_INT (int)(*(int *)STEP_ACTION_NAME_CHIP_RESET)
+#define STEP_KEEP_WAKEUP_ACT_INT (int)(*(int *)STEP_ACTION_NAME_KEEP_WAKEUP)
+#define STEP_CANCEL_KEEP_WAKEUP_ACT_INT (int)(*(int *)STEP_ACTION_NAME_CANCEL_WAKEUP)
+#define STEP_SHOW_STRING_ACT_INT (int)(*(int *)STEP_ACTION_NAME_SHOW_STRING)
+#define STEP_SLEEP_ACT_INT (int)(*(int *)STEP_ACTION_NAME_SLEEP)
+#define STEP_CONDITION_ACT_INT (int)(*(int *)STEP_ACTION_NAME_CONDITION)
+#define STEP_VALUE_ACT_INT (int)(*(int *)STEP_ACTION_NAME_VALUE)
+#define STEP_CONDITION_EMI_ACT_INT (int)(*(int *)STEP_ACTION_NAME_CONDITION_EMI)
+#define STEP_CONDITION_REG_ACT_INT (int)(*(int *)STEP_ACTION_NAME_CONDITION_REGISTER)
+
+#define STEP_PARSE_LINE_STATE_INIT 0
+#define STEP_PARSE_LINE_STATE_TP 1
+#define STEP_PARSE_LINE_STATE_TP_ID 2
+#define STEP_PARSE_LINE_STATE_AT 3
+#define STEP_PARSE_LINE_STATE_AT_OP 4
+#define STEP_PARSE_LINE_STATE_PD_START 5
+#define STEP_PARSE_LINE_STATE_PD_END 6
+
+/*******************************************************************************
+ * P R I V A T E D A T A
+********************************************************************************/
+
+
+typedef int (*STEP_LINE_STATE) (char *,
+ struct step_target_act_list_info *, struct step_parse_line_data_param_info *);
+
+static const STEP_LINE_STATE conninfra_step_line_state_action_map[] = {
+ [STEP_PARSE_LINE_STATE_INIT] = conninfra_step_access_line_state_init,
+ [STEP_PARSE_LINE_STATE_TP] = conninfra_step_access_line_state_tp,
+ [STEP_PARSE_LINE_STATE_TP_ID] = conninfra_step_access_line_state_tp_id,
+ [STEP_PARSE_LINE_STATE_AT] = conninfra_step_access_line_state_at,
+ [STEP_PARSE_LINE_STATE_AT_OP] = conninfra_step_access_line_state_at_op,
+ [STEP_PARSE_LINE_STATE_PD_START] = conninfra_step_access_line_state_pd,
+};
+
+/*******************************************************************************
+ * I N T E R N A L F U N C T I O N S
+********************************************************************************/
+
+#define STEP_PARSE_LINE_RET_CONTINUE 0
+#define STEP_PARSE_LINE_RET_BREAK 1
+
+static void conninfra_step_set_line_state(int *p_state, int value)
+{
+ *p_state = value;
+}
+
+static unsigned char conninfra_step_to_upper(char str)
+{
+ if ((str >= 'a') && (str <= 'z'))
+ return str + ('A' - 'a');
+ else
+ return str;
+}
+
+static void conninfra_step_string_to_upper(char *tok)
+{
+ for (; *tok != '\0'; tok++)
+ *tok = conninfra_step_to_upper(*tok);
+}
+
+static int conninfra_step_get_int_from_four_char(char *str)
+{
+ unsigned char char_array[4];
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (*(str + i) == '\0')
+ return -1;
+
+ char_array[i] = conninfra_step_to_upper(*(str + i));
+ }
+
+ return *(int *)char_array;
+}
+
+
+
+static unsigned int conninfra_step_parse_tp_id(enum step_drv_type drv_type, char *str)
+{
+ long tp_id = STEP_TP_NO_DEFINE;
+
+ if (osal_strtol(str, 10, &tp_id)) {
+ pr_err("STEP failed: str to value %s\n", str);
+ return STEP_TP_NO_DEFINE;
+ }
+ if (tp_id <= STEP_TP_NO_DEFINE || tp_id >= g_step_drv_type_def[drv_type].tp_max)
+ return STEP_TP_NO_DEFINE;
+
+ return tp_id;
+}
+
+
+static int conninfra_step_parse_pd_expires(char *ptr)
+{
+ long expires_ms;
+
+ if (osal_strtol(ptr, 0, &expires_ms))
+ return -1;
+
+ return (int)expires_ms;
+}
+
+static int conninfra_step_parse_act_id(char *str)
+{
+ int str_to_int = STEP_ACTION_INDEX_NO_DEFINE;
+
+ if (str == NULL || str == '\0')
+ return STEP_ACTION_INDEX_NO_DEFINE;
+
+ str_to_int = conninfra_step_get_int_from_four_char(str);
+ if (str_to_int == STEP_EMI_ACT_INT)
+ return STEP_ACTION_INDEX_EMI;
+ else if (str_to_int == STEP_REG_ACT_INT)
+ return STEP_ACTION_INDEX_REGISTER;
+ else if (str_to_int == STEP_GPIO_ACT_INT)
+ return STEP_ACTION_INDEX_GPIO;
+ else if (str_to_int == STEP_SHOW_STRING_ACT_INT)
+ return STEP_ACTION_INDEX_SHOW_STRING;
+ else if (str_to_int == STEP_SLEEP_ACT_INT)
+ return STEP_ACTION_INDEX_SLEEP;
+ else if (str_to_int == STEP_CONDITION_ACT_INT)
+ return STEP_ACTION_INDEX_CONDITION;
+ else if (str_to_int == STEP_VALUE_ACT_INT)
+ return STEP_ACTION_INDEX_VALUE;
+ else if (str_to_int == STEP_CONDITION_EMI_ACT_INT)
+ return STEP_ACTION_INDEX_CONDITION_EMI;
+ else if (str_to_int == STEP_CONDITION_REG_ACT_INT)
+ return STEP_ACTION_INDEX_CONDITION_REGISTER;
+ else
+ return STEP_ACTION_INDEX_NO_DEFINE;
+
+}
+
+
+static int conninfra_step_access_line_state_init(char *tok,
+ struct step_target_act_list_info *p_parse_info,
+ struct step_parse_line_data_param_info *p_parse_line_info)
+{
+ conninfra_step_string_to_upper(tok);
+ if (osal_strcmp(tok, "[TP") == 0) {
+ conninfra_step_set_line_state(&p_parse_line_info->state, STEP_PARSE_LINE_STATE_TP);
+ return STEP_PARSE_LINE_RET_CONTINUE;
+ }
+
+ if (p_parse_info->tp_id == STEP_TP_NO_DEFINE) {
+ pr_err("STEP failed: Set trigger point first: %s\n", tok);
+ return STEP_PARSE_LINE_RET_BREAK;
+ }
+
+ if (osal_strcmp(tok, "[PD+]") == 0) {
+ conninfra_step_set_line_state(&p_parse_line_info->state, STEP_PARSE_LINE_STATE_PD_START);
+ return STEP_PARSE_LINE_RET_CONTINUE;
+ }
+
+ if (osal_strcmp(tok, "[PD-]") == 0) {
+ conninfra_step_set_line_state(&p_parse_line_info->state, STEP_PARSE_LINE_STATE_PD_END);
+ return STEP_PARSE_LINE_RET_BREAK;
+ }
+
+ if (osal_strcmp(tok, "[AT]") == 0) {
+ conninfra_step_set_line_state(&p_parse_line_info->state, STEP_PARSE_LINE_STATE_AT);
+ return STEP_PARSE_LINE_RET_CONTINUE;
+ }
+
+ return STEP_PARSE_LINE_RET_BREAK;
+}
+
+static int conninfra_step_drv_type(char *tok, enum step_drv_type *drv_type)
+{
+ int i;
+ const char *p;
+
+ for (i = 0; i < STEP_DRV_TYPE_MAX; i++) {
+ p = g_step_drv_type_def[i].drv_type_str;
+ if (!strncmp(tok, p, strlen(p))) {
+ *drv_type = (enum step_drv_type)i;
+ return strlen(p);
+ }
+ }
+ return -1;
+}
+
+static int conninfra_step_access_line_state_tp(char *tok,
+ struct step_target_act_list_info *p_parse_info,
+ struct step_parse_line_data_param_info *p_parse_line_info)
+{
+ int ret = 0;
+ enum step_drv_type drv_type = STEP_DRV_TYPE_NO_DEFINE;
+
+ conninfra_step_string_to_upper(tok);
+ if (p_parse_info->p_pd_entry != NULL) {
+ pr_err("STEP failed: Please add [PD-] after [PD+], tok = %s\n", tok);
+ p_parse_info->p_pd_entry = NULL;
+ }
+
+ ret = conninfra_step_drv_type(tok, &drv_type);
+ if (ret <= 0) {
+ pr_err("STEP failed: Trigger point format is wrong: %s\n", tok);
+ return STEP_PARSE_LINE_RET_BREAK;
+ }
+
+ p_parse_info->drv_type = drv_type;
+ conninfra_step_set_line_state(&p_parse_line_info->state, STEP_PARSE_LINE_STATE_TP_ID);
+
+ return STEP_PARSE_LINE_RET_CONTINUE;
+}
+
+static int conninfra_step_access_line_state_tp_id(char *tok,
+ struct step_target_act_list_info *p_parse_info,
+ struct step_parse_line_data_param_info *p_parse_line_info)
+{
+ char *pch;
+ enum step_drv_type drv_type = p_parse_info->drv_type;
+
+ if (p_parse_info->p_pd_entry != NULL) {
+ pr_err("STEP failed: Please add [PD-] after [PD+], tok = %s\n", tok);
+ p_parse_info->p_pd_entry = NULL;
+ }
+
+ pch = osal_strchr(tok, ']');
+ if (pch == NULL) {
+ pr_err("STEP failed: Trigger point format is wrong: %s\n", tok);
+ } else {
+ *pch = '\0';
+ p_parse_info->tp_id = conninfra_step_parse_tp_id(drv_type, tok);
+ p_parse_info->p_target_list = conninfra_step_get_tp_list(drv_type, p_parse_info->tp_id);
+
+ if (p_parse_info->tp_id == STEP_TP_NO_DEFINE)
+ pr_err("STEP failed: Trigger point no define: %s\n", tok);
+ }
+
+ return STEP_PARSE_LINE_RET_BREAK;
+}
+
+static int conninfra_step_access_line_state_at(char *tok,
+ struct step_target_act_list_info *p_parse_info,
+ struct step_parse_line_data_param_info *p_parse_line_info)
+{
+ p_parse_line_info->act_id = conninfra_step_parse_act_id(tok);
+ if (p_parse_line_info->act_id == STEP_ACTION_INDEX_NO_DEFINE) {
+ pr_err("STEP failed: Action no define: %s\n", tok);
+ return STEP_PARSE_LINE_RET_BREAK;
+ }
+ conninfra_step_set_line_state(&p_parse_line_info->state, STEP_PARSE_LINE_STATE_AT_OP);
+
+ return STEP_PARSE_LINE_RET_CONTINUE;
+}
+
+static int conninfra_step_access_line_state_at_op(char *tok,
+ struct step_target_act_list_info *p_parse_info,
+ struct step_parse_line_data_param_info *p_parse_line_info)
+{
+ p_parse_line_info->act_params[p_parse_line_info->param_index] = tok;
+ (p_parse_line_info->param_index)++;
+
+ if (p_parse_line_info->param_index >= STEP_PARAMETER_SIZE) {
+ pr_err("STEP failed: Param too much");
+ return STEP_PARSE_LINE_RET_BREAK;
+ }
+
+ return STEP_PARSE_LINE_RET_CONTINUE;
+}
+
+static int conninfra_step_access_line_state_pd(char *tok,
+ struct step_target_act_list_info *p_parse_info,
+ struct step_parse_line_data_param_info *p_parse_line_info)
+{
+ int pd_ms = -1;
+
+ pd_ms = conninfra_step_parse_pd_expires(tok);
+ if (pd_ms == -1)
+ pr_err("STEP failed: PD ms failed %s\n", tok);
+
+ if (p_parse_info->p_pd_entry != NULL)
+ pr_err("STEP failed: Please add [PD-] after [PD+], tok = %s\n", tok);
+
+ p_parse_info->p_pd_entry = conninfra_step_get_periodic_dump_entry(pd_ms);
+ if (p_parse_info->p_pd_entry == NULL)
+ pr_err("STEP failed: p_pd_entry create fail\n");
+ else
+ p_parse_info->p_target_list = &(p_parse_info->p_pd_entry->action_list);
+
+ return STEP_PARSE_LINE_RET_BREAK;
+}
+
+
+
+
+static void conninfra_step_parse_line_data(char *line, struct step_target_act_list_info *p_parse_info,
+ STEP_WRITE_ACT_TO_LIST func_act_to_list)
+{
+ char *tok;
+ int line_ret = STEP_PARSE_LINE_RET_BREAK;
+ struct step_parse_line_data_param_info parse_line_info;
+
+ parse_line_info.param_index = 0;
+ parse_line_info.act_id = STEP_ACTION_INDEX_NO_DEFINE;
+ parse_line_info.state = STEP_PARSE_LINE_STATE_INIT;
+
+ while ((tok = osal_strsep(&line, " \t")) != NULL) {
+ if (*tok == '\0')
+ continue;
+ if (osal_strcmp(tok, "//") == 0)
+ break;
+
+ if (conninfra_step_line_state_action_map[parse_line_info.state] != NULL) {
+ line_ret = conninfra_step_line_state_action_map[parse_line_info.state] (tok,
+ p_parse_info, &parse_line_info);
+ }
+
+ if (line_ret == STEP_PARSE_LINE_RET_CONTINUE)
+ continue;
+ else
+ break;
+ }
+
+ if (parse_line_info.state == STEP_PARSE_LINE_STATE_AT_OP) {
+ func_act_to_list(p_parse_info->p_target_list, p_parse_info->drv_type,
+ parse_line_info.act_id, parse_line_info.param_index, parse_line_info.act_params);
+ } else if (parse_line_info.state == STEP_PARSE_LINE_STATE_PD_END) {
+ p_parse_info->p_target_list = conninfra_step_get_tp_list(p_parse_info->drv_type, p_parse_info->tp_id);
+ if (p_parse_info->p_pd_entry != NULL) {
+ parse_line_info.act_params[0] = (char*)p_parse_info->p_pd_entry;
+ func_act_to_list(p_parse_info->p_target_list, p_parse_info->drv_type,
+ STEP_ACTION_INDEX_PERIODIC_DUMP, parse_line_info.param_index,
+ parse_line_info.act_params);
+ p_parse_info->p_pd_entry = NULL;
+ }
+ }
+}
+
+
+
+int conninfra_step_parse_data(const char *in_buf, unsigned int size,
+ STEP_WRITE_ACT_TO_LIST func_act_to_list)
+{
+ struct step_target_act_list_info parse_info;
+ char *buf, *tmp_buf;
+ char *line;
+
+ buf = osal_malloc(size + 1);
+ if (!buf) {
+ pr_err("STEP failed: Buf malloc\n");
+ return -1;
+ }
+
+ osal_memcpy(buf, (char *)in_buf, size);
+ buf[size] = '\0';
+
+ parse_info.drv_type = STEP_DRV_TYPE_NO_DEFINE;
+ parse_info.tp_id = STEP_TP_NO_DEFINE;
+ parse_info.p_target_list = NULL;
+ parse_info.p_pd_entry = NULL;
+
+ tmp_buf = buf;
+ while ((line = osal_strsep(&tmp_buf, "\r\n")) != NULL)
+ conninfra_step_parse_line_data(line, &parse_info, func_act_to_list);
+
+ osal_free(buf);
+
+ return 0;
+}
+
+
+
+/*******************************************************************************
+ * I N T E R N A L F U N C T I O N S W I T H U T
+********************************************************************************/
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/conninfra_step_parse_act.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/conninfra_step_parse_act.c
new file mode 100755
index 0000000..d77ab73
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/conninfra_step_parse_act.c
@@ -0,0 +1,781 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <connectivity_build_in_adapter.h>
+
+#include <linux/firmware.h>
+#include <asm/delay.h>
+#include <linux/slab.h>
+
+#include "osal.h"
+#include "conninfra_step.h"
+#include "consys_hw.h"
+#include "consys_reg_mng.h"
+
+/*******************************************************************************
+ * F U N C T I O N D E C L A R A T I O N S
+********************************************************************************/
+
+
+/*******************************************************************************
+ * D E F I N E
+********************************************************************************/
+
+/*******************************************************************************
+ * P R I V A T E D A T A
+********************************************************************************/
+
+/*******************************************************************************
+ * I N T E R N A L F U N C T I O N S
+********************************************************************************/
+
+/*************** for debug ************************/
+/*************** for debug ************************/
+
+static int conninfra_step_parse_number_with_symbol(char *ptr, long *value)
+{
+ int ret = STEP_VALUE_INFO_UNKNOWN;
+
+ if (*ptr == '#') {
+ if (osal_strtol(ptr + 1, 10, value)) {
+ pr_err("STEP failed: str to value %s\n", ptr);
+ ret = STEP_VALUE_INFO_UNKNOWN;
+ } else {
+ ret = STEP_VALUE_INFO_SYMBOL_REG_BASE;
+ }
+ } else if (*ptr == '$') {
+ if (osal_strtol(ptr + 1, 10, value)) {
+ pr_err("STEP failed: str to value %s\n", ptr);
+ ret = STEP_VALUE_INFO_UNKNOWN;
+ } else {
+ ret = STEP_VALUE_INFO_SYMBOL_TEMP_REG;
+ }
+ } else {
+ if (osal_strtol(ptr, 0, value)) {
+ pr_err("STEP failed: str to value %s\n", ptr);
+ ret = STEP_VALUE_INFO_UNKNOWN;
+ } else {
+ ret = STEP_VALUE_INFO_NUMBER;
+ }
+ }
+
+ return ret;
+}
+
+static enum step_condition_operator_id conninfra_step_parse_operator_id(char *ptr)
+{
+ if (osal_strcmp(ptr, ">") == 0)
+ return STEP_OPERATOR_GREATER;
+ else if (osal_strcmp(ptr, ">=") == 0)
+ return STEP_OPERATOR_GREATER_EQUAL;
+ else if (osal_strcmp(ptr, "<") == 0)
+ return STEP_OPERATOR_LESS;
+ else if (osal_strcmp(ptr, "<=") == 0)
+ return STEP_OPERATOR_LESS_EQUAL;
+ else if (osal_strcmp(ptr, "==") == 0)
+ return STEP_OPERATOR_EQUAL;
+ else if (osal_strcmp(ptr, "!=") == 0)
+ return STEP_OPERATOR_NOT_EQUAL;
+ else if (osal_strcmp(ptr, "&&") == 0)
+ return STEP_OPERATOR_AND;
+ else if (osal_strcmp(ptr, "||") == 0)
+ return STEP_OPERATOR_OR;
+
+ return STEP_OPERATOR_MAX;
+}
+
+
+
+
+static unsigned int conninfra_step_parse_temp_register_id(char *ptr)
+{
+ unsigned long res;
+ int num_sym;
+
+ num_sym = conninfra_step_parse_number_with_symbol(ptr, &res);
+
+ if (num_sym == STEP_VALUE_INFO_SYMBOL_TEMP_REG)
+ return res;
+ else
+ return STEP_TEMP_REGISTER_SIZE;
+}
+
+static char *conninfra_step_save_params_msg(int num, char *params[], char *buf, int buf_size)
+{
+ int i, len, temp;
+
+ for (i = 0, len = 0; i < num; i++) {
+ if (params[i] == NULL)
+ break;
+
+ temp = osal_strlen(params[i]) + 1;
+
+ if ((len + temp) >= (buf_size - 1))
+ break;
+
+ len += temp;
+ osal_strncat(buf, params[i], temp);
+ osal_strncat(buf, " ", 1);
+ }
+ osal_strncat(buf, "\0", 1);
+
+ return buf;
+}
+
+static int conninfra_step_parse_register_address(struct step_reg_addr_info *p_reg_addr, char *ptr, long offset)
+{
+ unsigned long res;
+ unsigned int symbol;
+ int num_sym;
+
+ num_sym = conninfra_step_parse_number_with_symbol(ptr, &res);
+
+ if (num_sym == STEP_VALUE_INFO_SYMBOL_REG_BASE) {
+ symbol = (unsigned int) res;
+
+ res = consys_reg_mng_validate_idx_n_offset(symbol-1, offset);
+ if (res == 0) {
+ pr_err("STEP failed: validate symbol(%d) and ofsset(%d) fail. %s\n",
+ symbol, offset, ptr);
+ return -1;
+ }
+ res = consys_reg_mng_get_phy_addr_by_idx(symbol - 1);
+ if (res == 0) {
+ pr_err("STEP failed: validate symbol(%d) and ofsset(%d) fail. %s\n",
+ symbol, offset, ptr);
+ return -1;
+ }
+
+ p_reg_addr->address = res;
+ p_reg_addr->address_type = symbol;
+ } else if (num_sym == STEP_VALUE_INFO_NUMBER) {
+ p_reg_addr->address = res;
+ p_reg_addr->address_type = 0;
+ } else {
+ pr_err("STEP failed: number with symbol parse fail %s\n", ptr);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+
+static void conninfra_step_create_emi_output_log(struct step_emi_info *p_emi_info, int write,
+ unsigned int begin, unsigned int end)
+{
+ p_emi_info->is_write = write;
+ p_emi_info->begin_offset = begin;
+ p_emi_info->end_offset = end;
+ p_emi_info->output_mode = STEP_OUTPUT_LOG;
+}
+
+static void conninfra_step_create_emi_output_register(struct step_emi_info *p_emi_info, int write,
+ unsigned int begin, unsigned int mask, unsigned int reg_id)
+{
+ p_emi_info->is_write = write;
+ p_emi_info->begin_offset = begin;
+ p_emi_info->end_offset = begin + 0x4;
+ p_emi_info->mask = mask;
+ p_emi_info->temp_reg_id = reg_id;
+ p_emi_info->output_mode = STEP_OUTPUT_REGISTER;
+}
+
+static int _conninfra_step_create_emi_action(struct step_emi_info *p_emi_info, int param_num, char *params[])
+{
+ long write, begin, end;
+ unsigned int reg_id;
+ char buf[128] = "";
+ long mask = 0xFFFFFFFF;
+
+ if (param_num < 3) {
+ pr_err("STEP failed: Init EMI to log param(%d): %s\n", param_num,
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return -1;
+ }
+
+ if (osal_strtol(params[0], 0, &write) ||
+ osal_strtol(params[1], 0, &begin)) {
+ pr_err("STEP failed: str to value %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return -1;
+ }
+
+ if (*params[(param_num - 1)] == STEP_TEMP_REGISTER_SYMBOL) {
+ reg_id = conninfra_step_parse_temp_register_id(params[(param_num - 1)]);
+ if (reg_id >= STEP_PARAMETER_SIZE) {
+ pr_err("STEP failed: register id failed: %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return -1;
+ }
+
+ if (param_num > 3) {
+ if (osal_strtol(params[2], 0, &mask)) {
+ pr_err("STEP failed: str to value %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return -1;
+ }
+ }
+
+ conninfra_step_create_emi_output_register(p_emi_info, write, begin, mask, reg_id);
+ } else {
+ if (osal_strtol(params[2], 0, &end)) {
+ pr_err("STEP failed: str to value %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return -1;
+ }
+ conninfra_step_create_emi_output_log(p_emi_info, write, begin, end);
+ }
+
+ return 0;
+}
+
+
+/*
+ * Support:
+ * _EMI | R(0) | Begin offset | End offset
+ * _EMI | R(0) | Begin offset | mask | Output temp register ID ($)
+ * _EMI | R(0) | Begin offset | Output temp register ID ($)
+ */
+struct step_action *conninfra_step_create_emi_action(enum step_drv_type drv_type, int param_num, char *params[])
+{
+ struct step_emi_action *p_emi_act = NULL;
+ struct step_emi_info *p_emi_info = NULL;
+ int ret;
+
+ p_emi_act = kzalloc(sizeof(struct step_emi_action), GFP_KERNEL);
+ if (p_emi_act == NULL) {
+ pr_err("STEP failed: kzalloc emi fail\n");
+ return NULL;
+ }
+
+ p_emi_info = &p_emi_act->info;
+ ret = _conninfra_step_create_emi_action(p_emi_info, param_num, params);
+
+ if (ret != 0) {
+ kfree(p_emi_act);
+ return NULL;
+ }
+
+ return &(p_emi_act->base);
+}
+
+static void conninfra_step_create_read_register_output_register(struct step_register_info *p_reg_info,
+ struct step_reg_addr_info reg_addr_info, unsigned int offset, int mask, unsigned int reg_id)
+{
+ p_reg_info->is_write = 0;
+ p_reg_info->address_type = reg_addr_info.address_type;
+ p_reg_info->address = reg_addr_info.address;
+ p_reg_info->offset = offset;
+ p_reg_info->times = 1;
+ p_reg_info->delay_time = 0;
+ p_reg_info->mask = mask;
+ p_reg_info->temp_reg_id = reg_id;
+ p_reg_info->output_mode = STEP_OUTPUT_REGISTER;
+}
+
+static void conninfra_step_create_read_register_output_log(struct step_register_info *p_reg_info,
+ struct step_reg_addr_info reg_addr_info, unsigned int offset, unsigned int times, unsigned int delay_time)
+{
+ p_reg_info->is_write = 0;
+ p_reg_info->address_type = reg_addr_info.address_type;
+ p_reg_info->address = reg_addr_info.address;
+ p_reg_info->offset = offset;
+ p_reg_info->times = times;
+ p_reg_info->delay_time = delay_time;
+ p_reg_info->output_mode = STEP_OUTPUT_LOG;
+}
+
+static void conninfra_step_create_write_register_action(struct step_register_info *p_reg_info,
+ struct step_reg_addr_info reg_addr_info, unsigned int offset, int value, int mask)
+{
+ p_reg_info->is_write = 1;
+ p_reg_info->address_type = reg_addr_info.address_type;
+ p_reg_info->address = reg_addr_info.address;
+ p_reg_info->offset = offset;
+ p_reg_info->value = value;
+ p_reg_info->mask = mask;
+}
+
+static int _conninfra_step_create_register_action(struct step_register_info *p_reg_info,
+ int param_num, char *params[])
+{
+ long write;
+ struct step_reg_addr_info reg_addr_info;
+ long offset, value;
+ unsigned int reg_id = 0;
+ char buf[128] = "";
+ long mask = 0xFFFFFFFF;
+ long times = 1;
+ long delay_time = 0;
+
+ if (param_num < 4) {
+ pr_err("STEP failed: Register no params\n");
+ return -1;
+ }
+
+ if (osal_strtol(params[0], 0, &write)) {
+ pr_err("STEP failed: str to value %s\n",
+ params[0]);
+ return -1;
+ }
+
+ if (osal_strtol(params[2], 0, &offset)) {
+ pr_err("STEP failed: str to value %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return -1;
+ }
+
+ pr_info("[%s] == offset=[%x]", __func__, offset);
+
+ if (conninfra_step_parse_register_address(®_addr_info, params[1], offset) == -1) {
+ pr_err("STEP failed: init write register symbol: %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return -1;
+ }
+
+ if (write == 0) {
+ if (*params[(param_num - 1)] == STEP_TEMP_REGISTER_SYMBOL) {
+ reg_id = conninfra_step_parse_temp_register_id(params[(param_num - 1)]);
+ if (reg_id >= STEP_PARAMETER_SIZE) {
+ pr_err("STEP failed: register id failed: %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return -1;
+ }
+
+ if (param_num > 4) {
+ if (osal_strtol(params[3], 0, &mask)) {
+ pr_err("STEP failed: str to value %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return -1;
+ }
+ }
+
+ conninfra_step_create_read_register_output_register(p_reg_info, reg_addr_info, offset, mask, reg_id);
+ } else {
+ if (param_num < 5 ||
+ osal_strtol(params[3], 0, ×) ||
+ osal_strtol(params[4], 0, &delay_time)) {
+ pr_err("STEP failed: str to value %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return -1;
+ }
+
+ conninfra_step_create_read_register_output_log(p_reg_info, reg_addr_info, offset, times, delay_time);
+ }
+ } else {
+ if (osal_strtol(params[3], 0, &value)) {
+ pr_err("STEP failed: str to value %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return -1;
+ }
+
+ if (param_num > 4) {
+ if (osal_strtol(params[4], 0, &mask)) {
+ pr_err("STEP failed: str to value %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return -1;
+ }
+ }
+
+ conninfra_step_create_write_register_action(p_reg_info, reg_addr_info, offset, value, mask);
+ }
+
+ return 0;
+}
+
+
+/*
+ * Support:
+ * _REG | R(0) | Pre-define base address ID | offset | times | delay time(ms)
+ * _REG | R(0) | AP Physical address | offset | times | delay time(ms)
+ * _REG | R(0) | Pre-define base address ID | offset | mask | Output temp register ID ($)
+ * _REG | R(0) | AP Physical address | offset | mask | Output temp register ID ($)
+ * _REG | R(0) | Pre-define base address ID | offset | Output temp register ID ($)
+ * _REG | R(0) | AP Physical address | offset | Output temp register ID ($)
+ * _REG | W(1) | AP Physical address | offset | value
+ * _REG | W(1) | AP Physical address | offset | value
+ * _REG | W(1) | AP Physical address | offset | value | mask
+ * _REG | W(1) | AP Physical address | offset | value | mask
+ */
+struct step_action *conninfra_step_create_register_action(enum step_drv_type drv_type, int param_num, char *params[])
+{
+ struct step_register_action *p_reg_act = NULL;
+ struct step_register_info *p_reg_info;
+ int ret;
+
+ p_reg_act = kzalloc(sizeof(struct step_register_action), GFP_KERNEL);
+ if (p_reg_act == NULL) {
+ pr_err("STEP failed: kzalloc register fail\n");
+ return NULL;
+ }
+
+ p_reg_info = &p_reg_act->info;
+ ret = _conninfra_step_create_register_action(p_reg_info, param_num, params);
+
+ if (ret != 0) {
+ kfree(p_reg_act);
+ return NULL;
+ }
+ p_reg_info->drv_type = drv_type;
+
+ return &(p_reg_act->base);
+}
+
+
+/*
+ * Support:
+ * GPIO | R(0) | Pin number
+ */
+struct step_action *conninfra_step_create_gpio_action(enum step_drv_type drv_type, int param_num, char *params[])
+{
+ struct step_gpio_action *p_gpio_act = NULL;
+ long write, symbol;
+ char buf[128] = "";
+
+ if (param_num != 2) {
+ pr_err("STEP failed: init gpio param(%d): %s\n", param_num,
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return NULL;
+ }
+
+ if (osal_strtol(params[0], 0, &write) ||
+ osal_strtol(params[1], 0, &symbol)) {
+ pr_err("STEP failed: str to value %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return NULL;
+ }
+
+ p_gpio_act = kzalloc(sizeof(struct step_gpio_action), GFP_KERNEL);
+ if (p_gpio_act == NULL) {
+ pr_err("STEP failed: kzalloc gpio fail\n");
+ return NULL;
+ }
+ p_gpio_act->is_write = write;
+ p_gpio_act->pin_symbol = symbol;
+
+ return &(p_gpio_act->base);
+}
+
+#if 0
+/*
+ * Support:
+ * _RST
+ */
+struct step_action *conninfra_step_create_chip_reset_action(int param_num, char *params[])
+{
+ struct step_chip_reset_action *p_crst_act = NULL;
+
+ p_crst_act = kzalloc(sizeof(struct step_chip_reset_action), GFP_KERNEL);
+ if (p_crst_act == NULL) {
+ pr_err("STEP failed: kzalloc chip reset fail\n");
+ return NULL;
+ }
+
+ return &(p_crst_act->base);
+}
+#endif
+
+/*
+ * Support:
+ * [PD+] | ms
+ */
+struct step_action *conninfra_step_create_periodic_dump_action(enum step_drv_type drv_type, int param_num, char *params[])
+{
+ struct step_periodic_dump_action *p_pd_act = NULL;
+
+ if (params[0] == NULL) {
+ pr_err("STEP failed: param null\n");
+ return NULL;
+ }
+
+ p_pd_act = kzalloc(sizeof(struct step_periodic_dump_action), GFP_KERNEL);
+ if (p_pd_act == NULL) {
+ pr_err("STEP failed: kzalloc fail\n");
+ return NULL;
+ }
+
+ p_pd_act->pd_entry = (struct step_pd_entry *)params[0];
+ return &(p_pd_act->base);
+}
+
+/*
+ * Support:
+ * SHOW | Message (no space)
+ */
+struct step_action *conninfra_step_create_show_string_action(enum step_drv_type drv_type, int param_num, char *params[])
+{
+ struct step_show_string_action *p_show_act = NULL;
+ char buf[128] = "";
+
+ if (param_num != 1) {
+ pr_err("STEP failed: init show param(%d): %s\n", param_num,
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return NULL;
+ }
+
+ p_show_act = kzalloc(sizeof(struct step_show_string_action), GFP_KERNEL);
+ if (p_show_act == NULL) {
+ pr_err("STEP failed: kzalloc show string fail\n");
+ return NULL;
+ }
+
+ p_show_act->content = kzalloc((osal_strlen(params[0]) + 1), GFP_KERNEL);
+ if (p_show_act->content == NULL) {
+ pr_err("STEP failed: kzalloc show string content fail\n");
+ kfree(p_show_act);
+ return NULL;
+ }
+ osal_memcpy(p_show_act->content, params[0], osal_strlen(params[0]));
+ return &(p_show_act->base);
+}
+
+/*
+ * Support:
+ * _SLP | time (ms)
+ */
+struct step_action *conninfra_step_create_sleep_action(enum step_drv_type drv_type, int param_num, char *params[])
+{
+ struct step_sleep_action *p_sleep_act = NULL;
+ long ms;
+ char buf[128] = "";
+
+ if (param_num != 1) {
+ pr_err("STEP failed: init sleep param(%d): %s\n", param_num,
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return NULL;
+ }
+
+ if (osal_strtol(params[0], 0, &ms)) {
+ pr_err("STEP failed: str to value %s\n",
+ params[0]);
+ return NULL;
+ }
+
+ p_sleep_act = kzalloc(sizeof(struct step_sleep_action), GFP_KERNEL);
+ if (p_sleep_act == NULL) {
+ pr_err("STEP failed: kzalloc sleep fail\n");
+ return NULL;
+ }
+ p_sleep_act->ms = ms;
+
+ return &(p_sleep_act->base);
+}
+
+/*
+ * Support:
+ * COND | Check temp register ID ($) | Left temp register ID ($) | Operator | Right temp register ID ($)
+ * COND | Check temp register ID ($) | Left temp register ID ($) | Operator | value
+ */
+struct step_action *conninfra_step_create_condition_action(enum step_drv_type drv_type, int param_num, char *params[])
+{
+ struct step_condition_action *p_cond_act = NULL;
+ unsigned int res_reg_id, l_reg_id, r_reg_id = 0;
+ long value = 0;
+ int mode;
+ enum step_condition_operator_id op_id;
+ char buf[128] = "";
+
+ if (param_num != 4) {
+ pr_err("STEP failed: init sleep param(%d): %s\n", param_num,
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return NULL;
+ }
+
+ res_reg_id = conninfra_step_parse_temp_register_id(params[0]);
+ l_reg_id = conninfra_step_parse_temp_register_id(params[1]);
+ if (res_reg_id >= STEP_PARAMETER_SIZE || l_reg_id >= STEP_PARAMETER_SIZE) {
+ pr_err("STEP failed: register id failed: %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return NULL;
+ }
+
+ op_id = conninfra_step_parse_operator_id(params[2]);
+ if (op_id >= STEP_OPERATOR_MAX) {
+ pr_err("STEP failed: operator id failed: %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return NULL;
+ }
+
+ if (*params[(param_num - 1)] == STEP_TEMP_REGISTER_SYMBOL) {
+ r_reg_id = conninfra_step_parse_temp_register_id(params[3]);
+ mode = STEP_CONDITION_RIGHT_REGISTER;
+ if (r_reg_id >= STEP_PARAMETER_SIZE) {
+ pr_err("STEP failed: register id failed: %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return NULL;
+ }
+ } else {
+ if (osal_strtol(params[3], 0, &value)) {
+ pr_err("STEP failed: str to value %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return NULL;
+ }
+ mode = STEP_CONDITION_RIGHT_VALUE;
+ }
+
+ p_cond_act = kzalloc(sizeof(struct step_condition_action), GFP_KERNEL);
+ if (p_cond_act == NULL) {
+ pr_err("STEP failed: kzalloc condition fail\n");
+ return NULL;
+ }
+
+ p_cond_act->result_temp_reg_id = res_reg_id;
+ p_cond_act->l_temp_reg_id = l_reg_id;
+ p_cond_act->operator_id = op_id;
+ p_cond_act->r_temp_reg_id = r_reg_id;
+ p_cond_act->value = value;
+ p_cond_act->mode = mode;
+
+ return &(p_cond_act->base);
+}
+
+/*
+ * Support:
+ * _VAL | Save temp register ID ($) | Value
+ */
+struct step_action *conninfra_step_create_value_action(enum step_drv_type drv_type, int param_num, char *params[])
+{
+ struct step_value_action *p_val_act = NULL;
+ unsigned int reg_id;
+ long value;
+ char buf[128] = "";
+
+ if (param_num != 2) {
+ pr_err("STEP failed: init sleep param(%d): %s\n", param_num,
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return NULL;
+ }
+
+ reg_id = conninfra_step_parse_temp_register_id(params[0]);
+ if (reg_id >= STEP_PARAMETER_SIZE) {
+ pr_err("STEP failed: register id failed: %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return NULL;
+ }
+
+ if (osal_strtol(params[1], 0, &value)) {
+ pr_err("STEP failed: str to value %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return NULL;
+ }
+
+ p_val_act = kzalloc(sizeof(struct step_value_action), GFP_KERNEL);
+ if (p_val_act == NULL) {
+ pr_err("STEP failed: kzalloc value fail\n");
+ return NULL;
+ }
+
+ p_val_act->temp_reg_id = reg_id;
+ p_val_act->value = value;
+
+ return &(p_val_act->base);
+}
+
+/*
+ * Support:
+ * CEMI | Check temp register ID (#) | R(0) | Begin offset | End offset
+ * CEMI | Check temp register ID (#) | R(0) | Begin offset | mask | Output temp register ID ($)
+ * CEMI | Check temp register ID (#) | R(0) | Begin offset | Output temp register ID ($)
+ */
+struct step_action *conninfra_step_create_condition_emi_action(enum step_drv_type drv_type, int param_num, char *params[])
+{
+ struct step_condition_emi_action *p_cond_emi_act = NULL;
+ struct step_emi_info *p_emi_info = NULL;
+ unsigned int reg_id;
+ char buf[128] = "";
+ int ret;
+
+ if (param_num < 1) {
+ pr_err("STEP failed: EMI no params\n");
+ return NULL;
+ }
+
+ reg_id = conninfra_step_parse_temp_register_id(params[0]);
+ if (reg_id >= STEP_PARAMETER_SIZE) {
+ pr_err("STEP failed: condition register id failed: %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return NULL;
+ }
+
+ p_cond_emi_act = kzalloc(sizeof(struct step_condition_emi_action), GFP_KERNEL);
+ if (p_cond_emi_act == NULL) {
+ pr_err("STEP failed: kzalloc condition emi fail\n");
+ return NULL;
+ }
+
+ p_emi_info = &p_cond_emi_act->info;
+ p_cond_emi_act->cond_reg_id = reg_id;
+ ret = _conninfra_step_create_emi_action(p_emi_info, param_num - 1, ¶ms[1]);
+
+ if (ret != 0) {
+ kfree(p_cond_emi_act);
+ return NULL;
+ }
+
+ return &(p_cond_emi_act->base);
+}
+
+/*
+ * Support:
+ * CREG | Check temp register ID (#) | R(0) | Pre-define base address ID | offset | times | delay time(ms)
+ * CREG | Check temp register ID (#) | R(0) | AP Physical address | offset | times | delay time(ms)
+ * CREG | Check temp register ID (#) | R(0) | Pre-define base address ID | offset | mask | Output temp register ID ($)
+ * CREG | Check temp register ID (#) | R(0) | AP Physical address | offset | mask | Output temp register ID ($)
+ * CREG | Check temp register ID (#) | R(0) | Pre-define base address ID | offset | Output temp register ID ($)
+ * CREG | Check temp register ID (#) | R(0) | AP Physical address | offset | Output temp register ID ($)
+ * CREG | Check temp register ID (#) | W(1) | AP Physical address | offset | value
+ * CREG | Check temp register ID (#) | W(1) | AP Physical address | offset | value
+ * CREG | Check temp register ID (#) | W(1) | AP Physical address | offset | value | mask
+ * CREG | Check temp register ID (#) | W(1) | AP Physical address | offset | value | mask
+ */
+struct step_action *conninfra_step_create_condition_register_action(enum step_drv_type drv_type, int param_num, char *params[])
+{
+ struct step_condition_register_action *p_cond_reg_act = NULL;
+ struct step_register_info *p_reg_info;
+ unsigned int reg_id;
+ char buf[128] = "";
+ int ret;
+
+ if (param_num < 0) {
+ pr_err("STEP failed: Init EMI param(%d): %s\n", param_num,
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return NULL;
+ }
+
+ reg_id = conninfra_step_parse_temp_register_id(params[0]);
+ if (reg_id >= STEP_PARAMETER_SIZE) {
+ pr_err("STEP failed: condition register id failed: %s\n",
+ conninfra_step_save_params_msg(param_num, params, buf, 128));
+ return NULL;
+ }
+
+ p_cond_reg_act = kzalloc(sizeof(struct step_condition_register_action), GFP_KERNEL);
+ if (p_cond_reg_act == NULL) {
+ pr_err("STEP failed: kzalloc condition register fail\n");
+ return NULL;
+ }
+
+ p_reg_info = &p_cond_reg_act->info;
+ p_cond_reg_act->cond_reg_id = reg_id;
+ ret = _conninfra_step_create_register_action(p_reg_info, param_num - 1, ¶ms[1]);
+
+ if (ret != 0) {
+ kfree(p_cond_reg_act);
+ return NULL;
+ }
+
+ p_reg_info->drv_type = drv_type;
+
+ return &(p_cond_reg_act->base);
+}
+
+
+
+/*******************************************************************************
+ * I N T E R N A L F U N C T I O N S W I T H U T
+********************************************************************************/
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/include/conninfra_step.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/include/conninfra_step.h
new file mode 100755
index 0000000..16f55ba
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/include/conninfra_step.h
@@ -0,0 +1,304 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _CONNINFRA_STEP_H_
+#define _CONNINFRA_STEP_H_
+
+#include <linux/list.h>
+#include <linux/workqueue.h>
+#include <linux/rwsem.h>
+#include "connsys_step.h"
+#include "conninfra_step_base.h"
+#include "conninfra.h"
+#include "consys_hw.h"
+
+#define STEP_CONFIG_NAME "CONNINFRA_STEP.cfg"
+#define STEP_VERSION 2
+
+#define STEP_PERIODIC_DUMP_WORK_QUEUE "conninfra_step_pd_wq"
+
+#define STEP_ACTION_NAME_EMI "_EMI"
+#define STEP_ACTION_NAME_REGISTER "_REG"
+#define STEP_ACTION_NAME_GPIO "GPIO"
+#define STEP_ACTION_NAME_DISABLE_RESET "DRST"
+#define STEP_ACTION_NAME_CHIP_RESET "_RST"
+#define STEP_ACTION_NAME_KEEP_WAKEUP "WAK+"
+#define STEP_ACTION_NAME_CANCEL_WAKEUP "WAK-"
+#define STEP_ACTION_NAME_SHOW_STRING "SHOW"
+#define STEP_ACTION_NAME_SLEEP "_SLP"
+#define STEP_ACTION_NAME_CONDITION "COND"
+#define STEP_ACTION_NAME_VALUE "_VAL"
+#define STEP_ACTION_NAME_CONDITION_EMI "CEMI"
+#define STEP_ACTION_NAME_CONDITION_REGISTER "CREG"
+
+enum consys_conninfra_step_trigger_point {
+ STEP_CONNINFRA_TP_NO_DEFINE = STEP_TP_NO_DEFINE,
+ /* CONNINFRA TRIGGER POINT */
+ STEP_CONNINFRA_TP_BEFORE_CHIP_RESET,
+ STEP_CONNINFRA_TP_AFTER_CHIP_RESET,
+ /* thermal */
+ STEP_CONNINFRA_TP_BEFORE_READ_THERMAL,
+ /* power on sequence */
+ STEP_CONNINFRA_TP_POWER_ON_START,
+ STEP_CONNINFRA_TP_POWER_ON_BEFORE_GET_CONNSYS_ID, /* 5 */
+ STEP_CONNINFRA_TP_POWER_ON_END,
+ /* power off */
+ STEP_CONNINFRA_TP_BEFORE_POWER_OFF,
+ /* Suspend/Resume */
+ STEP_CONNINFRA_TP_WHEN_AP_SUSPEND,
+ STEP_CONNINFRA_TP_WHEN_AP_RESUME, /* 9 */
+
+ STEP_CONNINFRA_TP_MAX,
+};
+
+
+/********* action ***********/
+
+struct step_action_list {
+ struct list_head list;
+};
+
+struct step_action {
+ struct list_head list;
+ enum step_action_id action_id;
+};
+
+
+/********** pd *****************/
+struct step_pd_entry {
+ bool is_enable;
+ unsigned int expires_ms;
+ struct step_action_list action_list;
+ struct delayed_work pd_work;
+ struct list_head list;
+};
+
+struct step_pd_struct {
+ bool is_init;
+ struct workqueue_struct *step_pd_wq;
+ struct list_head pd_list;
+};
+
+typedef int (*STEP_WRITE_ACT_TO_LIST) (struct step_action_list *, enum step_drv_type, enum step_action_id, int, char **);
+typedef void (*STEP_DO_EXTRA) (unsigned int, ...);
+
+#define STEP_OUTPUT_LOG 0
+#define STEP_OUTPUT_REGISTER 1
+
+
+/****************** ACTION *****************/
+struct step_emi_info {
+ bool is_write;
+ unsigned int begin_offset;
+ unsigned int end_offset;
+ int value;
+ unsigned int temp_reg_id;
+ int output_mode;
+ int mask;
+};
+
+struct step_emi_action {
+ struct step_emi_info info;
+ struct step_action base;
+};
+
+struct step_register_info {
+ enum step_drv_type drv_type;
+ bool is_write;
+ unsigned int address_type;
+ unsigned long address;
+ unsigned int offset;
+ unsigned int times;
+ unsigned int delay_time;
+ int value;
+ int mask;
+ unsigned int temp_reg_id;
+ int output_mode;
+};
+
+struct step_register_action {
+ struct step_register_info info;
+ struct step_action base;
+};
+
+struct step_gpio_action {
+ bool is_write;
+ unsigned int pin_symbol;
+ struct step_action base;
+};
+
+struct step_periodic_dump_action {
+ struct step_pd_entry *pd_entry;
+ struct step_action base;
+};
+
+struct step_show_string_action {
+ char *content;
+ struct step_action base;
+};
+
+struct step_sleep_action {
+ unsigned int ms;
+ struct step_action base;
+};
+
+#define STEP_CONDITION_RIGHT_REGISTER 0
+#define STEP_CONDITION_RIGHT_VALUE 1
+struct step_condition_action {
+ unsigned int result_temp_reg_id;
+ unsigned int l_temp_reg_id;
+ unsigned int r_temp_reg_id;
+ int value;
+ int mode;
+ enum step_condition_operator_id operator_id;
+ struct step_action base;
+};
+
+struct step_value_action {
+ unsigned int temp_reg_id;
+ int value;
+ struct step_action base;
+};
+
+struct step_condition_emi_action {
+ unsigned int cond_reg_id;
+ struct step_emi_info info;
+ struct step_action base;
+};
+
+struct step_condition_register_action {
+ unsigned int cond_reg_id;
+ struct step_register_info info;
+ struct step_action base;
+};
+
+#define clist_entry_action(act_struct, ptr) \
+ container_of(ptr, struct step_##act_struct##_action, base)
+
+struct step_reg_addr_info {
+ int address_type;
+ unsigned long address;
+};
+
+/************************* PARSE *************************/
+struct step_target_act_list_info {
+ enum step_drv_type drv_type;
+ //enum consys_step_trigger_point_id tp_id;
+ unsigned int tp_id;
+ struct step_action_list *p_target_list;
+ struct step_pd_entry *p_pd_entry;
+};
+
+#define STEP_PARAMETER_SIZE 10
+struct step_parse_line_data_param_info {
+ int state;
+ enum step_action_id act_id;
+ char *act_params[STEP_PARAMETER_SIZE];
+ int param_index;
+};
+
+typedef struct step_action *(*STEP_CREATE_ACTION) (enum step_drv_type, int, char *[]);
+typedef int (*STEP_DO_ACTIONS) (struct step_action *, STEP_DO_EXTRA);
+typedef void (*STEP_REMOVE_ACTION) (struct step_action *);
+struct step_action_contrl {
+ STEP_CREATE_ACTION func_create_action;
+ STEP_DO_ACTIONS func_do_action;
+ STEP_REMOVE_ACTION func_remove_action;
+};
+
+struct step_drv_type_def {
+ const char* drv_type_str;
+ int tp_max;
+ struct consys_step_register_cb *drv_cb;
+ struct step_action_list *action_list;
+};
+extern struct step_drv_type_def g_step_drv_type_def[STEP_DRV_TYPE_MAX];
+
+
+#define STEP_REGISTER_BASE_SYMBOL '#'
+#define STEP_TEMP_REGISTER_SYMBOL '$'
+
+#define STEP_VALUE_INFO_UNKNOWN -1
+#define STEP_VALUE_INFO_NUMBER 0
+#define STEP_VALUE_INFO_SYMBOL_REG_BASE 1
+#define STEP_VALUE_INFO_SYMBOL_TEMP_REG 2
+
+#define STEP_TEMP_REGISTER_SIZE 10
+struct step_env_struct {
+ bool is_enable;
+ bool is_keep_wakeup;
+ //struct step_action_list actions[STEP_DRV_TYPE_MAX][STEP_TRIGGER_POINT_MAX];
+ struct step_action_list conninfra_actions[STEP_CONNINFRA_TP_MAX];
+ struct step_action_list wf_actions[STEP_WF_TP_MAX];
+ struct step_action_list bt_actions[STEP_BT_TP_MAX];
+ struct step_action_list gps_actions[STEP_GPS_TP_MAX];
+ struct step_action_list fm_actions[STEP_FM_TP_MAX];
+
+ unsigned char __iomem *emi_base_addr;
+ unsigned int emi_size;
+
+ struct step_pd_struct pd_struct;
+ int temp_register[STEP_TEMP_REGISTER_SIZE];
+ bool is_setup;
+ struct rw_semaphore init_rwsem;
+};
+
+/********************************************************************************
+ * F U N C T I O N D E C L A R A T I O N S
+*********************************************************************************/
+void conninfra_step_init(void);
+void conninfra_step_deinit(void);
+
+void conninfra_step_do_actions(enum consys_conninfra_step_trigger_point tp_id);
+void conninfra_step_func_crtl_do_actions(enum consys_drv_type type, enum step_func_event_id opId);
+
+#ifdef CFG_CONNINFRA_STEP
+#define CONNINFRA_STEP_INIT_FUNC() conninfra_step_init()
+#define CONNINFRA_STEP_DEINIT_FUNC() conninfra_step_deinit()
+#define CONNINFRA_STEP_DO_ACTIONS_FUNC(tp) conninfra_step_do_actions(tp)
+#define CONNINFRA_STEP_FUNC_CTRL_DO_ACTIONS_FUNC(type, id) conninfra_step_func_crtl_do_actions(type, id)
+//#define conninfra_STEP_COMMAND_TIMEOUT_DO_ACTIONS_FUNC(reason) conninfra_step_command_timeout_do_actions(reason)
+
+#else
+#define CONNINFRA_STEP_INIT_FUNC()
+#define CONNINFRA_STEP_DEINIT_FUNC()
+#define CONNINFRA_STEP_DO_ACTIONS_FUNC(tp)
+#define CONNINFRA_STEP_FUNC_CTRL_DO_ACTIONS_FUNC(type, id)
+#define CONNINFRA_STEP_COMMAND_TIMEOUT_DO_ACTIONS_FUNC(reason)
+#endif
+
+/********************************************************************************
+ * D E C L A R E F O R T E S T
+*********************************************************************************/
+int conninfra_step_read_file(const char *file_name);
+int conninfra_step_parse_data(const char *in_buf, unsigned int size, STEP_WRITE_ACT_TO_LIST func_act_to_list);
+
+int conninfra_step_init_pd_env(void);
+int conninfra_step_deinit_pd_env(void);
+
+
+struct step_action_list *conninfra_step_get_tp_list(enum step_drv_type, int tp_id);
+
+struct step_pd_entry *conninfra_step_get_periodic_dump_entry(unsigned int expires);
+struct step_action *conninfra_step_create_action(enum step_drv_type drv_type, enum step_action_id act_id, int param_num, char *params[]);
+int conninfra_step_do_emi_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra);
+int conninfra_step_do_register_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra);
+int conninfra_step_do_gpio_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra);
+
+int conninfra_step_do_periodic_dump_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra);
+int conninfra_step_do_show_string_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra);
+int conninfra_step_do_sleep_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra);
+int conninfra_step_do_condition_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra);
+int conninfra_step_do_value_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra);
+int conninfra_step_do_condition_emi_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra);
+int conninfra_step_do_condition_register_action(struct step_action *p_act, STEP_DO_EXTRA func_do_extra);
+void conninfra_step_remove_action(struct step_action *p_act);
+void conninfra_step_print_version(void);
+
+void conninfra_step_do_actions_from_tp(enum step_drv_type drv_type,
+ unsigned int tp_id, char *reason);
+
+#endif /* end of _CONNINFRA_STEP_H_ */
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/include/conninfra_step_base.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/include/conninfra_step_base.h
new file mode 100755
index 0000000..4b1520a
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/include/conninfra_step_base.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _CONNINFRA_STEP_BASE_H_
+#define _CONNINFRA_STEP_BASE_H_
+
+enum step_drv_type {
+ STEP_DRV_TYPE_NO_DEFINE = 0,
+ STEP_DRV_TYPE_CONNINFRA,
+ STEP_DRV_TYPE_BT,
+ STEP_DRV_TYPE_FM,
+ STEP_DRV_TYPE_GPS,
+ STEP_DRV_TYPE_WIFI,
+
+ STEP_DRV_TYPE_MAX,
+};
+
+enum step_func_event_id {
+ STEP_FUNC_OFF = 0,
+ STEP_FUNC_ON
+};
+
+enum step_condition_operator_id {
+ STEP_OPERATOR_GREATER = 0,
+ STEP_OPERATOR_GREATER_EQUAL,
+ STEP_OPERATOR_LESS,
+ STEP_OPERATOR_LESS_EQUAL,
+ STEP_OPERATOR_EQUAL,
+ STEP_OPERATOR_NOT_EQUAL,
+ STEP_OPERATOR_AND,
+ STEP_OPERATOR_OR,
+ STEP_OPERATOR_MAX,
+};
+
+
+
+enum step_action_id {
+ STEP_ACTION_INDEX_NO_DEFINE = 0,
+ STEP_ACTION_INDEX_EMI = 1,
+ STEP_ACTION_INDEX_REGISTER,
+ STEP_ACTION_INDEX_GPIO,
+ STEP_ACTION_INDEX_PERIODIC_DUMP,
+ STEP_ACTION_INDEX_SHOW_STRING,
+ STEP_ACTION_INDEX_SLEEP,
+ STEP_ACTION_INDEX_CONDITION,
+ STEP_ACTION_INDEX_VALUE,
+ STEP_ACTION_INDEX_CONDITION_EMI,
+ STEP_ACTION_INDEX_CONDITION_REGISTER,
+ STEP_ACTION_INDEX_MAX,
+};
+
+
+#endif /* end of _CONNINFRA_STEP_BASE_H_ */
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/include/conninfra_step_parse_act.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/include/conninfra_step_parse_act.h
new file mode 100755
index 0000000..3bf9a3c
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/debug_utility/step/include/conninfra_step_parse_act.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _CONNINFRA_STEP_PARSE_ACT_H_
+#define _CONNINFRA_STEP_PARSE_ACT_H_
+
+#include "conninfra_step_base.h"
+
+
+struct step_action *conninfra_step_create_emi_action(enum step_drv_type drv_type, int param_num, char *params[]);
+struct step_action *conninfra_step_create_register_action(enum step_drv_type drv_type, int param_num, char *params[]);
+struct step_action *conninfra_step_create_gpio_action(enum step_drv_type drv_type, int param_num, char *params[]);
+
+struct step_action *conninfra_step_create_periodic_dump_action(enum step_drv_type drv_type, int param_num, char *params[]);
+struct step_action *conninfra_step_create_show_string_action(enum step_drv_type drv_type, int param_num, char *params[]);
+struct step_action *conninfra_step_create_sleep_action(enum step_drv_type drv_type, int param_num, char *params[]);
+struct step_action *conninfra_step_create_condition_action(enum step_drv_type drv_type, int param_num, char *params[]);
+struct step_action *conninfra_step_create_value_action(enum step_drv_type drv_type, int param_num, char *params[]);
+struct step_action *conninfra_step_create_condition_emi_action(enum step_drv_type drv_type, int param_num, char *params[]);
+struct step_action *conninfra_step_create_condition_register_action(enum step_drv_type drv_type, int param_num, char *params[]);
+
+
+#endif /* end of _CONNINFRA_STEP_PARSE_ACT_H_ */
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/include/conninfra.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/include/conninfra.h
new file mode 100755
index 0000000..c43bfb2
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/include/conninfra.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _CONNINFRA_H_
+#define _CONNINFRA_H_
+
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+enum consys_drv_type {
+ CONNDRV_TYPE_BT = 0,
+ CONNDRV_TYPE_FM = 1,
+ CONNDRV_TYPE_GPS = 2,
+ CONNDRV_TYPE_WIFI = 3,
+ CONNDRV_TYPE_CONNINFRA = 4,
+ CONNDRV_TYPE_MAX
+};
+
+/* Only for several project: MT6885 */
+enum consys_adie_ctl_type {
+ CONNSYS_ADIE_CTL_HOST_BT,
+ CONNSYS_ADIE_CTL_HOST_FM,
+ CONNSYS_ADIE_CTL_HOST_GPS,
+ CONNSYS_ADIE_CTL_HOST_WIFI,
+ CONNSYS_ADIE_CTL_HOST_CONNINFRA,
+ CONNSYS_ADIE_CTL_FW_BT,
+ CONNSYS_ADIE_CTL_FW_WIFI,
+ CONNSYS_ADIE_CTL_MAX
+};
+
+/* HW-specific, need sync with FW. DO NOT MODIFY */
+enum sys_spi_subsystem
+{
+ SYS_SPI_WF1 = 0x00,
+ SYS_SPI_WF = 0x01,
+ SYS_SPI_BT = 0x02,
+ SYS_SPI_FM = 0x03,
+ SYS_SPI_GPS = 0x04,
+ SYS_SPI_TOP = 0x05,
+ SYS_SPI_WF2 = 0x06,
+ SYS_SPI_WF3 = 0x07,
+ SYS_SPI_MAX
+};
+
+enum connsys_spi_speed_type {
+ CONNSYS_SPI_SPEED_26M,
+ CONNSYS_SPI_SPEED_64M,
+ CONNSYS_SPI_SPEED_MAX
+};
+
+enum connsys_clock_schematic
+{
+ CONNSYS_CLOCK_SCHEMATIC_26M_COTMS = 0,
+ CONNSYS_CLOCK_SCHEMATIC_52M_COTMS,
+ CONNSYS_CLOCK_SCHEMATIC_26M_EXTCXO,
+
+ CONNSYS_CLOCK_SCHEMATIC_MAX,
+};
+
+/* Conninfra driver allocate EMI for FW and WFDAM
+ * (FW includes: BT, WIFI and their MCU)
+ * +-----------+ +
+ * | | |
+ * | FW | |
+ * | | |
+ * +-----------+ v
+ * | |
+ * | | FW_WFDMA
+ * | | ^
+ * | WFDMA | |
+ * | | |
+ * | | |
+ * +-----------+ +
+ *
+ * MCIF region is provided by MD
+ * +-----------+
+ * | |
+ * | |
+ * | MCIF |
+ * | |
+ * +-----------+
+ */
+enum connsys_emi_type
+{
+ CONNSYS_EMI_FW_WFDMA = 0,
+ CONNSYS_EMI_FW,
+ CONNSYS_EMI_WFDMA,
+ CONNSYS_EMI_MCIF,
+
+ CONNSYS_EMI_MAX,
+};
+
+#define CONNINFRA_SPI_OP_FAIL 0x1
+
+#define CONNINFRA_CB_RET_CAL_PASS_POWER_OFF 0x0
+#define CONNINFRA_CB_RET_CAL_PASS_POWER_ON 0x2
+#define CONNINFRA_CB_RET_CAL_FAIL_POWER_OFF 0x1
+#define CONNINFRA_CB_RET_CAL_FAIL_POWER_ON 0x3
+
+#define CONNINFRA_BUS_CLOCK_WPLL 0x1
+#define CONNINFRA_BUS_CLOCK_BPLL 0x2
+#define CONNINFRA_BUS_CLOCK_ALL 0x3
+
+/* bus hang error define */
+#define CONNINFRA_INFRA_BUS_HANG 0x1
+#define CONNINFRA_AP2CONN_RX_SLP_PROT_ERR 0x2
+#define CONNINFRA_AP2CONN_TX_SLP_PROT_ERR 0x4
+#define CONNINFRA_AP2CONN_CLK_ERR 0x8
+#define CONNINFRA_INFRA_BUS_HANG_IRQ 0x10
+
+#define CONNINFRA_ERR_RST_ONGOING -0x7788
+#define CONNINFRA_ERR_WAKEUP_FAIL -0x5566
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+/* Conninfra bus clock control */
+int conninfra_bus_clock_ctrl(enum consys_drv_type drv_type, unsigned int bus_clock, int status);
+/* Clock schematic query */
+int conninfra_get_clock_schematic(void);
+
+/* SPI clock switch */
+int conninfra_spi_clock_switch(enum connsys_spi_speed_type type);
+
+/* A-die top_ck_en control, only for MT6885 */
+int conninfra_adie_top_ck_en_on(enum consys_adie_ctl_type type);
+int conninfra_adie_top_ck_en_off(enum consys_adie_ctl_type type);
+
+/* RFSPI */
+int conninfra_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data);
+int conninfra_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data);
+
+/* EMI */
+void conninfra_get_phy_addr(unsigned int *addr, unsigned int *size);
+void conninfra_get_emi_phy_addr(enum connsys_emi_type type, phys_addr_t* base, unsigned int *size);
+
+/* power on/off */
+int conninfra_pwr_on(enum consys_drv_type drv_type);
+int conninfra_pwr_off(enum consys_drv_type drv_type);
+
+/* To setup config relative data, ex: debug flag */
+void conninfra_config_setup(void);
+
+/* reg */
+/*
+ * 1 : can read
+ * 0 : can't read
+ */
+int conninfra_reg_readable(void);
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+/* reg readable */
+/* THIS API SHOULD NOT USED IN NORMAL CASE */
+/* IF YOU NEED THIS, PLEASE DISCUSS WITH OWNER */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+int conninfra_reg_readable_no_lock(void);
+/*
+ * 0 : NO hang
+ * > 0 : HANG!!
+ * CONNINFRA_ERR_RST_ONGOING: whole chip reset is ongoing
+ */
+int conninfra_is_bus_hang(void);
+
+/* chip reset
+* return:
+* <0: error
+* =0: triggered
+* =1: ongoing
+*/
+int conninfra_trigger_whole_chip_rst(enum consys_drv_type drv, char *reason);
+
+int conninfra_debug_dump(void);
+
+struct whole_chip_rst_cb {
+ int (*pre_whole_chip_rst)(enum consys_drv_type drv, char *reason);
+ int (*post_whole_chip_rst)(void);
+};
+
+/* driver state query */
+
+/* VCN control */
+
+/* Thermal */
+
+/* Config */
+
+/* semaphore */
+
+/* calibration */
+
+
+
+/* subsys callback register */
+struct pre_calibration_cb {
+ int (*pwr_on_cb)(void);
+ int (*do_cal_cb)(void);
+};
+
+struct sub_drv_ops_cb {
+ /* chip reset */
+ struct whole_chip_rst_cb rst_cb;
+
+ /* calibration */
+ struct pre_calibration_cb pre_cal_cb;
+
+ /* thermal query */
+ int (*thermal_qry)(void);
+
+};
+
+int conninfra_sub_drv_ops_register(enum consys_drv_type drv_type, struct sub_drv_ops_cb *cb);
+int conninfra_sub_drv_ops_unregister(enum consys_drv_type drv_type);
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _CONNINFRA_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/include/connsys_step.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/include/connsys_step.h
new file mode 100755
index 0000000..15c06a4
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/include/connsys_step.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef _CONNSYS_STEP_H_
+#define _CONNSYS_STEP_H_
+
+#define STEP_TP_NO_DEFINE 0
+
+enum consys_wf_step_trigger_point {
+ STEP_WF_TP_NO_DEFINE = STEP_TP_NO_DEFINE,
+ STEP_WF_TP_COMMAND_TIMEOUT,
+ STEP_WF_TP_BEFORE_CHIP_RESET,
+ STEP_WF_TP_AFTER_CHIP_RESET,
+
+ STEP_WF_TP_MAX,
+};
+
+enum consys_bt_step_trigger_point {
+ STEP_BT_TP_NO_DEFINE = STEP_TP_NO_DEFINE,
+ STEP_BT_TP_COMMAND_TIMEOUT,
+ STEP_BT_TP_BEFORE_CHIP_RESET,
+ STEP_BT_TP_AFTER_CHIP_RESET,
+
+ STEP_BT_TP_MAX,
+};
+
+enum consys_gps_step_trigger_point {
+ STEP_GPS_TP_NO_DEFINE = STEP_TP_NO_DEFINE,
+ STEP_GPS_TP_COMMAND_TIMEOUT,
+ STEP_GPS_TP_BEFORE_CHIP_RESET,
+ STEP_GPS_TP_AFTER_CHIP_RESET,
+
+ STEP_GPS_TP_MAX,
+};
+
+enum consys_fm_step_trigger_point {
+ STEP_FM_TP_NO_DEFINE = STEP_TP_NO_DEFINE,
+ STEP_FM_TP_COMMAND_TIMEOUT,
+ STEP_FM_TP_BEFORE_CHIP_RESET,
+ STEP_FM_TP_AFTER_CHIP_RESET,
+
+ STEP_FM_TP_MAX,
+};
+
+/******************************************
+ * readable
+ * 1: can read, 0: CANNOT read
+ ******************************************/
+struct consys_step_register_cb {
+ int (*readable_cb)(unsigned long);
+};
+
+/******************************************
+ * drv down should call consys_step_xx_register(NULL);
+ ******************************************/
+void consys_step_bt_register(struct consys_step_register_cb *cb);
+void consys_step_bt_do_action(enum consys_bt_step_trigger_point);
+
+void consys_step_wf_register(struct consys_step_register_cb *cb);
+void consys_step_wf_do_action(enum consys_wf_step_trigger_point);
+
+void consys_step_gps_register(struct consys_step_register_cb *cb);
+void consys_step_gps_do_action(enum consys_gps_step_trigger_point);
+
+void consys_step_fm_register(struct consys_step_register_cb *cb);
+void consys_step_fm_do_action(enum consys_fm_step_trigger_point);
+
+
+#endif /* end of _CONNSYS_STEP_H_ */
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/init.conninfra.rc b/src/kernel/modules/connectivity/2.0/conninfra_driver/init.conninfra.rc
new file mode 100755
index 0000000..cca37bf
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/init.conninfra.rc
@@ -0,0 +1,2 @@
+on boot
+ insmod /vendor/lib/modules/conninfra.ko
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/clock_mng.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/clock_mng.c
new file mode 100755
index 0000000..9c2fd55
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/clock_mng.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#include "osal.h"
+
+#include "clock_mng.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/consys_hw.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/consys_hw.c
new file mode 100755
index 0000000..22ef3f9
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/consys_hw.c
@@ -0,0 +1,622 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#include <linux/delay.h>
+#include <linux/of_device.h>
+#include <linux/of_reserved_mem.h>
+
+#include "osal.h"
+
+#include "consys_hw.h"
+#include "emi_mng.h"
+#include "pmic_mng.h"
+#include "consys_reg_mng.h"
+#if CFG_CONNINFRA_FW_LOG_SUPPORT
+#include "connsys_debug_utility.h"
+#endif
+#if CFG_CONNINFRA_STEP_SUPPORT
+#include "connsys_step.h"
+#include "conninfra_step.h"
+#endif
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+static int mtk_conninfra_probe(struct platform_device *pdev);
+static int mtk_conninfra_remove(struct platform_device *pdev);
+static int mtk_conninfra_suspend(struct platform_device *pdev, pm_message_t state);
+static int mtk_conninfra_resume(struct platform_device *pdev);
+
+static int consys_hw_init(struct platform_device *pdev, struct conninfra_dev_cb* dev_cb);
+static int consys_hw_deinit(void);
+static int _consys_hw_conninfra_wakeup(void);
+static void _consys_hw_conninfra_sleep(void);
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+extern const struct of_device_id apconninfra_of_ids[];
+
+static struct platform_driver mtk_conninfra_dev_drv = {
+ .probe = mtk_conninfra_probe,
+ .remove = mtk_conninfra_remove,
+ .suspend = mtk_conninfra_suspend,
+ .resume = mtk_conninfra_resume,
+ .driver = {
+ .name = "mtk_conninfra",
+ .owner = THIS_MODULE,
+ .of_match_table = apconninfra_of_ids,
+ },
+};
+
+
+struct consys_hw_env conn_hw_env;
+
+const struct consys_hw_ops_struct *consys_hw_ops;
+struct platform_device *g_pdev;
+
+int g_conninfra_wakeup_ref_cnt;
+
+struct work_struct ap_resume_work;
+
+struct conninfra_dev_cb *g_conninfra_dev_cb;
+const struct conninfra_plat_data *g_conninfra_plat_data = NULL;
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+struct platform_device *get_consys_device(void)
+{
+ return g_pdev;
+}
+
+int consys_hw_get_clock_schematic(void)
+{
+ if (consys_hw_ops->consys_plt_co_clock_type)
+ return consys_hw_ops->consys_plt_co_clock_type();
+ else
+ pr_err("consys_hw_ops->consys_co_clock_type not supported\n");
+
+ return -1;
+}
+
+unsigned int consys_hw_chipid_get(void)
+{
+ if (g_conninfra_plat_data && g_conninfra_plat_data->chip_id)
+ return g_conninfra_plat_data->chip_id;
+ else if (consys_hw_ops->consys_plt_soc_chipid_get)
+ return consys_hw_ops->consys_plt_soc_chipid_get();
+ else
+ pr_err("consys_plt_soc_chipid_get not supported\n");
+
+ return 0;
+}
+
+unsigned int consys_hw_get_hw_ver(void)
+{
+ if (consys_hw_ops->consys_plt_get_hw_ver)
+ return consys_hw_ops->consys_plt_get_hw_ver();
+ return 0;
+}
+
+
+int consys_hw_reg_readable(void)
+{
+ return consys_reg_mng_reg_readable();
+}
+
+int consys_hw_is_connsys_reg(phys_addr_t addr)
+{
+ return consys_reg_mng_is_connsys_reg(addr);
+}
+
+int consys_hw_is_bus_hang(void)
+{
+ return consys_reg_mng_is_bus_hang();
+}
+
+int consys_hw_dump_bus_status(void)
+{
+ return consys_reg_mng_dump_bus_status();
+}
+
+int consys_hw_dump_cpupcr(enum conn_dump_cpupcr_type dump_type, int times, unsigned long interval_us)
+{
+ return consys_reg_mng_dump_cpupcr(dump_type, times, interval_us);
+}
+
+int consys_hw_pwr_off(unsigned int curr_status, unsigned int off_radio)
+{
+ unsigned int next_status = curr_status & ~(0x1 << off_radio);
+ int ret = 0;
+
+ if (next_status == 0) {
+
+ #if CFG_CONNINFRA_STEP_SUPPORT
+ CONNINFRA_STEP_DO_ACTIONS_FUNC(STEP_CONNINFRA_TP_BEFORE_POWER_OFF);
+ #endif
+ pr_info("Last pwoer off: %d\n", off_radio);
+ pr_info("Power off CONNSYS PART 1\n");
+ if (consys_hw_ops->consys_plt_conninfra_on_power_ctrl)
+ consys_hw_ops->consys_plt_conninfra_on_power_ctrl(0);
+ pr_info("Power off CONNSYS PART 2\n");
+ if (consys_hw_ops->consys_plt_set_if_pinmux)
+ consys_hw_ops->consys_plt_set_if_pinmux(0);
+ if (consys_hw_ops->consys_plt_clock_buffer_ctrl)
+ consys_hw_ops->consys_plt_clock_buffer_ctrl(0);
+ ret = pmic_mng_common_power_ctrl(0);
+ pr_info("Power off a-die power, ret=%d\n", ret);
+ } else {
+ pr_info("[%s] Part 0: only subsys (%d) off (curr_status=0x%x, next_status = 0x%x)\n",
+ __func__, off_radio, curr_status, next_status);
+ ret = _consys_hw_conninfra_wakeup();
+ if (consys_hw_ops->consys_plt_subsys_status_update)
+ consys_hw_ops->consys_plt_subsys_status_update(false, off_radio);
+ if (consys_hw_ops->consys_plt_spi_master_cfg)
+ consys_hw_ops->consys_plt_spi_master_cfg(next_status);
+ if (consys_hw_ops->consys_plt_low_power_setting)
+ consys_hw_ops->consys_plt_low_power_setting(curr_status, next_status);
+ if (ret == 0)
+ _consys_hw_conninfra_sleep();
+ }
+
+ return 0;
+}
+
+int consys_hw_pwr_on(unsigned int curr_status, unsigned int on_radio)
+{
+ int ret;
+ unsigned int next_status = (curr_status | (0x1 << on_radio));
+
+ /* first power on */
+ if (curr_status == 0) {
+ #if CFG_CONNINFRA_STEP_SUPPORT
+ CONNINFRA_STEP_DO_ACTIONS_FUNC(STEP_CONNINFRA_TP_POWER_ON_START);
+ #endif
+ /* POS PART 1:
+ * Set PMIC to turn on the power that AFE WBG circuit in D-die,
+ * OSC or crystal component, and A-die need.
+ */
+ ret = pmic_mng_common_power_ctrl(1);
+ if (consys_hw_ops->consys_plt_clock_buffer_ctrl)
+ consys_hw_ops->consys_plt_clock_buffer_ctrl(1);
+
+ /* POS PART 2:
+ * 1. Pinmux setting
+ * 2. Turn on MTCMOS
+ * 3. Enable AXI bus (AP2CONN slpprot)
+ */
+ if (consys_hw_ops->consys_plt_set_if_pinmux)
+ consys_hw_ops->consys_plt_set_if_pinmux(1);
+
+ udelay(500);
+ if (consys_hw_ops->consys_plt_conninfra_on_power_ctrl)
+ consys_hw_ops->consys_plt_conninfra_on_power_ctrl(1);
+
+ #if CFG_CONNINFRA_STEP_SUPPORT
+ CONNINFRA_STEP_DO_ACTIONS_FUNC(STEP_CONNINFRA_TP_POWER_ON_BEFORE_GET_CONNSYS_ID);
+ #endif
+ if (consys_hw_ops->consys_plt_polling_consys_chipid)
+ consys_hw_ops->consys_plt_polling_consys_chipid();
+
+ /* POS PART 3:
+ * 1. Set connsys EMI mapping
+ * 2. d_die_cfg
+ * 3. spi_master_cfg
+ * 4. a_die_cfg
+ * 5. afe_wbg_cal
+ * 6. patch default value
+ * 7. CONN_INFRA low power setting (srcclken wait time, mtcmos HW ctl...)
+ */
+ emi_mng_set_remapping_reg();
+ if (consys_hw_ops->consys_plt_d_die_cfg)
+ consys_hw_ops->consys_plt_d_die_cfg();
+ if (consys_hw_ops->consys_plt_spi_master_cfg)
+ consys_hw_ops->consys_plt_spi_master_cfg(next_status);
+ if (consys_hw_ops->consys_plt_a_die_cfg)
+ consys_hw_ops->consys_plt_a_die_cfg();
+ if (consys_hw_ops->consys_plt_afe_wbg_cal)
+ consys_hw_ops->consys_plt_afe_wbg_cal();
+ if (consys_hw_ops->consys_plt_subsys_pll_initial)
+ consys_hw_ops->consys_plt_subsys_pll_initial();
+ /* Record SW status on shared sysram */
+ if (consys_hw_ops->consys_plt_subsys_status_update)
+ consys_hw_ops->consys_plt_subsys_status_update(true, on_radio);
+ if (consys_hw_ops->consys_plt_low_power_setting)
+ consys_hw_ops->consys_plt_low_power_setting(curr_status, next_status);
+ #if CFG_CONNINFRA_STEP_SUPPORT
+ CONNINFRA_STEP_DO_ACTIONS_FUNC(STEP_CONNINFRA_TP_POWER_ON_END);
+ #endif
+ } else {
+ ret = _consys_hw_conninfra_wakeup();
+ /* Record SW status on shared sysram */
+ if (consys_hw_ops->consys_plt_subsys_status_update)
+ consys_hw_ops->consys_plt_subsys_status_update(true, on_radio);
+ if (consys_hw_ops->consys_plt_spi_master_cfg)
+ consys_hw_ops->consys_plt_spi_master_cfg(next_status);
+ if (consys_hw_ops->consys_plt_low_power_setting)
+ consys_hw_ops->consys_plt_low_power_setting(curr_status, next_status);
+
+ if (ret == 0)
+ _consys_hw_conninfra_sleep();
+ }
+ return 0;
+}
+
+int consys_hw_wifi_power_ctl(unsigned int enable)
+{
+ return pmic_mng_wifi_power_ctrl(enable);
+}
+
+int consys_hw_bt_power_ctl(unsigned int enable)
+{
+ return pmic_mng_bt_power_ctrl(enable);
+}
+
+int consys_hw_gps_power_ctl(unsigned int enable)
+{
+ return pmic_mng_gps_power_ctrl(enable);
+}
+
+int consys_hw_fm_power_ctl(unsigned int enable)
+{
+ return pmic_mng_fm_power_ctrl(enable);
+}
+
+
+int consys_hw_therm_query(int *temp_ptr)
+{
+ int ret = 0;
+
+ /* wake/sleep conninfra */
+ if (consys_hw_ops && consys_hw_ops->consys_plt_thermal_query) {
+ ret = _consys_hw_conninfra_wakeup();
+ if (ret)
+ return CONNINFRA_ERR_WAKEUP_FAIL;
+ #if CFG_CONNINFRA_STEP_SUPPORT
+ CONNINFRA_STEP_DO_ACTIONS_FUNC(STEP_CONNINFRA_TP_BEFORE_READ_THERMAL);
+ #endif
+ *temp_ptr = consys_hw_ops->consys_plt_thermal_query();
+ _consys_hw_conninfra_sleep();
+ } else
+ ret = -1;
+
+ return ret;
+}
+
+void consys_hw_clock_fail_dump(void)
+{
+ if (consys_hw_ops && consys_hw_ops->consys_plt_clock_fail_dump)
+ consys_hw_ops->consys_plt_clock_fail_dump();
+}
+
+
+int consys_hw_dump_power_state(void)
+{
+ if (consys_hw_ops && consys_hw_ops->consys_plt_power_state)
+ consys_hw_ops->consys_plt_power_state();
+ return 0;
+}
+
+int consys_hw_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data)
+{
+ if (consys_hw_ops->consys_plt_spi_read)
+ return consys_hw_ops->consys_plt_spi_read(subsystem, addr, data);
+ return -1;
+}
+
+int consys_hw_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data)
+{
+ if (consys_hw_ops->consys_plt_spi_write)
+ return consys_hw_ops->consys_plt_spi_write(subsystem, addr, data);
+ return -1;
+}
+
+int consys_hw_adie_top_ck_en_on(enum consys_adie_ctl_type type)
+{
+ if (consys_hw_ops->consys_plt_adie_top_ck_en_on)
+ return consys_hw_ops->consys_plt_adie_top_ck_en_on(type);
+ return -1;
+}
+
+int consys_hw_adie_top_ck_en_off(enum consys_adie_ctl_type type)
+{
+ if (consys_hw_ops->consys_plt_adie_top_ck_en_off)
+ return consys_hw_ops->consys_plt_adie_top_ck_en_off(type);
+ return -1;
+}
+
+
+static int _consys_hw_conninfra_wakeup(void)
+{
+ int ref = g_conninfra_wakeup_ref_cnt;
+ bool wakeup = false, ret;
+
+ if (consys_hw_ops->consys_plt_conninfra_wakeup) {
+ if (g_conninfra_wakeup_ref_cnt == 0) {
+ ret = consys_hw_ops->consys_plt_conninfra_wakeup();
+ if (ret) {
+ pr_err("wakeup fail!! ret=[%d]", ret);
+ return ret;
+ }
+ wakeup = true;
+ }
+ g_conninfra_wakeup_ref_cnt++;
+ }
+
+ pr_info("conninfra_wakeup refcnt=[%d]->[%d] %s",
+ ref, g_conninfra_wakeup_ref_cnt, (wakeup ? "wakeup!!" : ""));
+ return 0;
+}
+
+static void _consys_hw_conninfra_sleep(void)
+{
+ int ref = g_conninfra_wakeup_ref_cnt;
+ bool sleep = false;
+
+ if (consys_hw_ops->consys_plt_conninfra_sleep &&
+ --g_conninfra_wakeup_ref_cnt == 0) {
+ sleep = true;
+ consys_hw_ops->consys_plt_conninfra_sleep();
+ }
+ pr_info("conninfra_sleep refcnt=[%d]->[%d] %s",
+ ref, g_conninfra_wakeup_ref_cnt, (sleep ? "sleep!!" : ""));
+}
+
+int consys_hw_force_conninfra_wakeup(void)
+{
+ return _consys_hw_conninfra_wakeup();
+}
+
+int consys_hw_force_conninfra_sleep(void)
+{
+ _consys_hw_conninfra_sleep();
+ return 0;
+}
+
+int consys_hw_spi_clock_switch(enum connsys_spi_speed_type type)
+{
+ if (consys_hw_ops->consys_plt_spi_clock_switch)
+ return consys_hw_ops->consys_plt_spi_clock_switch(type);
+ return -1;
+}
+
+void consys_hw_config_setup(void)
+{
+ if (consys_hw_ops->consys_plt_config_setup)
+ consys_hw_ops->consys_plt_config_setup();
+}
+
+int consys_hw_pmic_event_cb(unsigned int id, unsigned int event)
+{
+ pmic_mng_event_cb(id, event);
+ return 0;
+}
+
+int consys_hw_bus_clock_ctrl(enum consys_drv_type drv_type, unsigned int bus_clock, int status)
+{
+ if (consys_hw_ops->consys_plt_bus_clock_ctrl)
+ return consys_hw_ops->consys_plt_bus_clock_ctrl(drv_type, bus_clock, status);
+ else
+ return -1;
+}
+
+int mtk_conninfra_probe(struct platform_device *pdev)
+{
+ int ret = -1;
+#if CFG_CONNINFRA_FW_LOG_SUPPORT
+ struct consys_emi_addr_info* emi_info = NULL;
+#endif
+
+ if (pdev)
+ g_pdev = pdev;
+ else {
+ pr_err("[%s] pdev is NULL\n", __func__);
+ return -1;
+ }
+
+ /* HW operation init */
+ if (consys_hw_init(pdev, g_conninfra_dev_cb) != 0) {
+ pr_err("consys_hw_init fail");
+ return -1;
+ }
+
+ /* Read device node */
+ if (consys_reg_mng_init(pdev, g_conninfra_plat_data) != 0) {
+ pr_err("consys_plt_read_reg_from_dts fail");
+ return -2;
+ }
+
+ if (consys_hw_ops->consys_plt_clk_get_from_dts)
+ consys_hw_ops->consys_plt_clk_get_from_dts(pdev);
+ else {
+ pr_err("consys_plt_clk_get_from_dtsfail");
+ return -3;
+ }
+
+ /* emi mng init */
+ ret = emi_mng_init(pdev, g_conninfra_plat_data);
+ if (ret) {
+ pr_err("emi_mng init fail, %d\n", ret);
+ return -4;
+ }
+
+ ret = pmic_mng_init(pdev, g_conninfra_dev_cb, g_conninfra_plat_data);
+ if (ret) {
+ pr_err("pmic_mng init fail, %d\n", ret);
+ return -5;
+ }
+
+#if CFG_CONNINFRA_FW_LOG_SUPPORT
+ /* Setup connsys log emi base */
+ emi_info = emi_mng_get_phy_addr();
+ if (emi_info) {
+ connsys_dedicated_log_path_apsoc_init((phys_addr_t)emi_info->emi_ap_phy_addr);
+ } else {
+ pr_err("Connsys log didn't init because EMI is invalid\n");
+ }
+#endif /* CONNINFRA_FW_LOG_SUPPORT */
+
+ /* Register thermal */
+ if (consys_hw_ops->consys_plt_thermal_register)
+ consys_hw_ops->consys_plt_thermal_register(pdev, g_conninfra_dev_cb);
+ else
+ pr_info("consys_plt_thermal_register is not supported.");
+
+ return 0;
+}
+
+int mtk_conninfra_remove(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = pmic_mng_deinit();
+ pr_info("pmic_mng_deinit ret=%d", ret);
+
+ ret = emi_mng_deinit();
+ pr_info("emi_mng_deinit ret=%d", ret);
+
+ if (consys_hw_ops->consys_plt_clk_detach)
+ consys_hw_ops->consys_plt_clk_detach();
+ else
+ pr_err("consys_plt_clk_detach is null");
+
+ ret = consys_reg_mng_deinit();
+ pr_info("consys_reg_mng_deinit ret=%d", ret);
+
+ ret = consys_hw_deinit();
+ pr_info("consys_hw_deinit ret=%d", ret);
+
+ if (g_pdev)
+ g_pdev = NULL;
+
+ return 0;
+}
+
+int mtk_conninfra_suspend(struct platform_device *pdev, pm_message_t state)
+{
+#if CFG_CONNINFRA_STEP_SUPPORT
+ /* suspend callback is in atomic context */
+ CONNINFRA_STEP_DO_ACTIONS_FUNC(STEP_CONNINFRA_TP_WHEN_AP_SUSPEND);
+#endif /* CFG_CONNINFRA_STEP_SUPPORT */
+
+ return 0;
+}
+
+int mtk_conninfra_resume(struct platform_device *pdev)
+{
+ /* suspend callback is in atomic context, use schedule work to execute STEP */
+
+ schedule_work(&ap_resume_work);
+ return 0;
+}
+
+
+static void consys_hw_ap_resume_handler(struct work_struct *work)
+{
+#if CFG_CONNINFRA_STEP_SUPPORT
+ CONNINFRA_STEP_DO_ACTIONS_FUNC(STEP_CONNINFRA_TP_WHEN_AP_RESUME);
+#endif /* CFG_CONNINFRA_STEP_SUPPORT */
+
+ if (g_conninfra_dev_cb && g_conninfra_dev_cb->conninfra_resume_cb)
+ (*g_conninfra_dev_cb->conninfra_resume_cb)();
+}
+
+
+int consys_hw_init(struct platform_device *pdev, struct conninfra_dev_cb* dev_cb)
+{
+ g_conninfra_plat_data = (const struct conninfra_plat_data*)of_device_get_match_data(&pdev->dev);
+ if (g_conninfra_plat_data == NULL) {
+ pr_err("[%s] Get platform data fail.", __func__);
+ return -1;
+ }
+ if (consys_hw_ops == NULL)
+ consys_hw_ops = (const struct consys_hw_ops_struct*)g_conninfra_plat_data->hw_ops;
+
+ if (consys_hw_ops == NULL)
+ pr_err("Get HW op fail");
+ return 0;
+}
+
+int consys_hw_deinit(void)
+{
+ return 0;
+}
+
+
+int mtk_conninfra_drv_init(struct conninfra_dev_cb *dev_cb)
+{
+ int iRet = 0;
+
+ g_conninfra_dev_cb = dev_cb;
+
+ pr_info("Before platform_driver_register");
+ iRet = platform_driver_register(&mtk_conninfra_dev_drv);
+ if (iRet)
+ pr_err("Conninfra platform driver registered failed(%d)\n", iRet);
+ pr_info("After platform_driver_register");
+
+ INIT_WORK(&ap_resume_work, consys_hw_ap_resume_handler);
+ pr_info("[consys_hw_init] result [%d]\n", iRet);
+
+ return iRet;
+}
+
+int mtk_conninfra_drv_deinit(void)
+{
+ platform_driver_unregister(&mtk_conninfra_dev_drv);
+ g_conninfra_dev_cb = NULL;
+ return 0;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/consys_hw_plat_data.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/consys_hw_plat_data.c
new file mode 100644
index 0000000..0b8bd32
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/consys_hw_plat_data.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+#include <linux/of_device.h>
+
+#include "consys_hw.h"
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/* Platform data */
+extern struct conninfra_plat_data mt6880_plat_data;
+
+const struct of_device_id apconninfra_of_ids[] = {
+ {
+ .compatible = "mediatek,mt6880-consys",
+ .data = (void*)&mt6880_plat_data,
+ },
+ {}
+};
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/consys_reg_mng.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/consys_reg_mng.c
new file mode 100755
index 0000000..406306a
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/consys_reg_mng.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__
+
+#include "consys_hw.h"
+#include "consys_reg_mng.h"
+#include "consys_reg_util.h"
+
+const struct consys_reg_mng_ops* g_consys_reg_ops = NULL;
+
+int consys_reg_mng_reg_readable(void)
+{
+ if (g_consys_reg_ops &&
+ g_consys_reg_ops->consys_reg_mng_check_reable)
+ return g_consys_reg_ops->consys_reg_mng_check_reable();
+ pr_err("%s not implement", __func__);
+ return -1;
+}
+
+int consys_reg_mng_is_connsys_reg(phys_addr_t addr)
+{
+ if (g_consys_reg_ops &&
+ g_consys_reg_ops->consys_reg_mng_is_consys_reg)
+ return g_consys_reg_ops->consys_reg_mng_is_consys_reg(addr);
+ return -1;
+}
+
+
+int consys_reg_mng_is_bus_hang(void)
+{
+ if (g_consys_reg_ops &&
+ g_consys_reg_ops->consys_reg_mng_is_bus_hang)
+ return g_consys_reg_ops->consys_reg_mng_is_bus_hang();
+ return -1;
+}
+
+int consys_reg_mng_dump_bus_status(void)
+{
+ if (g_consys_reg_ops &&
+ g_consys_reg_ops->consys_reg_mng_dump_bus_status)
+ return g_consys_reg_ops->consys_reg_mng_dump_bus_status();
+ return -1;
+}
+
+int consys_reg_mng_dump_conninfra_status(void)
+{
+ if (g_consys_reg_ops &&
+ g_consys_reg_ops->consys_reg_mng_dump_conninfra_status)
+ return g_consys_reg_ops->consys_reg_mng_dump_conninfra_status();
+ return -1;
+}
+
+int consys_reg_mng_dump_cpupcr(enum conn_dump_cpupcr_type dump_type, int times, unsigned long interval_us)
+{
+ if (g_consys_reg_ops &&
+ g_consys_reg_ops->consys_reg_mng_dump_cpupcr)
+ return g_consys_reg_ops->consys_reg_mng_dump_cpupcr(dump_type, times, interval_us);
+ return -1;
+}
+
+unsigned long consys_reg_mng_validate_idx_n_offset(unsigned int idx, unsigned long offset)
+{
+ if (g_consys_reg_ops&&
+ g_consys_reg_ops->consys_reg_mng_validate_idx_n_offset)
+ return g_consys_reg_ops->consys_reg_mng_validate_idx_n_offset(idx, offset);
+ return -1;
+}
+
+int consys_reg_mng_find_can_write_reg(unsigned int *idx, unsigned long* offset)
+{
+ if (g_consys_reg_ops&&
+ g_consys_reg_ops->consys_reg_mng_find_can_write_reg)
+ return g_consys_reg_ops->consys_reg_mng_find_can_write_reg(idx, offset);
+ return -1;
+}
+
+unsigned long consys_reg_mng_get_phy_addr_by_idx(unsigned int idx)
+{
+ if (g_consys_reg_ops&&
+ g_consys_reg_ops->consys_reg_mng_get_phy_addr_by_idx)
+ return g_consys_reg_ops->consys_reg_mng_get_phy_addr_by_idx(idx);
+ return -1;
+}
+
+unsigned long consys_reg_mng_get_virt_addr_by_idx(unsigned int idx)
+{
+ if (g_consys_reg_ops&&
+ g_consys_reg_ops->consys_reg_mng_get_virt_addr_by_idx)
+ return g_consys_reg_ops->consys_reg_mng_get_virt_addr_by_idx(idx);
+ return -1;
+}
+
+
+int consys_reg_mng_get_chip_id_idx_offset(unsigned int *idx, unsigned long *offset)
+{
+ if (g_consys_reg_ops&&
+ g_consys_reg_ops->consys_reg_mng_get_chip_id_idx_offset)
+ return g_consys_reg_ops->consys_reg_mng_get_chip_id_idx_offset(idx, offset);
+ return -1;
+}
+
+int consys_reg_mng_get_reg_symbol_num(void)
+{
+ if (g_consys_reg_ops&&
+ g_consys_reg_ops->consys_reg_mng_get_reg_symbol_num)
+ return g_consys_reg_ops->consys_reg_mng_get_reg_symbol_num();
+ return -1;
+}
+
+
+int consys_reg_mng_init(struct platform_device *pdev, const struct conninfra_plat_data* plat_data)
+{
+ int ret = 0;
+ if (g_consys_reg_ops == NULL)
+ g_consys_reg_ops = (const struct consys_reg_mng_ops*)plat_data->reg_ops;
+
+ if (g_consys_reg_ops &&
+ g_consys_reg_ops->consys_reg_mng_init)
+ ret = g_consys_reg_ops->consys_reg_mng_init(pdev);
+ else
+ ret = EFAULT;
+
+ return ret;
+}
+
+int consys_reg_mng_deinit(void)
+{
+ if (g_consys_reg_ops&&
+ g_consys_reg_ops->consys_reg_mng_deinit)
+ g_consys_reg_ops->consys_reg_mng_deinit();
+
+ return 0;
+}
+
+int consys_reg_mng_reg_read(unsigned long addr, unsigned int *value, unsigned int mask)
+{
+ void __iomem *vir_addr = NULL;
+
+ vir_addr = ioremap_nocache(addr, 0x100);
+ if (!vir_addr) {
+ pr_err("ioremap fail");
+ return -1;
+ }
+
+ *value = (unsigned int)CONSYS_REG_READ(vir_addr) & mask;
+
+ pr_info("[%x] mask=[%x]", *value, mask);
+
+ iounmap(vir_addr);
+ return 0;
+}
+
+int consys_reg_mng_reg_write(unsigned long addr, unsigned int value, unsigned int mask)
+{
+ void __iomem *vir_addr = NULL;
+
+ vir_addr = ioremap_nocache(addr, 0x100);
+ if (!vir_addr) {
+ pr_err("ioremap fail");
+ return -1;
+ }
+
+ CONSYS_REG_WRITE_MASK(vir_addr, value, mask);
+
+ iounmap(vir_addr);
+ return 0;
+}
+
+
+int consys_reg_mng_is_host_csr(unsigned long addr)
+{
+ if (g_consys_reg_ops &&
+ g_consys_reg_ops->consys_reg_mng_is_host_csr)
+ return g_consys_reg_ops->consys_reg_mng_is_host_csr(addr);
+ return -1;
+}
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/emi_mng.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/emi_mng.c
new file mode 100755
index 0000000..4dbcc18
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/emi_mng.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#include <linux/of.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include "osal.h"
+
+#include "consys_hw.h"
+#include "emi_mng.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+unsigned long long gConEmiSize = 0;
+phys_addr_t gConEmiPhyBase = 0x0;
+
+const struct consys_platform_emi_ops* consys_platform_emi_ops = NULL;
+
+struct consys_emi_addr_info connsys_emi_addr_info = {
+ .emi_ap_phy_addr = 0,
+ .emi_size = 0,
+ .md_emi_phy_addr = 0,
+ .md_emi_size = 0,
+};
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+
+int emi_mng_set_region_protection(void)
+{
+ if (consys_platform_emi_ops &&
+ consys_platform_emi_ops->consys_ic_emi_mpu_set_region_protection)
+ return consys_platform_emi_ops->consys_ic_emi_mpu_set_region_protection();
+ return -1;
+}
+
+int emi_mng_set_remapping_reg(void)
+{
+ if (consys_platform_emi_ops &&
+ consys_platform_emi_ops->consys_ic_emi_set_remapping_reg)
+ return consys_platform_emi_ops->consys_ic_emi_set_remapping_reg(
+ connsys_emi_addr_info.emi_ap_phy_addr,
+ connsys_emi_addr_info.md_emi_phy_addr);
+ return -1;
+}
+
+struct consys_emi_addr_info* emi_mng_get_phy_addr(void)
+{
+ return &connsys_emi_addr_info;
+}
+
+int emi_mng_init(struct platform_device *pdev, const struct conninfra_plat_data* plat_data)
+{
+ unsigned int fw_emi_size = gConEmiSize;
+#if CFG_CONNINFRA_EMI_SUPPORT
+ struct device_node *np;
+ struct reserved_mem *rmem;
+
+ np = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
+
+ if (!np) {
+ pr_info("[%s] memory region not found.");
+ return -1;
+ }
+
+ rmem = of_reserved_mem_lookup(np);
+ of_node_put(np);
+ if (!rmem) {
+ pr_info("[%s] no memory-region");
+ return -1;
+ } else {
+ gConEmiPhyBase = rmem->base;
+ gConEmiSize = rmem->size;
+ }
+#else
+ pr_info("Conninfra not support EMI reservation for %04x", plat_data->chip_id);
+#endif /* CFG_CONNINFRA_EMI_SUPPORT */
+
+ if (consys_platform_emi_ops == NULL) {
+ consys_platform_emi_ops = (const struct consys_platform_emi_ops*)plat_data->platform_emi_ops;
+ }
+
+ if (consys_platform_emi_ops && consys_platform_emi_ops->consys_ic_emi_get_fw_emi_size)
+ fw_emi_size = consys_platform_emi_ops->consys_ic_emi_get_fw_emi_size();
+ pr_info("[emi_mng_init] gConEmiPhyBase = [0x%llx] size = [0x%llx] fw size = [0x%x] ops=[%p]",
+ gConEmiPhyBase, gConEmiSize, fw_emi_size, consys_platform_emi_ops);
+
+ if (gConEmiPhyBase) {
+ connsys_emi_addr_info.emi_ap_phy_addr = gConEmiPhyBase;
+ connsys_emi_addr_info.emi_size = gConEmiSize;
+ connsys_emi_addr_info.fw_emi_size = fw_emi_size;
+ } else {
+ pr_err("consys emi memory address gConEmiPhyBase invalid\n");
+ }
+
+ if (consys_platform_emi_ops &&
+ consys_platform_emi_ops->consys_ic_emi_get_md_shared_emi)
+ consys_platform_emi_ops->consys_ic_emi_get_md_shared_emi(
+ &connsys_emi_addr_info.md_emi_phy_addr,
+ &connsys_emi_addr_info.md_emi_size);
+
+ if (consys_platform_emi_ops &&
+ consys_platform_emi_ops->consys_ic_emi_mpu_set_region_protection)
+ consys_platform_emi_ops->consys_ic_emi_mpu_set_region_protection();
+
+ return 0;
+}
+
+int emi_mng_deinit(void)
+{
+ return 0;
+}
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/clock_mng.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/clock_mng.h
new file mode 100755
index 0000000..ff62830
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/clock_mng.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_CLOCK_MNG_H_
+#define _PLATFORM_CLOCK_MNG_H_
+
+#include "osal.h"
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _PLATFORM_CLOCK_MNG_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/consys_hw.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/consys_hw.h
new file mode 100755
index 0000000..3ff7b22
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/consys_hw.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_CONSYS_HW_H_
+#define _PLATFORM_CONSYS_HW_H_
+
+#include <linux/platform_device.h>
+
+#include "conninfra.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+#define CONN_SEMA_GET_SUCCESS 0
+#define CONN_SEMA_GET_FAIL 1
+
+#define CONN_SEMA_TIMEOUT (1*1000) /* 1ms */
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+struct conninfra_dev_cb {
+ int (*conninfra_suspend_cb) (void);
+ int (*conninfra_resume_cb) (void);
+ int (*conninfra_pmic_event_notifier) (unsigned int, unsigned int);
+ int (*conninfra_thermal_query_cb) (void*, int*);
+};
+
+typedef int(*CONSYS_PLT_CLK_GET_FROM_DTS) (struct platform_device *pdev);
+typedef int(*CONSYS_PLT_CLK_DETACH) (void);
+typedef int(*CONSYS_PLT_READ_REG_FROM_DTS) (struct platform_device *pdev);
+
+typedef int(*CONSYS_PLT_CLOCK_BUFFER_CTRL) (unsigned int enable);
+typedef int(*CONSYS_PLT_CONNINFRA_ON_POWER_CTRL) (unsigned int enable);
+typedef void(*CONSYS_PLT_SET_IF_PINMUX) (unsigned int enable);
+
+typedef int(*CONSYS_PLT_POLLING_CONSYS_CHIPID) (void);
+typedef int(*CONSYS_PLT_D_DIE_CFG) (void);
+typedef int(*CONSYS_PLT_SPI_MASTER_CFG) (unsigned int next_status);
+typedef int(*CONSYS_PLT_A_DIE_CFG) (void);
+typedef int(*CONSYS_PLT_AFE_WBG_CAL) (void);
+typedef int(*CONSYS_PLT_SUBSYS_PLL_INITIAL) (void);
+typedef int(*CONSYS_PLT_LOW_POWER_SETTING) (unsigned int curr_status, unsigned int next_status);
+typedef int(*CONSYS_PLT_CONNINFRA_WAKEUP) (void);
+typedef int(*CONSYS_PLT_CONNINFRA_SLEEP) (void);
+
+typedef void(*CONSYS_PLT_AFE_REG_SETTING) (void);
+typedef unsigned int(*CONSYS_PLT_SOC_CHIPID_GET) (void);
+
+typedef void(*CONSYS_PLT_FORCE_TRIGGER_ASSERT_DEBUG_PIN) (void);
+typedef int(*CONSYS_PLT_CO_CLOCK_TYPE) (void);
+
+typedef int(*CONSYS_PLT_CHECK_REG_READABLE) (void);
+typedef void(*CONSYS_PLT_CLOCK_FAIL_DUMP) (void);
+typedef int(*CONSYS_PLT_IS_CONNSYS_REG) (unsigned int addr);
+
+
+typedef int(*CONSYS_PLT_SPI_READ)(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data);
+typedef int(*CONSYS_PLT_SPI_WRITE)(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data);
+
+typedef int(*CONSYS_PLT_ADIE_TOP_CK_EN_ON)(enum consys_adie_ctl_type type);
+typedef int(*CONSYS_PLT_ADIE_TOP_CK_EN_OFF)(enum consys_adie_ctl_type type);
+
+typedef int(*CONSYS_PLT_SPI_CLOCK_SWITCH)(enum connsys_spi_speed_type type);
+
+typedef bool(*CONSYS_PLT_IS_RC_MODE_ENABLE)(void);
+typedef int(*CONSYS_PLT_SUBSYS_STATUS_UPDATE)(bool on, int radio);
+
+typedef unsigned int(*CONSYS_PLT_GET_HW_VER)(void);
+typedef int(*CONSYS_PLT_THERMAL_QUERY)(void);
+typedef int(*CONSYS_PLT_POWER_STATE)(void);
+
+typedef void(*CONSYS_PLT_CONFIG_SETUP)(void);
+
+typedef int(*CONSYS_PLT_BUS_CLOCK_CTRL)(enum consys_drv_type drv_type, unsigned int, int);
+
+typedef int(*CONSYS_PLT_THERMAL_REGISTER)(struct platform_device *pdev, struct conninfra_dev_cb* dev_cb);
+
+struct consys_hw_ops_struct {
+ /* load from dts */
+ CONSYS_PLT_CLK_GET_FROM_DTS consys_plt_clk_get_from_dts;
+ CONSYS_PLT_CLK_DETACH consys_plt_clk_detach;
+ CONSYS_PLT_THERMAL_REGISTER consys_plt_thermal_register;
+
+ /* clock */
+ CONSYS_PLT_CLOCK_BUFFER_CTRL consys_plt_clock_buffer_ctrl;
+ CONSYS_PLT_CO_CLOCK_TYPE consys_plt_co_clock_type;
+
+ /* POS */
+ /*CONSYS_IC_HW_SPM_CLK_GATING_ENABLE consys_ic_hw_spm_clk_gating_enable;*/
+ CONSYS_PLT_CONNINFRA_ON_POWER_CTRL consys_plt_conninfra_on_power_ctrl;
+ CONSYS_PLT_SET_IF_PINMUX consys_plt_set_if_pinmux;
+
+ CONSYS_PLT_POLLING_CONSYS_CHIPID consys_plt_polling_consys_chipid;
+ CONSYS_PLT_D_DIE_CFG consys_plt_d_die_cfg;
+ CONSYS_PLT_SPI_MASTER_CFG consys_plt_spi_master_cfg;
+ CONSYS_PLT_A_DIE_CFG consys_plt_a_die_cfg;
+ CONSYS_PLT_AFE_WBG_CAL consys_plt_afe_wbg_cal;
+ CONSYS_PLT_SUBSYS_PLL_INITIAL consys_plt_subsys_pll_initial;
+ CONSYS_PLT_LOW_POWER_SETTING consys_plt_low_power_setting;
+
+ CONSYS_PLT_AFE_REG_SETTING consys_plt_afe_reg_setting;
+
+ CONSYS_PLT_SOC_CHIPID_GET consys_plt_soc_chipid_get;
+ CONSYS_PLT_CONNINFRA_WAKEUP consys_plt_conninfra_wakeup;
+ CONSYS_PLT_CONNINFRA_SLEEP consys_plt_conninfra_sleep;
+ CONSYS_PLT_IS_RC_MODE_ENABLE consys_plt_is_rc_mode_enable;
+ /*IC_BT_WIFI_SHARE_V33_SPIN_LOCK_INIT ic_bt_wifi_share_v33_spin_lock_init;*/
+ /*CONSYS_PLT_FORCE_TRIGGER_ASSERT_DEBUG_PIN consys_plt_force_trigger_assert_debug_pin;*/
+
+ CONSYS_PLT_CHECK_REG_READABLE consys_plt_check_reg_readable;
+ /* debug */
+ CONSYS_PLT_CLOCK_FAIL_DUMP consys_plt_clock_fail_dump;
+ CONSYS_PLT_GET_HW_VER consys_plt_get_hw_ver;
+
+ /* debug, used by STEP */
+ CONSYS_PLT_IS_CONNSYS_REG consys_plt_is_connsys_reg;
+
+ /* For SPI operation */
+ CONSYS_PLT_SPI_READ consys_plt_spi_read;
+ CONSYS_PLT_SPI_WRITE consys_plt_spi_write;
+
+ /* For a-die top_ck_en control */
+ CONSYS_PLT_ADIE_TOP_CK_EN_ON consys_plt_adie_top_ck_en_on;
+ CONSYS_PLT_ADIE_TOP_CK_EN_OFF consys_plt_adie_top_ck_en_off;
+
+ /* For SPI clock switch */
+ CONSYS_PLT_SPI_CLOCK_SWITCH consys_plt_spi_clock_switch;
+ CONSYS_PLT_SUBSYS_STATUS_UPDATE consys_plt_subsys_status_update;
+
+ /* thermal */
+ CONSYS_PLT_THERMAL_QUERY consys_plt_thermal_query;
+
+ /* power state */
+ CONSYS_PLT_POWER_STATE consys_plt_power_state;
+
+ CONSYS_PLT_CONFIG_SETUP consys_plt_config_setup;
+
+ CONSYS_PLT_BUS_CLOCK_CTRL consys_plt_bus_clock_ctrl;
+};
+
+struct consys_hw_env {
+ unsigned int adie_hw_version;
+ int is_rc_mode;
+};
+
+struct conninfra_plat_data {
+ const unsigned int chip_id;
+ const void* hw_ops;
+ const void* reg_ops;
+ const void* platform_emi_ops;
+ const void* platform_pmic_ops;
+};
+
+extern struct consys_hw_env conn_hw_env;
+extern struct consys_base_addr conn_reg;
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+int mtk_conninfra_drv_init(struct conninfra_dev_cb *dev_cb);
+int mtk_conninfra_drv_deinit(void);
+
+int consys_hw_pwr_off(unsigned int curr_status, unsigned int off_radio);
+int consys_hw_pwr_on(unsigned int curr_status, unsigned int on_radio);
+
+int consys_hw_wifi_power_ctl(unsigned int enable);
+int consys_hw_bt_power_ctl(unsigned int enable);
+int consys_hw_gps_power_ctl(unsigned int enable);
+int consys_hw_fm_power_ctl(unsigned int enable);
+int consys_hw_pmic_event_cb(unsigned int id, unsigned int event);
+
+unsigned int consys_hw_chipid_get(void);
+
+int consys_hw_get_clock_schematic(void);
+unsigned int consys_hw_get_hw_ver(void);
+
+/*******************************************************************************
+* tempoary for STEP
+********************************************************************************
+*/
+/*
+ * return
+ * 1 : can read
+ * 0 : can't read
+ * -1: not consys register
+ */
+int consys_hw_reg_readable(void);
+int consys_hw_is_connsys_reg(phys_addr_t addr);
+/*
+ * 0 means NO hang
+ * > 0 means hang!!
+ */
+int consys_hw_is_bus_hang(void);
+int consys_hw_dump_bus_status(void);
+
+int consys_hw_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data);
+int consys_hw_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data);
+
+int consys_hw_adie_top_ck_en_on(enum consys_adie_ctl_type type);
+int consys_hw_adie_top_ck_en_off(enum consys_adie_ctl_type type);
+
+/* NOTE: debug only*/
+int consys_hw_force_conninfra_wakeup(void);
+int consys_hw_force_conninfra_sleep(void);
+
+int consys_hw_spi_clock_switch(enum connsys_spi_speed_type type);
+
+struct platform_device *get_consys_device(void);
+struct consys_base_addr *get_conn_reg_base_addr(void);
+
+int consys_hw_therm_query(int *temp_ptr);
+void consys_hw_clock_fail_dump(void);
+
+int consys_hw_dump_power_state(void);
+void consys_hw_config_setup(void);
+int consys_hw_bus_clock_ctrl(enum consys_drv_type drv_type, unsigned int bus_clock, int status);
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _PLATFORM_CONSYS_HW_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/consys_reg_base.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/consys_reg_base.h
new file mode 100755
index 0000000..563fd19
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/consys_reg_base.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_CONSYS_REG_BASE_H_
+#define _PLATFORM_CONSYS_REG_BASE_H_
+
+struct consys_reg_base_addr {
+ unsigned long vir_addr;
+ unsigned long phy_addr;
+ unsigned long long size;
+};
+
+#endif /* _PLATFORM_CONSYS_REG_BASE_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/consys_reg_mng.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/consys_reg_mng.h
new file mode 100755
index 0000000..02b584f
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/consys_reg_mng.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_CONSYS_REG_MNG_H_
+#define _PLATFORM_CONSYS_REG_MNG_H_
+
+#include <linux/platform_device.h>
+
+#include "consys_hw.h"
+
+enum conn_dump_cpupcr_type
+{
+ CONN_DUMP_CPUPCR_TYPE_BT = 1,
+ CONN_DUMP_CPUPCR_TYPE_WF = 2,
+ CONN_DUMP_CPUPCR_TYPE_ALL = 3,
+};
+
+struct consys_reg_mng_ops {
+
+ int(*consys_reg_mng_init) (struct platform_device *pdev);
+ int(*consys_reg_mng_deinit) (void);
+ int(*consys_reg_mng_check_reable) (void);
+ int(*consys_reg_mng_is_consys_reg) (unsigned int addr);
+
+ int(*consys_reg_mng_is_bus_hang) (void);
+ int(*consys_reg_mng_dump_bus_status) (void);
+ int(*consys_reg_mng_dump_conninfra_status) (void);
+ int(*consys_reg_mng_dump_cpupcr) (enum conn_dump_cpupcr_type, int times, unsigned long interval_us);
+
+ int(*consys_reg_mng_is_host_csr) (unsigned long addr);
+
+ /* STEP Utility func */
+ unsigned long (*consys_reg_mng_validate_idx_n_offset) (unsigned int idx, unsigned long offset);
+ int (*consys_reg_mng_find_can_write_reg) (unsigned int * idx, unsigned long* offset);
+ unsigned long (*consys_reg_mng_get_phy_addr_by_idx) (unsigned int idx);
+ unsigned long (*consys_reg_mng_get_virt_addr_by_idx) (unsigned int idx);
+ int (*consys_reg_mng_get_chip_id_idx_offset) (unsigned int *idx, unsigned long *offset);
+ int (*consys_reg_mng_get_reg_symbol_num) (void);
+};
+
+int consys_reg_mng_init(struct platform_device *pdev, const struct conninfra_plat_data* plat_data);
+int consys_reg_mng_deinit(void);
+
+int consys_reg_mng_reg_readable(void);
+int consys_reg_mng_is_connsys_reg(phys_addr_t addr);
+int consys_reg_mng_reg_read(unsigned long addr, unsigned int *value, unsigned int mask);
+int consys_reg_mng_reg_write(unsigned long addr, unsigned int value, unsigned int mask);
+int consys_reg_mng_is_bus_hang(void);
+int consys_reg_mng_dump_bus_status(void);
+int consys_reg_mng_dump_conninfra_status(void);
+int consys_reg_mng_dump_cpupcr(enum conn_dump_cpupcr_type dump_type, int times, unsigned long interval_us);
+
+int consys_reg_mng_is_host_csr(unsigned long addr);
+
+
+/**************** step *************************/
+/*********************************************
+ * validate the reg base address index and offset
+ * Parameters:
+ * idx: base address index
+ * offset: offset from base address
+ *
+ * Return
+ * > 0 : phy address of index
+ * = 0 : validate fail
+ *********************************************/
+unsigned long consys_reg_mng_validate_idx_n_offset(unsigned int idx, unsigned long offset);
+
+/* for consys_step_test */
+/*********************************************
+ * validate the reg base address index and offset
+ * Parameters:
+ * offset : offset of base address index
+ *
+ * Return
+ * > 0 : phy address of index
+ * < 0 : can't find
+ *********************************************/
+int consys_reg_mng_find_can_write_reg(unsigned int *idx, unsigned long* offset);
+unsigned long consys_reg_mng_get_phy_addr_by_idx(unsigned int idx);
+unsigned long consys_reg_mng_get_virt_addr_by_idx(unsigned int idx);
+
+int consys_reg_mng_get_chip_id_idx_offset(unsigned int *idx, unsigned long *offset);
+int consys_reg_mng_get_reg_symbol_num(void);
+
+#endif /* _PLATFORM_CONSYS_REG_MNG_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/consys_reg_util.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/consys_reg_util.h
new file mode 100755
index 0000000..e5d06ec
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/consys_reg_util.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_CONSYS_REG_UTIL_H_
+#define _PLATFORM_CONSYS_REG_UTIL_H_
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+/* platform dependent */
+#include "plat_def.h"
+
+#define KBYTE (1024*sizeof(char))
+
+#define GENMASK(h, l) \
+ (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
+
+#define GET_BIT_MASK(value, mask) ((value) & (mask))
+#define SET_BIT_MASK(pdest, value, mask) (*(pdest) = (GET_BIT_MASK(*(pdest), ~(mask)) | GET_BIT_MASK(value, mask)))
+#define GET_BIT_RANGE(data, end, begin) ((data) & GENMASK(end, begin))
+#define SET_BIT_RANGE(pdest, data, end, begin) (SET_BIT_MASK(pdest, data, GENMASK(end, begin)))
+
+#define CONSYS_SET_BIT(REG, BITVAL) (*((volatile unsigned int *)(REG)) |= ((unsigned int)(BITVAL)))
+#define CONSYS_CLR_BIT(REG, BITVAL) ((*(volatile unsigned int *)(REG)) &= ~((unsigned int)(BITVAL)))
+#define CONSYS_CLR_BIT_WITH_KEY(REG, BITVAL, KEY) {\
+ unsigned int val = (*(volatile unsigned int *)(REG)); \
+ val &= ~((unsigned int)(BITVAL)); \
+ val |= ((unsigned int)(KEY)); \
+ (*(volatile unsigned int *)(REG)) = val;\
+}
+#define CONSYS_REG_READ(addr) (*((volatile unsigned int *)(addr)))
+#define CONSYS_REG_READ_BIT(addr, BITVAL) (*((volatile unsigned int *)(addr)) & ((unsigned int)(BITVAL)))
+#define CONSYS_REG_WRITE(addr, data) mt_reg_sync_writel(data, addr)
+#define CONSYS_REG_WRITE_RANGE(reg, data, end, begin) {\
+ unsigned int val = CONSYS_REG_READ(reg); \
+ SET_BIT_RANGE(&val, data, end, begin); \
+ CONSYS_REG_WRITE(reg, val); \
+}
+#define CONSYS_REG_WRITE_MASK(reg, data, mask) {\
+ unsigned int val = CONSYS_REG_READ(reg); \
+ SET_BIT_MASK(&val, data, mask); \
+ CONSYS_REG_WRITE(reg, val); \
+}
+
+/*
+ * Write value with value_offset bits of right shift and size bits,
+ * to the reg_offset-th bit of address reg
+ * value -----------XXXXXXXXXXXX-------------------
+ * |<--size-->|<--value_offset-->|
+ * reg -------------OOOOOOOOOOOO-----------------
+ * |<--size-->|<--reg_offset-->|
+ * result -------------XXXXXXXXXXXX-----------------
+ */
+#define CONSYS_REG_WRITE_OFFSET_RANGE(reg, value, reg_offset, value_offset, size) ({\
+ unsigned int data = (value) >> (value_offset); \
+ data = GET_BIT_RANGE(data, size, 0); \
+ data = data << (reg_offset); \
+ CONSYS_REG_WRITE_RANGE(reg, data, ((reg_offset) + ((size) - 1)), reg_offset); \
+})
+
+#define CONSYS_REG_WRITE_BIT(reg, offset, val) CONSYS_REG_WRITE_OFFSET_RANGE(reg, ((val) & 1), offset, 0, 1)
+
+#define CONSYS_REG_BIT_POLLING(addr, bit_index, exp_val, loop, delay, success) {\
+ unsigned int polling_count = 0; \
+ unsigned int reg_value = 0; \
+ success = 0; \
+ reg_value = (CONSYS_REG_READ_BIT(addr, (0x1 << bit_index)) >> bit_index); \
+ while (reg_value != exp_val) { \
+ if (polling_count > loop) { \
+ success = -1; \
+ break; \
+ } \
+ reg_value = (CONSYS_REG_READ_BIT(addr, (0x1 << bit_index)) >> bit_index); \
+ udelay(delay); \
+ polling_count++; \
+ } \
+}
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _PLATFORM_CONSYS_REG_UTIL_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/emi_mng.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/emi_mng.h
new file mode 100755
index 0000000..f894e55
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/emi_mng.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_EMI_MNG_H_
+#define _PLATFORM_EMI_MNG_H_
+
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include "osal.h"
+
+#include "consys_hw.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+struct consys_emi_addr_info {
+ /* This include BT/WF FW and WFDMA */
+ phys_addr_t emi_ap_phy_addr;
+ unsigned int emi_size;
+ unsigned int fw_emi_size;
+ unsigned int wfdma_emi_size;
+ /* MCIF EMI get from MD */
+ phys_addr_t md_emi_phy_addr;
+ unsigned int md_emi_size;
+};
+
+typedef int(*CONSYS_IC_EMI_MPU_SET_REGION_PROTECTION) (void);
+typedef unsigned int(*CONSYS_IC_EMI_SET_REMAPPING_REG) (phys_addr_t, phys_addr_t);
+typedef void(*CONSYS_IC_EMI_GET_MD_SHARED_EMI) (phys_addr_t* phy_addr, unsigned int *size);
+typedef unsigned int (*CONSYS_IC_GET_FW_EMI_SIZE)(void);
+
+struct consys_platform_emi_ops {
+ CONSYS_IC_EMI_MPU_SET_REGION_PROTECTION consys_ic_emi_mpu_set_region_protection;
+ CONSYS_IC_EMI_SET_REMAPPING_REG consys_ic_emi_set_remapping_reg;
+ CONSYS_IC_EMI_GET_MD_SHARED_EMI consys_ic_emi_get_md_shared_emi;
+ CONSYS_IC_GET_FW_EMI_SIZE consys_ic_emi_get_fw_emi_size;
+};
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+int emi_mng_init(struct platform_device *pdev, const struct conninfra_plat_data* plat_data);
+int emi_mng_deinit(void);
+
+int emi_mng_set_region_protection(void);
+int emi_mng_set_remapping_reg(void);
+struct consys_emi_addr_info* emi_mng_get_phy_addr(void);
+
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _PLATFORM_EMI_MNG_H_ */
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/plat_def.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/plat_def.h
new file mode 100755
index 0000000..7c2a4f6
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/plat_def.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_DEF_H_
+#define _PLATFORM_DEF_H_
+
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#define mt_reg_sync_writel(v, a) \
+ do { \
+ writel((v), (void __force __iomem *)((a))); \
+ mb(); \
+ } while (0)
+
+#endif /* _PLATFORM_DEF_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/pmic_mng.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/pmic_mng.h
new file mode 100755
index 0000000..8ee3243
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/include/pmic_mng.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_PMIC_MNG_H_
+#define _PLATFORM_PMIC_MNG_H_
+
+#include <linux/platform_device.h>
+
+#include "consys_hw.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+typedef int(*CONSYS_PMIC_GET_FROM_DTS) (
+ struct platform_device *pdev,
+ struct conninfra_dev_cb* dev_cb);
+
+typedef int(*CONSYS_PMIC_COMMON_POWER_CTRL) (unsigned int enable);
+
+typedef int(*CONSYS_PMIC_WIFI_POWER_CTRL) (unsigned int enable);
+typedef int(*CONSYS_PMIC_BT_POWER_CTRL) (unsigned int enable);
+typedef int(*CONSYS_PMIC_GPS_POWER_CTRL) (unsigned int enable);
+typedef int(*CONSYS_PMIC_FM_POWER_CTRL) (unsigned int enable);
+typedef int(*CONSYS_PMIC_EVENT_NOTIFIER) (unsigned int id, unsigned int event);
+
+struct consys_platform_pmic_ops {
+ CONSYS_PMIC_GET_FROM_DTS consys_pmic_get_from_dts;
+ /* vcn 18 */
+ CONSYS_PMIC_COMMON_POWER_CTRL consys_pmic_common_power_ctrl;
+ CONSYS_PMIC_WIFI_POWER_CTRL consys_pmic_wifi_power_ctrl;
+ CONSYS_PMIC_BT_POWER_CTRL consys_pmic_bt_power_ctrl;
+ CONSYS_PMIC_GPS_POWER_CTRL consys_pmic_gps_power_ctrl;
+ CONSYS_PMIC_FM_POWER_CTRL consys_pmic_fm_power_ctrl;
+ CONSYS_PMIC_EVENT_NOTIFIER consys_pmic_event_notifier;
+};
+
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+int pmic_mng_init(
+ struct platform_device *pdev,
+ struct conninfra_dev_cb* dev_cb,
+ const struct conninfra_plat_data* plat_data);
+int pmic_mng_deinit(void);
+
+int pmic_mng_common_power_ctrl(unsigned int enable);
+int pmic_mng_wifi_power_ctrl(unsigned int enable);
+int pmic_mng_bt_power_ctrl(unsigned int enable);
+int pmic_mng_gps_power_ctrl(unsigned int enable);
+int pmic_mng_fm_power_ctrl(unsigned int enable);
+int pmic_mng_event_cb(unsigned int id, unsigned int event);
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _PLATFORM_PMIC_MNG_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/include/mt6880.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/include/mt6880.h
new file mode 100755
index 0000000..a360124
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/include/mt6880.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_MT6880_H_
+#define _PLATFORM_MT6880_H_
+
+enum conn_semaphore_type
+{
+ CONN_SEMA_CHIP_POWER_ON_INDEX = 0,
+ CONN_SEMA_CALIBRATION_INDEX = 1,
+ CONN_SEMA_FW_DL_INDEX = 2,
+ CONN_SEMA_CLOCK_SWITCH_INDEX = 3,
+ CONN_SEMA_CCIF_INDEX = 4,
+ CONN_SEMA_COEX_INDEX = 5,
+ CONN_SEMA_USB_EP0_INDEX = 6,
+ CONN_SEMA_USB_SHARED_INFO_INDEX = 7,
+ CONN_SEMA_USB_SUSPEND_INDEX = 8,
+ CONN_SEMA_USB_RESUME_INDEX = 9,
+ CONN_SEMA_PCIE_INDEX = 10,
+ CONN_SEMA_RFSPI_INDEX = 11,
+ CONN_SEMA_EFUSE_INDEX = 12,
+ CONN_SEMA_THERMAL_INDEX = 13,
+ CONN_SEMA_FLASH_INDEX = 14,
+ CONN_SEMA_DEBUG_INDEX = 15,
+ CONN_SEMA_WIFI_LP_INDEX = 16,
+ CONN_SEMA_PATCH_DL_INDEX = 17,
+ CONN_SEMA_SHARED_VAR_INDEX = 18,
+ CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX = 19,
+ CONN_SEMA_NUM_MAX = 32 /* can't be omitted */
+};
+
+int consys_platform_spm_conn_ctrl(unsigned int enable);
+int consys_co_clock_type(void);
+
+struct consys_plat_thermal_data {
+ int thermal_b;
+ int slop_molecule;
+ int offset;
+ unsigned int efuse0;
+ unsigned int efuse1;
+ unsigned int efuse2;
+ unsigned int efuse3;
+};
+
+void update_thermal_data(struct consys_plat_thermal_data* input);
+#endif /* _PLATFORM_MT6880_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/include/mt6880_consys_reg.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/include/mt6880_consys_reg.h
new file mode 100755
index 0000000..2cb7ebd
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/include/mt6880_consys_reg.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_MT6880_CONSYS_REG_H_
+#define _PLATFORM_MT6880_CONSYS_REG_H_
+
+#include "consys_reg_base.h"
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+enum consys_base_addr_index {
+ CONN_INFRA_RGU_BASE = 0, /* 0x1800_0000 */
+ CONN_INFRA_CFG_BASE = 1, /* 0x1800_1000 */
+ CONN_HOST_CSR_TOP_BASE = 2, /* 0x1806_0000 */
+ INFRACFG_AO_BASE = 3, /* 0x1000_1000 */
+ TOPRGU_BASE = 4, /* 0x1000_7000 */
+ SPM_BASE = 5, /* 0x1000_6000 */
+ INFRACFG_BASE = 6, /* 0x1020_e000 */
+ CONN_WT_SLP_CTL_REG = 7, /* 0x1800_5000 */
+ CONN_AFE_CTL = 8, /* 0x1800_3000 */
+ GPIO_BASE = 9, /* 0x1000_5000 */
+ CONN_RF_SPI_MST_REG_BASE = 10, /* 0x1800_4000 */
+ CONN_SEMAPHORE_BASE = 11, /* 0x1807_0000 */
+ CONN_TOP_THERM_CTL_BASE = 12, /* 0x1800_2000 */
+ IOCFG_BM_BASE = 13, /* 0x11d1_0000 */
+ CONN_DEBUG_CTRL = 14, /* 0x1800_F000 */
+ CONN_INFRA_CLKGEN_ON_TOP = 15, /* 0x1800_9000 */
+ CONN_INFRA_BUS_CR = 16, /* 0x1800_E000, offset 0x200~0x334 */
+ CONN_INFRA_DEBUG_CTRL_AO = 17, /* 0x1802_f000, offset 0x0~0x424 */
+
+ CONSYS_BASE_ADDR_MAX
+};
+
+
+struct consys_base_addr {
+ struct consys_reg_base_addr reg_base_addr[CONSYS_BASE_ADDR_MAX];
+};
+
+extern struct consys_base_addr conn_reg;
+
+#define REG_CONN_INFRA_RGU_ADDR conn_reg.reg_base_addr[CONN_INFRA_RGU_BASE].vir_addr
+#define REG_CONN_INFRA_CFG_ADDR conn_reg.reg_base_addr[CONN_INFRA_CFG_BASE].vir_addr
+#define REG_CONN_HOST_CSR_ADDR conn_reg.reg_base_addr[CONN_HOST_CSR_TOP_BASE].vir_addr
+#define REG_INFRACFG_AO_ADDR conn_reg.reg_base_addr[INFRACFG_AO_BASE].vir_addr
+
+#define REG_TOP_RGU_ADDR conn_reg.reg_base_addr[TOPRGU_BASE].vir_addr
+#define REG_SPM_BASE_ADDR conn_reg.reg_base_addr[SPM_BASE].vir_addr
+#define REG_INFRACFG_BASE_ADDR conn_reg.reg_base_addr[INFRACFG_BASE].vir_addr
+#define REG_CONN_WT_SPL_CTL_ADDR conn_reg.reg_base_addr[CONN_WT_SLP_CTL_REG].vir_addr
+
+#define REG_CONN_AFE_CTL_BASE_ADDR conn_reg.reg_base_addr[CONN_AFE_CTL].vir_addr
+#define REG_GPIO_BASE_ADDR conn_reg.reg_base_addr[GPIO_BASE].vir_addr
+#define REG_CONN_RFSPI_ADDR conn_reg.reg_base_addr[CONN_RF_SPI_MST_REG_BASE].vir_addr
+#define REG_CONN_SEMAPHORE_ADDR conn_reg.reg_base_addr[CONN_SEMAPHORE_BASE].vir_addr
+
+#define REG_CONN_TOP_THERM_CTL_ADDR conn_reg.reg_base_addr[CONN_TOP_THERM_CTL_BASE].vir_addr
+#define REG_IOCFG_BM_ADDR conn_reg.reg_base_addr[IOCFG_BM_BASE].vir_addr
+#define REG_CONN_DEBUG_CTRL_ADDR conn_reg.reg_base_addr[CONN_DEBUG_CTRL].vir_addr
+#define REG_CONN_INFRA_CLKGEN_ON_TOP_ADDR conn_reg.reg_base_addr[CONN_INFRA_CLKGEN_ON_TOP].vir_addr
+
+#define REG_CONN_INFRA_BUS_CR_ADDR conn_reg.reg_base_addr[CONN_INFRA_BUS_CR].vir_addr
+#define REG_CONN_INFRA_DEBUG_CTRL_AO conn_reg.reg_base_addr[CONN_INFRA_DEBUG_CTRL_AO].vir_addr
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+struct consys_base_addr* get_conn_reg_base_addr(void);
+
+#endif /* _PLATFORM_MT6880_CONSYS_REG_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/include/mt6880_consys_reg_offset.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/include/mt6880_consys_reg_offset.h
new file mode 100755
index 0000000..57112a3
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/include/mt6880_consys_reg_offset.h
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_MT6880_CONSYS_REG_OFFSET_H_
+#define _PLATFORM_MT6880_CONSYS_REG_OFFSET_H_
+
+/**********************************************************************/
+/* Base: infracfg_ao (0x1000_1000) */
+/**********************************************************************/
+#define INFRA_TOPAXI_PROTECTEN 0x0220
+#define INFRA_TOPAXI_PROTECTEN_STA1 0x0228
+#define INFRA_TOPAXI_PROTECTEN_SET 0x02a0
+#define INFRA_TOPAXI_PROTECTEN_CLR 0x02a4
+
+/**********************************************************************/
+/* Base: GPIO (0x1000_5000) */
+/**********************************************************************/
+#define GPIO_MODE15_SET 0x03f4
+#define GPIO_MODE15_CLR 0x03f8
+#define GPIO_MODE16_SET 0x0404
+#define GPIO_MODE16_CLR 0x0408
+
+/**********************************************************************/
+/* Base: SPM (0x1000_6000) */
+/**********************************************************************/
+#define SPM_POWERON_CONFIG_EN 0x0000
+#define SPM_PCM_REG0_DATA 0x0100
+#define SPM_PCM_REG13_DATA 0x0110
+#define SPM_SRC_REQ_STA_0 0x0114
+#define SPM_PWR_STATUS 0x016c
+#define SPM_PWR_STATUS_2ND 0x0170
+#define SPM_CONN_PWR_CON 0x0304
+#define SPM_RC_CMD_STA_0 0x0E04
+#define SPM_RC_M04_REQ_STA_0 0x0E28
+#define SPM_RC_M05_REQ_STA_0 0x0E2C
+#define SPM_RC_M06_REQ_STA_0 0x0E30
+#define SPM_RC_M07_REQ_STA_0 0x0E34
+
+/**********************************************************************/
+/* Base: TOP RGU (0x1000_7000) */
+/**********************************************************************/
+#define TOP_RGU_WDT_SWSYSRST 0x0018
+
+/**********************************************************************/
+/* Base: IOCFG_BM (0x11D1_0000) */
+/**********************************************************************/
+#define IOCFG_BM_DRV_CFG0_SET 0x0004
+#define IOCFG_BM_DRV_CFG0_CLR 0x0008
+#define IOCFG_BM_PD_CFG0_SET 0x00d4
+#define IOCFG_BM_PD_CFG0_CLR 0x00d8
+#define IOCFG_BM_PU_CFG0_SET 0x0114
+#define IOCFG_BM_PU_CFG0_CLR 0x0118
+
+
+/**********************************************************************/
+/* Base: conn_infra_rgu (0x1800_0000) */
+/**********************************************************************/
+#define CONN_INFRA_RGU_CONN_INFRA_OFF_TOP_PWR_CTL 0x0000
+#define CONN_INFRA_RGU_SYSRAM_HWCTL_PDN_SYSRAM_HWCTL_PDN 0x0050
+#define CONN_INFRA_RGU_SYSRAM_HWCTL_SLP_SYSRAM_HWCTL_SLP 0x0054
+
+/**********************************************************************/
+/* Base: conn_infra_cfg (0x1800_1000), offset 0x0~0x654 */
+/**********************************************************************/
+#define CONN_HW_VER_OFFSET 0x0000
+#define CONN_CFG_ID_OFFSET 0x0004
+#define AP2CONN_EFUSE_DATA 0x0020
+#define CONN_INFRA_CFG_ADIE_CTL 0x0030
+#define CONN_INFRA_CFG_PWRCTRL0 0x0200
+#define CONN_INFRA_CFG_OSC_CTL_0 0x0300
+#define CONN_INFRA_CFG_OSC_CTL_1 0x0304
+#define CONN_INFRA_CFG_RC_CTL_0 0x0380
+#define CONN_INFRA_CFG_RC_CTL_0_GPS 0x0390
+#define CONN_INFRA_CFG_RC_CTL_1_GPS 0x0394
+#define CONN_INFRA_CFG_RC_CTL_0_TOP 0x03c0
+#define CONN_INFRA_CFG_RC_CTL_1_TOP 0x03c4
+#define CONN_INFRA_CFG_EMI_CTL_0 0x0400
+#define CONN_INFRA_CONN2AP_SLP_STATUS 0x0504
+#define CONN_INFRA_AP2CONN_SLP_STATUS 0x0514
+#define CONN_INFRA_ON_BUS_SLP_STATUS 0x0524
+#define CONN_INFRA_OFF_BUS_SLP_STATUS 0x0534
+#define GALS_CONN2GPS_SLP_STATUS 0x0574
+#define GALS_GPS2CONN_SLP_STATUS 0x0584
+
+#define CONN_HW_VER 0x02030100
+#define CONN_CFG_ID 0x3
+
+
+
+/**********************************************************************/
+/* Base: conn_top_therm_ctl (0x1800_2000) */
+/**********************************************************************/
+#define CONN_TOP_THERM_CTL_THERMCR1 0x0004
+#define CONN_TOP_THERM_CTL_THERM_AADDR 0x0018
+#define CONN_TOP_THERM_CTL_THERM_CAL_EN 0x0024
+
+/**********************************************************************/
+/* Base: conn_afe_ctl(0x1800_3000) */
+/**********************************************************************/
+#define CONN_AFE_CTL_RG_DIG_EN_02 0x0004
+#define CONN_AFE_CTL_RG_PLL_STB_TIME 0x00f4
+
+/**********************************************************************/
+/* Base: conn_rf_spi_mst_reg(0x1800_4000) */
+/**********************************************************************/
+#define CONN_RF_SPI_MST_REG_SPI_STA 0x0000
+#define CONN_RF_SPI_MST_REG_SPI_CRTL 0x0004
+#define CONN_RF_SPI_MST_REG_FM_CTRL 0x000c
+#define CONN_RF_SPI_MST_REG_SPI_WF_ADDR 0x0010
+#define CONN_RF_SPI_MST_REG_SPI_WF_WDAT 0x0014
+#define CONN_RF_SPI_MST_REG_SPI_WF_RDAT 0x0018
+#define CONN_RF_SPI_MST_REG_SPI_BT_ADDR 0x0020
+#define CONN_RF_SPI_MST_REG_SPI_BT_WDAT 0x0024
+#define CONN_RF_SPI_MST_REG_SPI_BT_RDAT 0x0028
+#define CONN_RF_SPI_MST_REG_SPI_FM_ADDR 0x0030
+#define CONN_RF_SPI_MST_REG_SPI_FM_WDAT 0x0034
+#define CONN_RF_SPI_MST_REG_SPI_FM_RDAT 0x0038
+#define CONN_RF_SPI_MST_REG_SPI_TOP_ADDR 0x0050
+#define CONN_RF_SPI_MST_REG_SPI_TOP_WDAT 0x0054
+#define CONN_RF_SPI_MST_REG_SPI_TOP_RDAT 0x0058
+#define CONN_RF_SPI_MST_REG_SPI_GPS_GPS_ADDR 0x0210
+#define CONN_RF_SPI_MST_REG_SPI_GPS_GPS_WDAT 0x0214
+#define CONN_RF_SPI_MST_REG_SPI_GPS_GPS_RDAT 0x0218
+
+/**********************************************************************/
+/* Base: conn_wt_slp_ctl_reg(0x1800_5000) */
+/**********************************************************************/
+#define CONN_WT_SLP_CTL_REG_WB_SLP_CTL 0x0004
+#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR1 0x0010
+#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR2 0x0014
+#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR3 0x0018
+#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR4 0x001c
+#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR5 0x0020
+#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR6 0x0024
+#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR7 0x0028
+#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR8 0x002c
+#define CONN_WT_SLP_CTL_REG_WB_BG_ON1 0x0030
+#define CONN_WT_SLP_CTL_REG_WB_BG_ON2 0x0034
+#define CONN_WT_SLP_CTL_REG_WB_BG_ON3 0x0038
+#define CONN_WT_SLP_CTL_REG_WB_BG_ON4 0x003c
+#define CONN_WT_SLP_CTL_REG_WB_BG_ON5 0x0040
+#define CONN_WT_SLP_CTL_REG_WB_BG_ON6 0x0044
+#define CONN_WT_SLP_CTL_REG_WB_BG_ON7 0x0048
+#define CONN_WT_SLP_CTL_REG_WB_BG_ON8 0x004c
+#define CONN_WT_SLP_CTL_REG_WB_BG_OFF1 0x0050
+#define CONN_WT_SLP_CTL_REG_WB_BG_OFF2 0x0054
+#define CONN_WT_SLP_CTL_REG_WB_BG_OFF3 0x0058
+#define CONN_WT_SLP_CTL_REG_WB_BG_OFF4 0x005c
+#define CONN_WT_SLP_CTL_REG_WB_BG_OFF5 0x0060
+#define CONN_WT_SLP_CTL_REG_WB_BG_OFF6 0x0064
+#define CONN_WT_SLP_CTL_REG_WB_BG_OFF7 0x0068
+#define CONN_WT_SLP_CTL_REG_WB_BG_OFF8 0x006c
+#define CONN_WT_SLP_CTL_REG_WF_CK_ADDR 0x0070
+#define CONN_WT_SLP_CTL_REG_WF_WAKE_ADDR 0x0074
+#define CONN_WT_SLP_CTL_REG_WF_ZPS_ADDR 0x0078
+#define CONN_WT_SLP_CTL_REG_BT_CK_ADDR 0x007c
+#define CONN_WT_SLP_CTL_REG_BT_WAKE_ADDR 0x0080
+#define CONN_WT_SLP_CTL_REG_TOP_CK_ADDR 0x0084
+#define CONN_WT_SLP_CTL_REG_GPS_CK_ADDR 0x0088
+#define CONN_WT_SLP_CTL_REG_WF_B0_CMD_ADDR 0x008c
+#define CONN_WT_SLP_CTL_REG_WF_B1_CMD_ADDR 0x0090
+#define CONN_WT_SLP_CTL_REG_GPS_RFBUF_ADDR 0x0094
+#define CONN_WT_SLP_CTL_REG_GPS_L5_EN_ADDR 0x0098
+#define CONN_WT_SLP_WB_SLP_TOP_CK_0 0x0120
+
+/**********************************************************************/
+/* Base: conn_infra_gpt(0x1800_7000) */
+/**********************************************************************/
+#define CONN_INFRA_GPT_BASE 0x18007000
+#define GPT2_AP_ENABLE 0x0038
+
+/**********************************************************************/
+/* Base: conn_infra_clkgen_on_top(0x1800_9000) */
+/**********************************************************************/
+#define CONN_INFRA_CKGEN_BUS_BPLL_DIV_2 0x0004
+#define CONN_INFRA_CLKGEN_ON_TOP_CKGEN_BUS 0x0a00
+
+/**********************************************************************/
+/* Base: conn_infra_bus_cr (0x1800_E000), offset 0x200~0x334 */
+/**********************************************************************/
+#define CONN_INFRA_BUS_CR_GALS_AP2CONN_GALS_DBG 0x02a0
+#define CONN_INFRA_BUS_CR_GALS_CONN2AP_GALS_DBG 0x02a4
+#define CONN_INFRA_BUS_CR_GALS_GPS2CONN_GALS_DBG 0x02B0
+#define CONN_INFRA_BUS_CR_GALS_CONN2GPS_GALS_DBG 0x02B4
+#define CONN_INFRA_BUS_CR_GALS_CONN2GPS_CTRL_0 0x02CC
+#define CONN_INFRA_BUS_OFF_TIMEOUT_CTRL 0x0300
+#define CONN_INFRA_BUS_ON_TIMEOUT_CTRL 0x031C
+
+/**********************************************************************/
+/* Base: debug_ctrl (0x1800_f000) */
+/**********************************************************************/
+#define CONN_DEBUG_CTRL_REG_OFFSET 0x0000
+
+/**********************************************************************/
+/* Base: conn_infra_debug_ctrl_ao (0x1802_f000) */
+/**********************************************************************/
+#define CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_ON_CTRL0 0x000
+#define CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_ON_CTRL1 0x004
+#define CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_ON_CTRL2 0x008
+#define CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_ON_RESULT0 0x400
+#define CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_ON_RESULT1 0x404
+#define CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_ON_RESULT2 0x408
+#define CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_ON_RESULT3 0x40C
+#define CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_ON_RESULT4 0x410
+#define CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_ON_RESULT5 0x414
+#define CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_ON_RESULT6 0x418
+#define CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_ON_RESULT7 0x41C
+#define CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_ON_RESULT8 0x420
+#define CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_ON_RESULT9 0x424
+
+
+/**********************************************************************/
+/* Base: conn_host_csr_top (0x1806_0000) */
+/**********************************************************************/
+#define CONN_INFRA_ON_BUS_TIMEOUT_IRQ 0x014c
+#define CONN_HOST_CSR_TOP_CONN_INFRA_CFG_DBG_SEL 0x015c
+#define CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP 0x01a0
+#define CONN2AP_REMAP_GPS_PERI_BASE_ADDR 0x01dc
+#define CONN_HOST_CSR_TOP_DBG_DUMMY_0 0x02c0
+#define CONN_HOST_CSR_TOP_DBG_DUMMY_2 0x02c8
+#define CONN_HOST_CSR_TOP_DBG_DUMMY_3 0x02cc
+#define CONN_HOST_CSR_TOP_DBG_DUMMY_5 0x02d4
+#define CONN_HOST_CSR_TOP_CONN_INFRA_BUS_OFF_DBG_1 0x0414
+#define CONN_HOST_CSR_TOP_CONN_INFRA_BUS_OFF_DBG_2 0x0418
+#define CONN_HOST_CSR_TOP_CONN_INFRA_BUS_OFF_TOP_DBG_1 0x041C
+#define CONN_HOST_CSR_TOP_CONN_INFRA_BUS_OFF_TOP_DBG_2 0x0420
+#define CONN_HOST_CSR_TOP_CONN_INFRA_BUS_ON_TOP_DBG_APB_1 0x042C
+#define CONN_HOST_CSR_TOP_CONN_INFRA_BUS_ON_TOP_DBG_APB_2 0x0430
+
+
+
+#define TOP_BUS_MUC_STAT_HCLK_FR_CK_DETECT_BIT (0x1 << 1)
+#define TOP_BUS_MUC_STAT_OSC_CLK_DETECT_BIT (0x1 << 2)
+
+/**********************************************************************/
+/* Base: conn_semaphore(0x1807_0000) */
+/**********************************************************************/
+#define CONN_SEMA_OWN_BY_M0_STA_REP 0x0400
+#define CONN_SEMA_OWN_BY_M1_STA_REP 0x1400
+#define CONN_SEMAPHORE_M2_OWN_STA 0x2000
+#define CONN_SEMAPHORE_M2_OWN_REL 0x2200
+#define CONN_SEMA_OWN_BY_M2_STA_REP 0x2400
+#define CONN_SEMA_OWN_BY_M3_STA_REP 0x3400
+
+/**********************************************************************/
+/* A-die CR */
+/**********************************************************************/
+#define ATOP_CHIP_ID 0x02c
+#define ATOP_RG_TOP_THADC_BG 0x034
+#define ATOP_RG_TOP_THADC 0x038
+#define ATOP_EFUSE_CTRL 0x108
+#define ATOP_EFUSE_RDATA0 0x130
+#define ATOP_EFUSE_RDATA1 0x134
+#define ATOP_EFUSE_RDATA2 0x138
+#define ATOP_EFUSE_RDATA3 0x13c
+#define ATOP_RG_TOP_XTAL_01 0xA18
+#define ATOP_RG_TOP_XTAL_02 0xA1C
+
+#endif /* _PLATFORM_MT6880_CONSSY_REG_OFFSET_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/include/mt6880_pmic.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/include/mt6880_pmic.h
new file mode 100755
index 0000000..de954ad
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/include/mt6880_pmic.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_MT6880_PMIC_H_
+#define _PLATFORM_MT6880_PMIC_H_
+
+#include "osal.h"
+#include "pmic_mng.h"
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+struct consys_platform_pmic_ops* get_consys_platform_pmic_ops(void);
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _PLATFORM_MT6880_PMIC_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/include/mt6880_pos.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/include/mt6880_pos.h
new file mode 100755
index 0000000..50ad78d
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/include/mt6880_pos.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_MT6880_POS_H_
+#define _PLATFORM_MT6880_POS_H_
+
+
+unsigned int consys_emi_set_remapping_reg(phys_addr_t, phys_addr_t);
+
+int consys_conninfra_on_power_ctrl(unsigned int enable);
+int consys_conninfra_wakeup(void);
+int consys_conninfra_sleep(void);
+void consys_set_if_pinmux(unsigned int enable);
+int consys_polling_chipid(void);
+
+int connsys_d_die_cfg(void);
+int connsys_spi_master_cfg(unsigned int);
+int connsys_a_die_cfg(void);
+int connsys_afe_wbg_cal(void);
+int connsys_subsys_pll_initial(void);
+int connsys_low_power_setting(unsigned int, unsigned int);
+
+int consys_sema_acquire_timeout(unsigned int index, unsigned int usec);
+void consys_sema_release(unsigned int index);
+
+int consys_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data);
+int consys_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data);
+int consys_spi_write_offset_range(
+ enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int value,
+ unsigned int reg_offset, unsigned int value_offset, unsigned int size);
+
+int consys_spi_clock_switch(enum connsys_spi_speed_type type);
+int consys_subsys_status_update(bool, int);
+bool consys_is_rc_mode_enable(void);
+
+#endif /* _PLATFORM_MT6880_POS_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/mt6880.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/mt6880.c
new file mode 100755
index 0000000..c0a178e
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/mt6880.c
@@ -0,0 +1,440 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__
+
+#include <linux/delay.h>
+#include <linux/memblock.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/thermal.h>
+#include <mtk-clkbuf-bridge.h>
+
+#include <connectivity_build_in_adapter.h>
+
+#include "osal.h"
+#include "conninfra.h"
+#include "conninfra_conf.h"
+#include "consys_hw.h"
+#include "consys_reg_mng.h"
+#include "consys_reg_util.h"
+#include "mt6880.h"
+#include "emi_mng.h"
+#include "mt6880_consys_reg.h"
+#include "mt6880_consys_reg_offset.h"
+#include "mt6880_pos.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+#define PLATFORM_SOC_CHIP 0x6880
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+static int consys_clk_get_from_dts(struct platform_device *pdev);
+static int consys_clk_detach(void);
+static int consys_clock_buffer_ctrl(unsigned int enable);
+static unsigned int consys_soc_chipid_get(void);
+static unsigned int consys_get_hw_ver(void);
+static void consys_clock_fail_dump(void);
+static int consys_thermal_query(void);
+static int consys_power_state(void);
+static int consys_thermal_register(struct platform_device *pdev, struct conninfra_dev_cb* dev_cb);
+static int consys_thermal_get_temp_cb(void*, int*);
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+struct consys_hw_ops_struct g_consys_hw_ops_mt6880 = {
+ /* load from dts */
+ /* TODO: mtcmos should move to a independent module */
+ .consys_plt_clk_get_from_dts = consys_clk_get_from_dts,
+ .consys_plt_clk_detach = consys_clk_detach,
+
+ /* clock */
+ .consys_plt_clock_buffer_ctrl = consys_clock_buffer_ctrl,
+ .consys_plt_co_clock_type = consys_co_clock_type,
+
+ /* POS */
+ .consys_plt_conninfra_on_power_ctrl = consys_conninfra_on_power_ctrl,
+ .consys_plt_set_if_pinmux = consys_set_if_pinmux,
+
+ .consys_plt_polling_consys_chipid = consys_polling_chipid,
+ .consys_plt_d_die_cfg = connsys_d_die_cfg,
+ .consys_plt_spi_master_cfg = connsys_spi_master_cfg,
+ .consys_plt_a_die_cfg = connsys_a_die_cfg,
+ .consys_plt_afe_wbg_cal = connsys_afe_wbg_cal,
+ .consys_plt_subsys_pll_initial = connsys_subsys_pll_initial,
+ .consys_plt_low_power_setting = connsys_low_power_setting,
+ .consys_plt_soc_chipid_get = consys_soc_chipid_get,
+ .consys_plt_conninfra_wakeup = consys_conninfra_wakeup,
+ .consys_plt_conninfra_sleep = consys_conninfra_sleep,
+ .consys_plt_is_rc_mode_enable = consys_is_rc_mode_enable,
+
+ /* debug */
+ .consys_plt_clock_fail_dump = consys_clock_fail_dump,
+ .consys_plt_get_hw_ver = consys_get_hw_ver,
+
+ .consys_plt_spi_read = consys_spi_read,
+ .consys_plt_spi_write = consys_spi_write,
+ .consys_plt_adie_top_ck_en_on = NULL,
+ .consys_plt_adie_top_ck_en_off = NULL,
+ .consys_plt_spi_clock_switch = NULL,
+ .consys_plt_subsys_status_update = NULL,
+
+ .consys_plt_thermal_query = consys_thermal_query,
+ .consys_plt_thermal_register = consys_thermal_register,
+ .consys_plt_power_state = consys_power_state,
+ .consys_plt_config_setup = NULL,
+ .consys_plt_bus_clock_ctrl = NULL,
+};
+
+
+struct consys_plat_thermal_data g_consys_plat_therm_data;
+
+/* For mt6880 */
+extern struct consys_hw_ops_struct g_consys_hw_ops_mt6880;
+extern struct consys_reg_mng_ops g_dev_consys_reg_ops_mt6880;
+extern struct consys_platform_emi_ops g_consys_platform_emi_ops_mt6880;
+extern struct consys_platform_pmic_ops g_consys_platform_pmic_ops_mt6880;
+
+const struct conninfra_plat_data mt6880_plat_data = {
+ .chip_id = PLATFORM_SOC_CHIP,
+ .hw_ops = &g_consys_hw_ops_mt6880,
+ .reg_ops = &g_dev_consys_reg_ops_mt6880,
+ .platform_emi_ops = &g_consys_platform_emi_ops_mt6880,
+ .platform_pmic_ops = &g_consys_platform_pmic_ops_mt6880,
+};
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+#if MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE
+static struct platform_device *connsys_pdev;
+#endif
+
+static const struct thermal_zone_of_device_ops tz_conninfra_thermal_ops = {
+ .get_temp = consys_thermal_get_temp_cb,
+};
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+/* mtcmos contorl */
+int consys_clk_get_from_dts(struct platform_device *pdev)
+{
+#if MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE
+ if (pdev == NULL) {
+ pr_err("%s pdev is null", __func__);
+ return -1;
+ }
+ connsys_pdev = pdev;
+ pm_runtime_enable(&connsys_pdev->dev);
+#else
+ pr_info("MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE not support");
+
+#endif /* #if MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE */
+ return 0;
+}
+
+int consys_clk_detach(void)
+{
+#if MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE
+ if (connsys_pdev == NULL)
+ return 0;
+ pm_runtime_disable(&connsys_pdev->dev);
+#endif
+ return 0;
+}
+
+int consys_platform_spm_conn_ctrl(unsigned int enable)
+{
+ int ret = 0;
+
+#if MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE
+ if (enable) {
+ ret = pm_runtime_get_sync(&connsys_pdev->dev);
+ if (ret) {
+ pr_err("Turn on oonn_infra power fail. Ret=%d", ret);
+ return -1;
+ }
+ } else {
+ ret = pm_runtime_put_sync(&connsys_pdev->dev);
+ if (ret) {
+ pr_err("Turn off conn_infra power fail. Ret=%d", ret);
+ return -1;
+ }
+
+ }
+#else
+ pr_err("Function: %s is not support", __func__);
+#endif
+ return ret;
+}
+
+int consys_clock_buffer_ctrl(unsigned int enable)
+{
+ /* This function call didn't work now.
+ * clock buffer is HW controlled, not SW controlled.
+ * Keep this function call to update status.
+ */
+ if (enable)
+ clk_buf_ctrl(CLK_BUF_CONN, true); /*open XO_WCN*/
+ else
+ clk_buf_ctrl(CLK_BUF_CONN, false); /*close XO_WCN*/
+ return 0;
+}
+
+int consys_co_clock_type(void)
+{
+ const struct conninfra_conf *conf;
+
+ /* Default solution */
+ conf = conninfra_conf_get_cfg();
+ if (NULL == conf) {
+ pr_err("[%s] Get conf fail", __func__);
+ return -1;
+ }
+ /* TODO: for co-clock mode, there are two case: 26M and 52M. Need something to distinguish it. */
+ if (conf->tcxo_gpio != 0)
+ return CONNSYS_CLOCK_SCHEMATIC_26M_EXTCXO;
+ else
+ return CONNSYS_CLOCK_SCHEMATIC_26M_COTMS;
+}
+
+unsigned int consys_soc_chipid_get(void)
+{
+ return PLATFORM_SOC_CHIP;
+}
+
+unsigned int consys_get_hw_ver(void)
+{
+ return CONN_HW_VER;
+}
+
+void consys_clock_fail_dump(void)
+{
+ pr_info("[%s]", __func__);
+}
+
+
+void update_thermal_data(struct consys_plat_thermal_data* input)
+{
+ memcpy(&g_consys_plat_therm_data, input, sizeof(struct consys_plat_thermal_data));
+#if CFG_CONNINFRA_THERMAL_SUPPORT
+ /* Special factor, not in POS */
+ /* THERMCR1 [16:17]*/
+ CONSYS_REG_WRITE(REG_CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERMCR1,
+ (CONSYS_REG_READ(REG_CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERMCR1) |
+ (0x3 << 16)));
+#endif
+}
+
+#if CFG_CONNINFRA_THERMAL_SUPPORT
+int calculate_thermal_temperature(int y)
+{
+ struct consys_plat_thermal_data *data = &g_consys_plat_therm_data;
+ int t;
+ int const_offset = 25;
+
+ /*
+ * MT6635 E1 : read 0x02C = 0x66358A00
+ * MT6635 E2 : read 0x02C = 0x66358A10
+ * MT6635 E3 : read 0x02C = 0x66358A11
+ */
+ if (conn_hw_env.adie_hw_version == 0x66358A10 ||
+ conn_hw_env.adie_hw_version == 0x66358A11)
+ const_offset = 28;
+
+ /* temperature = (y-b)*slope + (offset) */
+ /* TODO: offset + 25 : this is only for E1, E2 is 28 */
+ t = (y - (data->thermal_b == 0 ? 0x36 : data->thermal_b)) *
+ ((data->slop_molecule + 209) / 100) + (data->offset + const_offset);
+
+ pr_info("y=[%d] b=[%d] constOffset=[%d] [%d] [%d] => t=[%d]\n",
+ y, data->thermal_b, const_offset, data->slop_molecule, data->offset,
+ t);
+
+ return t;
+}
+#endif /* CFG_CONNINFRA_THERMAL_SUPPORT */
+
+int consys_thermal_query(void)
+{
+#if CFG_CONNINFRA_THERMAL_SUPPORT
+
+#define THERMAL_DUMP_NUM 11
+#define LOG_TMP_BUF_SZ 256
+#define TEMP_SIZE 13
+ void __iomem *addr = NULL;
+ int cal_val, res = 0;
+ /* Base: 0x1800_2000, CONN_TOP_THERM_CTL */
+ const unsigned int thermal_dump_crs[THERMAL_DUMP_NUM] = {
+ 0x00, 0x04, 0x08, 0x0c,
+ 0x10, 0x14, 0x18, 0x1c,
+ 0x20, 0x24, 0x28,
+ };
+ char tmp[TEMP_SIZE] = {'\0'};
+ char tmp_buf[LOG_TMP_BUF_SZ] = {'\0'};
+ unsigned int i;
+
+ addr = ioremap_nocache(CONN_INFRA_GPT_BASE, 0x100);
+ if (addr == NULL) {
+ pr_err("GPT2_CTRL_BASE remap fail");
+ return -1;
+ }
+
+ /* Hold Semaphore, TODO: may not need this, because
+ thermal cr seperate for different */
+ if (consys_sema_acquire_timeout(CONN_SEMA_THERMAL_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) {
+ pr_err("[THERM QRY] Require semaphore fail\n");
+ iounmap(addr);
+ return -1;
+ }
+
+ /* therm cal en */
+ CONSYS_SET_BIT(REG_CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN, (0x1 << 19));
+ /* GPT2 En */
+ CONSYS_SET_BIT(addr + GPT2_AP_ENABLE, 0x1);
+
+ /* thermal trigger */
+ CONSYS_SET_BIT(REG_CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN, (0x1 << 18));
+ udelay(500);
+ /* get thermal value */
+ cal_val = CONSYS_REG_READ(REG_CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN);
+ cal_val = (cal_val >> 8) & 0x7f;
+
+ /* thermal debug dump */
+ for (i = 0; i < THERMAL_DUMP_NUM; i++) {
+ snprintf(
+ tmp, TEMP_SIZE, "[0x%08x]",
+ CONSYS_REG_READ(REG_CONN_TOP_THERM_CTL_ADDR + thermal_dump_crs[i]));
+ strncat(tmp_buf, tmp, strlen(tmp));
+ }
+ res = calculate_thermal_temperature(cal_val);
+ pr_info("[%s] temp=%dC (%dmC) efuse:[0x%08x][0x%08x][0x%08x][0x%08x] thermal dump: %s",
+ __func__, res, res*1000,
+ g_consys_plat_therm_data.efuse0, g_consys_plat_therm_data.efuse1,
+ g_consys_plat_therm_data.efuse2, g_consys_plat_therm_data.efuse3,
+ tmp_buf);
+
+ /* GPT2 disable, no effect on 6880 */
+ CONSYS_CLR_BIT(addr + GPT2_AP_ENABLE, 0x1);
+
+ /* disable */
+ CONSYS_CLR_BIT(REG_CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN, (0x1 << 19));
+
+ consys_sema_release(CONN_SEMA_THERMAL_INDEX);
+
+ iounmap(addr);
+
+ return (res*1000);
+#else
+ return THERMAL_TEMP_INVALID;
+#endif /* CFG_CONNINFRA_THERMAL_SUPPORT */
+
+}
+
+int consys_thermal_get_temp_cb(void* data, int* temp)
+{
+ struct conninfra_dev_cb *dev_cb = data;
+
+ if (dev_cb && dev_cb->conninfra_thermal_query_cb) {
+ dev_cb->conninfra_thermal_query_cb(NULL, temp);
+ } else {
+ pr_info("Thermal callback is not support");
+ if (temp)
+ *temp = THERMAL_TEMP_INVALID;
+ }
+
+ return 0;
+}
+
+
+int consys_thermal_register(struct platform_device *pdev, struct conninfra_dev_cb* dev_cb)
+{
+ struct thermal_zone_device *tzdev;
+
+ if (dev_cb->conninfra_thermal_query_cb == NULL)
+ pr_info("Thermal callback is not support");
+
+ /* register thermal zone */
+ tzdev = devm_thermal_zone_of_sensor_register(
+ &pdev->dev, 0, dev_cb, &tz_conninfra_thermal_ops);
+
+ return 0;
+}
+
+int consys_power_state(void)
+{
+#if CFG_CONNINFRA_POWER_STATUS_SUPPORT
+ const char* osc_str[] = {
+ "fm ", "gps ", "bgf ", "wf ", "ap2conn ", "conn_thm ", "conn_pta ", "conn_infra_bus "
+ };
+ char buf[256] = {'\0'};
+ int r;
+ int i;
+
+ /* Setup debug select to power state
+ * debug sel: 0x1806015C[2:0]=3'b000 (default value)
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_CFG_DBG_SEL,
+ 0x0, 0x7);
+
+ r = CONSYS_REG_READ(REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_DBG_DUMMY_2);
+ for (i = 0; i < 8; i++) {
+ if ((r & (0x1 << (18 + i))) > 0)
+ strncat(buf, osc_str[i], strlen(osc_str[i]));
+ }
+ pr_info("[%s] [0x%x] %s", __func__, r, buf);
+#endif
+ return 0;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/mt6880_consys_reg.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/mt6880_consys_reg.c
new file mode 100755
index 0000000..0668676
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/mt6880_consys_reg.c
@@ -0,0 +1,634 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#include <linux/memblock.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/random.h>
+
+#include <connectivity_build_in_adapter.h>
+
+#include "consys_reg_mng.h"
+#include "mt6880_consys_reg.h"
+#include "mt6880_consys_reg_offset.h"
+#include "consys_hw.h"
+#include "consys_reg_util.h"
+
+#define LOG_TMP_BUF_SZ 256
+#define CONSYS_POWER_MODE_LEGACY "Legacy"
+#define CONSYS_POWER_MODE_RC "RC"
+
+static int consys_reg_init(struct platform_device *pdev);
+static int consys_reg_deinit(void);
+static int consys_check_reg_readable(void);
+static int consys_is_consys_reg(unsigned int addr);
+static int consys_is_bus_hang(void);
+static int consys_dump_bus_status(void);
+static int consys_dump_conninfra_status(void);
+static int consys_is_host_csr(unsigned long addr);
+
+struct consys_reg_mng_ops g_dev_consys_reg_ops_mt6880 = {
+ .consys_reg_mng_init = consys_reg_init,
+ .consys_reg_mng_deinit = consys_reg_deinit,
+
+ .consys_reg_mng_check_reable = consys_check_reg_readable,
+ .consys_reg_mng_is_consys_reg = consys_is_consys_reg,
+ .consys_reg_mng_is_bus_hang = consys_is_bus_hang,
+ .consys_reg_mng_dump_bus_status = consys_dump_bus_status,
+ .consys_reg_mng_dump_conninfra_status = consys_dump_conninfra_status,
+ .consys_reg_mng_dump_cpupcr = NULL,
+ .consys_reg_mng_is_host_csr = consys_is_host_csr,
+
+ /* step */
+ .consys_reg_mng_validate_idx_n_offset = NULL,
+ .consys_reg_mng_find_can_write_reg = NULL,
+ .consys_reg_mng_get_phy_addr_by_idx = NULL,
+ .consys_reg_mng_get_virt_addr_by_idx = NULL,
+ .consys_reg_mng_get_chip_id_idx_offset = NULL,
+ .consys_reg_mng_get_reg_symbol_num = NULL
+};
+
+
+const char* consys_base_addr_index_to_str[CONSYS_BASE_ADDR_MAX] = {
+ "CONN_INFRA_RGU_BASE",
+ "CONN_INFRA_CFG_BASE",
+ "CONN_HOST_CSR_TOP_BASE",
+ "INFRACFG_AO_BASE",
+ "TOPRGU_BASE",
+ "SPM_BASE",
+ "INFRACFG_BASE",
+ "CONN_WT_SLP_CTL_REG",
+ "CONN_AFE_CTL_REG",
+ "GPIO",
+ "CONN_RF_SPI_MST_REG",
+ "CONN_SEMAPHORE",
+ "CONN_TOP_THERM_CTL",
+ "IOCFG_BM",
+ "CONN_DEBUG_CTL",
+ "CONN_INFRA_CLKGEN_ON_TOP",
+ "CONN_INFRA_BUS_CR",
+ "CONN_INFRA_DEBUG_CTRL_AO",
+};
+
+struct consys_base_addr conn_reg;
+
+struct consys_base_addr* get_conn_reg_base_addr()
+{
+ return &conn_reg;
+}
+#if CFG_CONNINFRA_BUS_HANG_DEBUG_SUPPORT
+static void consys_bus_hang_dump_c_host_csr(void)
+{
+ unsigned int r1, r2, r3, r4, r5, r6, r7, r8;
+ char tmp[LOG_TMP_BUF_SZ] = {'\0'};
+ char tmp_buf[LOG_TMP_BUF_SZ] = {'\0'};
+ unsigned int i;
+
+ /* CONN_INFRA_DBG No.5: gps2conn gals
+ * Read gals status for debug
+ * Dump 1800_E2B0 for gals slave
+ */
+ r1 = CONSYS_REG_READ(
+ REG_CONN_INFRA_BUS_CR_ADDR + CONN_INFRA_BUS_CR_GALS_GPS2CONN_GALS_DBG);
+
+ /* CONN_INFRA_DBG No.6: conn2gps gals
+ * Read gals status for debug
+ * 1. Read 1800_E2B4 (GALS_CONN2GPS_GALS_DBG)
+ * 2. Read 1800_E2CC[7:6] for gals idle signal
+ */
+ r2 = CONSYS_REG_READ(
+ REG_CONN_INFRA_BUS_CR_ADDR + CONN_INFRA_BUS_CR_GALS_CONN2GPS_GALS_DBG);
+ r3 = CONSYS_REG_READ(
+ REG_CONN_INFRA_BUS_CR_ADDR + CONN_INFRA_BUS_CR_GALS_CONN2GPS_CTRL_0);
+
+ /* CONN_INFRA_DBG No.7: conn_infra timeout mechanism
+ * 1. off domain AHB slaves hang result to timeout
+ * - Read 1806_0414, 1806_0418
+ * 2. on domain APB slaves hang result to timeout
+ * - Read 1806_042c, 1806_0430
+ */
+ r4 = CONSYS_REG_READ(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_BUS_OFF_DBG_1);
+ r5 = CONSYS_REG_READ(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_BUS_OFF_DBG_2);
+ r6 = CONSYS_REG_READ(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_BUS_ON_TOP_DBG_APB_1);
+ r7 = CONSYS_REG_READ(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_BUS_ON_TOP_DBG_APB_2);
+
+ /* CONN_INFRA_DBG No.8: bus_debug_monitor
+ * 1. Read 1802_F000[8] to confirm if the irq is resulted by bus hang
+ * timeout mechanisim
+ * 2. Read 0x 1802_F408 ~ 0x1802_F424 to see the command information
+ * which resulting bus hang
+ */
+ r8 = CONSYS_REG_READ(
+ REG_CONN_INFRA_DEBUG_CTRL_AO + CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_ON_CTRL0);
+ for (i = 0x408; i <= 0x424; i += 4) {
+ snprintf(tmp, LOG_TMP_BUF_SZ, "[%x]",
+ CONSYS_REG_READ(REG_CONN_INFRA_DEBUG_CTRL_AO + i));
+ strncat(tmp_buf, tmp, strlen(tmp));
+ }
+
+ pr_info("[CONN_BUS_C_1][%x][%x][%x][%x][%x][%x][%x][%x]",
+ r1, r2, r3, r4, r5, r6, r7, r8);
+ pr_info("[CONN_BUS_C_2]%s", tmp_buf);
+}
+#endif
+
+static void consys_bus_hang_dump_c(void)
+{
+#if CFG_CONNINFRA_BUS_HANG_DEBUG_SUPPORT
+ char tmp[LOG_TMP_BUF_SZ] = {'\0'};
+ char tmp_buf[LOG_TMP_BUF_SZ] = {'\0'};
+ int i;
+ const static unsigned int conninfra_cfg_dump_list[] =
+ {0x504, 0x514, 0x524, 0x534, 0x574, 0x584};
+ const static unsigned int conninfra_bus_cr[] =
+ {0x2a0, 0x2a4, 0x2b0, 0x2b4, 0x2a0, 0x2a4};
+ void __iomem *addr = NULL;
+ unsigned int ary12, ary13;
+
+ consys_bus_hang_dump_c_host_csr();
+
+ /* ary12: 0x1020_E810 CONN2AP_GALS_SLV_DBG
+ * ary13: 0x1020_E814 AP2CONN_GALS_MST_DBG
+ */
+ addr = ioremap_nocache(0x1020E810, 0x20);
+ if (addr != NULL) {
+ ary12 = CONSYS_REG_READ(addr);
+ ary13 = CONSYS_REG_READ(addr + 0x4);
+ iounmap(addr);
+ } else {
+ ary12 = 0xdeaddead;
+ ary13 = 0xdeaddead;
+ pr_err("[%s] ioremap error", __func__);
+ }
+
+ /* CONN_INFRA_DBG No.2: sleep protect
+ * ary0: 0x1800_1504
+ * ary1: 0x1800_1514
+ * ary2: 0x1800_1524
+ * ary3: 0x1800_1534
+ * ary4: 0x1800_1574
+ * ary5: 0x1800_1584
+ * ary6: 0x1800_E2A0
+ * ary7: 0x1800_E2A4
+ * ary8: 0x1800_E2B0
+ * ary9: 0x1800_E2B4
+ */
+ /* CONN_INFRA_DBG No.3: ap2conn gals
+ * Read gals status for debug
+ * ary10: Read 1800_E2A0 for gals slave
+ */
+
+ /* CONN_INFRA_DBG No.4: conn2ap gals
+ * Read gals status for debug
+ * ary11: Read 1800_E2A4 for gals master
+ */
+
+ for (i = 0; i < sizeof(conninfra_cfg_dump_list)/sizeof(unsigned int); i++)
+ {
+ snprintf(tmp, LOG_TMP_BUF_SZ, "[%x]",
+ CONSYS_REG_READ(REG_CONN_INFRA_CFG_ADDR + conninfra_cfg_dump_list[i]));
+ strncat(tmp_buf, tmp, strlen(tmp));
+ }
+
+ for (i = 0; i < sizeof(conninfra_bus_cr)/sizeof(unsigned int); i++)
+ {
+ snprintf(tmp, LOG_TMP_BUF_SZ, "[%x]",
+ CONSYS_REG_READ(REG_CONN_INFRA_BUS_CR_ADDR + conninfra_bus_cr[i]));
+ strncat(tmp_buf, tmp, strlen(tmp));
+ }
+ pr_info("[CONN_BUS_C]%s[%x][%x]", tmp_buf, ary12, ary13);
+#endif
+}
+
+static void consys_bus_hang_dump_a(void)
+{
+#if CFG_CONNINFRA_BUS_HANG_DEBUG_SUPPORT
+ unsigned int r1, r2, r7, r8, r9, r10, r11, r12, r13;
+ void __iomem *addr = NULL;
+
+ /* SPM CR */
+ /* r1: PCM_REG13_DATA 0x1000_6110
+ * [4]: conn_ddr_en
+ * [13]: conn_state
+ * [14]: conn_srcclkena
+ * [15]: conn_apsrc_req
+ */
+ r1 = CONSYS_REG_READ(
+ REG_SPM_BASE_ADDR + SPM_PCM_REG13_DATA);
+
+ /* r2: SRC_REQ_STA_0 0x1000_6114
+ * [12]: CONN_SRCCLKENA
+ * [14]: CONN_INFRA_REQ
+ * [15]: CONN_APSRC_REQ
+ * [16]: CONN_VRF18_REQ
+ * [17]: CONN_DDR_EN
+ */
+ r2 = CONSYS_REG_READ(
+ REG_SPM_BASE_ADDR + SPM_SRC_REQ_STA_0);
+
+ /* r7: SPM debug CR 0x1000_6100
+ * 0x10006100[0] sc_26m_ck_off
+ * 1'b0: 26M on; 1'b1
+ * 0x10006100[3] sc_axi_ck_off
+ * 1'b0: bus ck on; 1'b1 bus ck off
+ * 0x10006100[5] sc_md26m_ck_off
+ * 1'b0: MD 26M on; 1'b1 MD 26M off
+ * 0x10006100[20] sc_cksq0_off
+ * 1'b0: clock square0 on; 1'b1 clock square off
+ */
+ r7 = CONSYS_REG_READ(
+ REG_SPM_BASE_ADDR + SPM_PCM_REG0_DATA);
+
+ /*
+ * 0x1000_6304[2] : pwr_on
+ * 0x1000_616c[1] : pwr_ack
+ * 0x1000_6304[3] : pwr_on_s
+ * 0x1000_6170[1] : pwr_ack_s
+ * 0x1000_6304[1] : iso_en
+ * 0x1000_6304[0] : ap_sw_rst
+ * r8: 0x1000_616C
+ * r9: 0x1000_6170
+ * r10: 0x1000_6304
+ */
+ r8 = CONSYS_REG_READ(
+ REG_SPM_BASE_ADDR + SPM_PWR_STATUS);
+ r9 = CONSYS_REG_READ(
+ REG_SPM_BASE_ADDR + SPM_PWR_STATUS_2ND);
+ r10 = CONSYS_REG_READ(
+ REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON);
+
+ /* r11: TOPCKGEN infra bus clock 0x10000010[2:0]
+ * 0: tck_26m_mx9_ck => 26M
+ * 1: mainpll_d4_d4 => 136.5M
+ * 2: mainpll_d7_d2 => 156M
+ * 3: mainpll_d4_d2 => 273M
+ * 4: mainpll_d5_d2 => 218.4M
+ * 5: mainpll_d6_d2 => 182M
+ * 6: osc_d4 => 65M
+ */
+ addr = ioremap_nocache(0x10000000, 0x20);
+ if (addr != NULL) {
+ r11 = CONSYS_REG_READ(addr + 0x10);
+ iounmap(addr);
+ } else {
+ r11 = 0xdeaddead;
+ pr_err("[%s] ioremap error", __func__);
+ }
+
+ /* ap2conn gals sleep protect status
+ * - 0x1000_1220 [13] / 0x1000_1228 [13] (rx/tx) (sleep protect enable ready)
+ * both of them should be 1'b0 (CR at ap side)
+ * r12 : 0x1000_1220 (rx)
+ * r13 : 0x1000_1228 (tx)
+ */
+ r12 = CONSYS_REG_READ(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN);
+ r13 = CONSYS_REG_READ(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1);
+
+ pr_info("[CONN_BUS_A] %s [%x][%x] [%x][%x][%x][%x] [%x] [%x][%x]",
+ CONSYS_POWER_MODE_LEGACY, r1, r2,
+ r7, r8, r9, r10,
+ r11,
+ r12, r13);
+#endif
+}
+
+static void consys_bus_hang_dump_b(void)
+{
+#if CFG_CONNINFRA_BUS_HANG_DEBUG_SUPPORT
+ unsigned int r1, r2, r3, r4, r5, r6, r7;
+
+ /* r1: 0x180602C0
+ * [4] conn_srcclkena_ack
+ * [5] conn_ap_bus_ack
+ * [6] conn_apsrc_ack
+ * [7] conn_ddr_en_ack
+ */
+ r1 = CONSYS_REG_READ(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_DBG_DUMMY_0);
+
+ /*****************
+ * Debug sel
+ *****************/
+ /* r2: 0x1806015C[2:0] = 3'b000 (default)
+ * Dump 0x180602C8
+ * [25]: conn_infra_bus_osc_en
+ * [24]: conn_pta_osc_en
+ * [23]: conn_thm_osc_en
+ * [22]: ap2conn_osc_en
+ * [21]: wfsys_osc_en
+ * [20]: bgfsys_osc_en
+ * [19]: gpssys_osc_en
+ * [18]: fmsys_osc_en
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_CFG_DBG_SEL,
+ 0x0, 0x7);
+ r2 = CONSYS_REG_READ(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_DBG_DUMMY_2);
+
+ /* r3: 0x1806015C[2:0] = 3'b010
+ * Dump 0x180602C8
+ * [12]: conn_srcclkena_0_bblpm_ack
+ * [13]: conn_srcclkena_0_fpm_ack
+ * [28]: conn_srcclkena_1_bblpm_ack
+ * [29]: conn_srcclkena_1_fpm_ack
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_CFG_DBG_SEL,
+ 0x2, 0x7);
+ r3 = CONSYS_REG_READ(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_DBG_DUMMY_2);
+
+ /* r4: 0x1806015C[2:0] = 3'b011
+ * Dump 0x180602C8
+ * [12]: conn_srcclkena_2_bblpm_ack
+ * [13]: conn_srcclkena_2_fpm_ack
+ * [28]: conn_srcclkena_3_bblpm_ack
+ * [29]: conn_srcclkena_3_fpm_ack
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_CFG_DBG_SEL,
+ 0x3, 0x7);
+ r4 = CONSYS_REG_READ(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_DBG_DUMMY_2);
+
+ /* r5: MTCMOS
+ * 0x1806_02CC[15]: power_enable
+ * 0x1806_02CC[14]: pwr_on
+ * 1'b0: power off; 1'b1: power on
+ * 0x1806_02CC[13]: pwr_ack
+ * 1'b0: power off; 1'b1: power on
+ * 0x1806_02CC[12]: pwr_on_s
+ * 1'b0: power off; 1'b1: power on
+ * 0x1806_02CC[11]: pwr_ack_s
+ * 1'b0: power off; 1'b1: power on
+ * 0x1806_02CC[10]: iso_en
+ * 1'b0: power on; 1'b1: power off
+ * 0x1806_02CC[9]: conn_infra_off_xreset_b
+ * 1'b0: power off; 1'b1: power on
+ * 0x1806_02CC[8]: conn_infra_off_hreset_b
+ * 1'b0: power off; 1'b1: power on
+ */
+ r5 = CONSYS_REG_READ(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_DBG_DUMMY_3);
+
+ /* Check conn_infra off bus clock
+ * - write 0x1 to 0x1806_0000[0], reset clock detect
+ * - 0x1806_0000[2] conn_infra off bus clock (should be 1'b1 if clock exist)
+ * - 0x1806_0000[1] osc clock (should be 1'b1 if clock exist)
+ */
+ CONSYS_SET_BIT(REG_CONN_HOST_CSR_ADDR, 0x1);
+ udelay(1);
+ r6 = CONSYS_REG_READ(REG_CONN_HOST_CSR_ADDR);
+
+ /* Check conn_infra off domain bus hang irq status
+ * - 0x1806_02D4[0], should be 1'b1, or means conn_infra off bus might hang
+ */
+ r7 = CONSYS_REG_READ(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_DBG_DUMMY_5);
+
+ pr_info("[CONN_BUS_B] %s [%x] [%x][%x][%x] [%x] [%x][%x]",
+ CONSYS_POWER_MODE_LEGACY, r1,
+ r2, r3, r4, /* debug select */
+ r5,
+ r6, r7);
+#endif
+}
+
+static int consys_dump_bus_status(void)
+{
+ consys_bus_hang_dump_c();
+ return 0;
+}
+
+static int consys_dump_conninfra_status(void)
+{
+ consys_bus_hang_dump_a();
+ consys_bus_hang_dump_b();
+ return 0;
+}
+
+static int consys_is_bus_hang(void)
+{
+ int ret = 0;
+#if CFG_CONNINFRA_BUS_HANG_DEBUG_SUPPORT
+ int r;
+
+ /* dump SPM register */
+ consys_bus_hang_dump_a();
+
+ /* ap2conn gals sleep protect status
+ * - 0x1000_1220 [13] / 0x1000_1228 [13] (rx/tx) (sleep protect enable ready)
+ * both of them should be 1'b0 ~(CR at ap side)
+ * 0x1000_1220 (rx)
+ * 0x1000_1228 (tx)
+ */
+ r = CONSYS_REG_READ_BIT(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN,
+ (0x1 << 13));
+ if (r != 0)
+ return CONNINFRA_AP2CONN_RX_SLP_PROT_ERR;
+ r = CONSYS_REG_READ_BIT(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1,
+ (0x1 << 13));
+ if (r != 0)
+ return CONNINFRA_AP2CONN_TX_SLP_PROT_ERR;
+
+ consys_bus_hang_dump_b();
+
+ /* AP2CONN_INFRA OFF
+ * 1. Check "AP2CONN_INFRA ON step is ok"
+ * 2. Check conn_infra off bus clock
+ * - write 0x1 to 0x1806_0000[0], reset clock detect
+ * - 0x1806_0000[2] conn_infra off bus clock (should be 1'b1 if clock exist)
+ * - 0x1806_0000[1] osc clock (should be 1'b1 if clock exist)
+ * 3. Check conn_infra off domain bus hang irq status
+ * - 0x1806_02d4[0], should be 1'b1, or means conn_infra off bus might hang
+ */
+ CONSYS_SET_BIT(REG_CONN_HOST_CSR_ADDR, 0x1);
+ udelay(1);
+ r = CONSYS_REG_READ(REG_CONN_HOST_CSR_ADDR);
+ if ((r & TOP_BUS_MUC_STAT_HCLK_FR_CK_DETECT_BIT) == 0 ||
+ (r & TOP_BUS_MUC_STAT_OSC_CLK_DETECT_BIT) == 0) {
+ pr_info("[%s] readable fail = bus clock", __func__);
+ consys_bus_hang_dump_c_host_csr();
+ return 0;
+ }
+
+ r = CONSYS_REG_READ_BIT(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_DBG_DUMMY_5, 0x1);
+ if (r == 0x0) {
+ ret |= CONNINFRA_INFRA_BUS_HANG_IRQ;
+ }
+
+ consys_bus_hang_dump_c();
+#endif /* CFG_CONNINFRA_BUS_HANG_DEBUG_SUPPORT */
+ return ret;
+
+}
+
+int consys_check_reg_readable(void)
+{
+#if CFG_CONNINFRA_BUS_HANG_DEBUG_SUPPORT
+ int r;
+ unsigned int rnd;
+ int delay_time = 1, spent = delay_time, max_wait = 16000; // 1.6 ms
+ int retry = max_wait / 10;
+
+ /* AP2CONN_INFRA ON */
+ /* 1. Check ap2conn gals sleep protect status
+ * - 0x1000_1220 [13] / 0x1000_1228 [13](rx/tx) (sleep protect enable ready)
+ * both of them should be 1'b0 (CR at ap side)
+ */
+ r = CONSYS_REG_READ_BIT(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN,
+ (0x1 << 13));
+ if (r != 0)
+ return 0;
+
+ r = CONSYS_REG_READ_BIT(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1,
+ (0x1 << 13));
+ if (r != 0)
+ return 0;
+
+ /* AP2CONN_INFRA OFF
+ * 1. Check "AP2CONN_INFRA ON step is ok"
+ * 2. Check conn_infra off bus clock
+ * - write 0x1 to 0x1806_0000[0], reset clock detect
+ * - 0x1806_0000[2] conn_infra off bus clock (should be 1'b1 if clock exist)
+ * - 0x1806_0000[1] osc clock (should be 1'b1 if clock exist)
+ * 3. Check conn_infra off domain bus hang irq status
+ * - 0x1806_02d4[0], should be 1'b1, or means conn_infra off bus might hang
+ */
+ while (retry > 0 && spent < max_wait) {
+ CONSYS_SET_BIT(REG_CONN_HOST_CSR_ADDR, 0x1);
+ udelay(delay_time);
+ r = CONSYS_REG_READ(REG_CONN_HOST_CSR_ADDR);
+ if ((r & TOP_BUS_MUC_STAT_HCLK_FR_CK_DETECT_BIT) == 0 ||
+ (r & TOP_BUS_MUC_STAT_OSC_CLK_DETECT_BIT) == 0) {
+ spent += delay_time;
+ retry--;
+ if (retry == 0)
+ pr_info("[%s] retry=0 r=[%x]", __func__, r);
+ else
+ delay_time = 10;
+ rnd = get_random_int() % 10;
+ spent += rnd;
+ udelay(rnd);
+ continue;
+ }
+ break;
+ }
+ if (retry == 0 || spent >= max_wait) {
+ pr_info("[%s] readable fail = bus clock retry=[%d] spent=[%d]", __func__,
+ retry, spent);
+ return 0;
+ }
+
+ r = CONSYS_REG_READ_BIT(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_DBG_DUMMY_5, 0x1);
+ if (r == 0x0)
+ return 0;
+
+#endif /* CFG_CONNINFRA_BUS_HANG_DEBUG_SUPPORT */
+ return 1;
+}
+
+
+int consys_is_consys_reg(unsigned int addr)
+{
+ return 0;
+}
+
+
+static int consys_is_host_csr(unsigned long addr)
+{
+ struct consys_reg_base_addr *host_csr_addr =
+ &conn_reg.reg_base_addr[CONN_HOST_CSR_TOP_BASE];
+
+ if (addr >= host_csr_addr->phy_addr &&
+ addr < host_csr_addr->phy_addr + host_csr_addr->size)
+ return 1;
+ return 0;
+}
+
+int consys_reg_init(struct platform_device *pdev)
+{
+ int ret = -1;
+ struct device_node *node = NULL;
+ struct consys_reg_base_addr *base_addr = NULL;
+ struct resource res;
+ int flag, i = 0;
+
+ node = pdev->dev.of_node;
+ pr_info("[%s] node=[%p]\n", __func__, node);
+ if (node) {
+ for (i = 0; i < CONSYS_BASE_ADDR_MAX; i++) {
+ base_addr = &conn_reg.reg_base_addr[i];
+
+ ret = of_address_to_resource(node, i, &res);
+ if (ret) {
+ pr_err("Get Reg Index(%d-%s) failed",
+ i, consys_base_addr_index_to_str[i]);
+ continue;
+ }
+
+ base_addr->phy_addr = res.start;
+ base_addr->vir_addr =
+ (unsigned long) of_iomap(node, i);
+ of_get_address(node, i, &(base_addr->size), &flag);
+
+ pr_info("Get Index(%d-%s) phy(0x%zx) baseAddr=(0x%zx) size=(0x%zx)",
+ i, consys_base_addr_index_to_str[i], base_addr->phy_addr,
+ base_addr->vir_addr, base_addr->size);
+ }
+
+ } else {
+ pr_err("[%s] can't find CONSYS compatible node\n", __func__);
+ return ret;
+ }
+ return 0;
+
+}
+
+static int consys_reg_deinit(void)
+{
+ int i = 0;
+
+ for (i = 0; i < CONSYS_BASE_ADDR_MAX; i++) {
+ if (conn_reg.reg_base_addr[i].vir_addr) {
+ pr_info("[%d] Unmap %s (0x%zx)",
+ i, consys_base_addr_index_to_str[i],
+ conn_reg.reg_base_addr[i].vir_addr);
+ iounmap((void __iomem*)conn_reg.reg_base_addr[i].vir_addr);
+ conn_reg.reg_base_addr[i].vir_addr = 0;
+ }
+ }
+
+ return 0;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/mt6880_emi.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/mt6880_emi.c
new file mode 100755
index 0000000..edd76ef
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/mt6880_emi.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__
+
+#include "consys_hw.h"
+#include "emi_mng.h"
+#include "mt6880_pos.h"
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+struct consys_platform_emi_ops g_consys_platform_emi_ops_mt6880 = {
+ .consys_ic_emi_mpu_set_region_protection = NULL,
+ .consys_ic_emi_set_remapping_reg = consys_emi_set_remapping_reg,
+ .consys_ic_emi_get_md_shared_emi = NULL,
+ .consys_ic_emi_get_fw_emi_size = NULL,
+};
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/mt6880_pmic.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/mt6880_pmic.c
new file mode 100755
index 0000000..13b08ad
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/mt6880_pmic.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__
+
+#include <connectivity_build_in_adapter.h>
+#include <linux/memblock.h>
+#include <linux/platform_device.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/regulator/consumer.h>
+#include <linux/notifier.h>
+
+#include "consys_hw.h"
+#include "consys_reg_util.h"
+#include "osal.h"
+#include "mt6880_pmic.h"
+#include "mt6880_pos.h"
+#include "mt6880_consys_reg.h"
+#include "mt6880_consys_reg_offset.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+static int consys_plt_pmic_get_from_dts(struct platform_device *pdev, struct conninfra_dev_cb* dev_cb);
+
+static int consys_plt_pmic_common_power_ctrl(unsigned int enable);
+static int consys_plt_pmic_gps_power_ctrl(unsigned int enable);
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+const struct consys_platform_pmic_ops g_consys_platform_pmic_ops_mt6880 = {
+ .consys_pmic_get_from_dts = consys_plt_pmic_get_from_dts,
+ .consys_pmic_common_power_ctrl = consys_plt_pmic_common_power_ctrl,
+ .consys_pmic_wifi_power_ctrl = NULL,
+ .consys_pmic_bt_power_ctrl = NULL,
+ .consys_pmic_gps_power_ctrl = consys_plt_pmic_gps_power_ctrl,
+ .consys_pmic_fm_power_ctrl = NULL,
+ .consys_pmic_event_notifier = NULL,
+};
+
+#if CFG_CONNINFRA_PMIC_SUPPORT
+struct regulator *reg_VCN18;
+#endif
+
+static struct conninfra_dev_cb* g_dev_cb;
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+int consys_plt_pmic_get_from_dts(struct platform_device *pdev, struct conninfra_dev_cb* dev_cb)
+{
+
+ g_dev_cb = dev_cb;
+#if CFG_CONNINFRA_PMIC_SUPPORT
+ reg_VCN18 = regulator_get(&pdev->dev, "vcn18");
+ if (!reg_VCN18)
+ pr_err("Regulator_get VCN_18 fail\n");
+#endif /* CFG_CONNINFRA_PMIC_SUPPORT */
+ return 0;
+}
+
+int consys_plt_pmic_common_power_ctrl(unsigned int enable)
+{
+#if CFG_CONNINFRA_PMIC_SUPPORT
+ int ret;
+
+ /* Only support legacy mode */
+ if (enable) {
+ /* Set PMIC VCN18 LDO SW_OP_EN =1, SW_EN = 1, SW_LP =0
+ * (sw enable & into normal mode)
+ */
+ /* SW_LP=0, default is 0 */
+ /* Setup voltage */
+ regulator_set_voltage(reg_VCN18, 1800000, 1800000);
+ /* SW_EN=1 */
+ ret = regulator_enable(reg_VCN18);
+ if (ret)
+ pr_err("[%s] regulator_enable return error %d", __func__, ret);
+ } else {
+ /* Set PMIC VCN18 LDO SW_OP_EN =0, SW_EN = 0, SW_LP =0 (sw disable)
+ */
+ regulator_disable(reg_VCN18);
+ }
+#endif /* CFG_CONNINFRA_PMIC_SUPPORT */
+ return 0;
+}
+
+int consys_plt_pmic_gps_power_ctrl(unsigned int enable)
+{
+ return 0;
+}
+
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/mt6880_pos.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/mt6880_pos.c
new file mode 100755
index 0000000..7bdf385
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6880/mt6880_pos.c
@@ -0,0 +1,1585 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+/* platform dependent */
+#include "plat_def.h"
+/* macro for read/write cr */
+#include "consys_reg_util.h"
+#include "consys_reg_mng.h"
+/* cr base address */
+#include "mt6880_consys_reg.h"
+/* cr offset */
+#include "mt6880_consys_reg_offset.h"
+/* For function declaration */
+#include "mt6880_pos.h"
+#include "mt6880.h"
+
+#include <linux/ratelimit.h>
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+#define CONN_INFRA_SYSRAM__A_DIE_DIG_TOP_CK_EN_MASK 0x7f
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+const static char* g_spi_system_name[SYS_SPI_MAX] = {
+ "SYS_SPI_WF1",
+ "SYS_SPI_WF",
+ "SYS_SPI_BT",
+ "SYS_SPI_FM",
+ "SYS_SPI_GPS",
+ "SYS_SPI_TOP",
+ "SYS_SPI_WF2",
+ "SYS_SPI_WF3",
+};
+
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+static int consys_spi_read_nolock(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data);
+static int consys_spi_write_nolock(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data);
+static void consys_spi_write_offset_range_nolock(
+ enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int value,
+ unsigned int reg_offset, unsigned int value_offset, unsigned int size);
+#if CFG_CONNINFRA_THERMAL_SUPPORT
+static int connsys_a_die_thermal_cal(
+ int efuse_valid,
+ unsigned int efuse0, unsigned int efuse1, unsigned int efuse2, unsigned int efuse3);
+#endif
+static int consys_polling_chipid_int(unsigned int retry, unsigned int sleep_ms);
+static int consys_adie_top_ck_en_top_ctrl(bool on);
+
+static int consys_sema_acquire(enum conn_semaphore_type index);
+
+unsigned int consys_emi_set_remapping_reg(
+ phys_addr_t con_emi_base_addr,
+ phys_addr_t md_shared_emi_base_addr)
+{
+ /* 0x1806_01DC[19:0], gps_ap_peri_base[19:0] = 0x0_1000 (un-related to emi)
+ * conn2ap peri ramappinng -> 0x1000_0000
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_HOST_CSR_ADDR + CONN2AP_REMAP_GPS_PERI_BASE_ADDR,
+ 0x01000, 0xFFFFF);
+
+ return 0;
+}
+
+int consys_conninfra_on_power_ctrl(unsigned int enable)
+{
+#if MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE
+ int ret;
+#else
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ int check;
+#endif
+#endif
+
+ if (enable) {
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ /* Turn on SPM clock (apply this for SPM's CONNSYS power control related CR accessing)
+ * address: 0x1000_6000[0]
+ * 0x1000_6000[31:16]
+ * Data: [0]=1'b1
+ * [31:16]=16'h0b16 (key)
+ * Action: write
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_SPM_BASE_ADDR + SPM_POWERON_CONFIG_EN, 0x0b160001, 0xffff0001);
+#endif
+
+ /* Power on Connsys MTCMOS */
+#if MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE
+ ret = consys_platform_spm_conn_ctrl(enable);
+ if (ret) {
+ pr_err("Turn on oonn_infra power fail.\n");
+ return -1;
+ }
+#else /* MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE */
+ pr_info("Turn on conn_infra power by POS steps\n");
+ /* Assert "conn_infra_on" primary part power on, set "connsys_on_domain_pwr_on"=1
+ * Address: 0x1000_6304[2]
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, (0x1<<2));
+
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ /* Check "conn_infra_on" primary part power status, check "connsys_on_domain_pwr_ack"=1
+ * (polling "10 times" and each polling interval is "0.5ms")
+ * Address: 0x1000_616C[1]
+ * Data: 1'b1
+ * Action: polling
+ */
+ check = 0;
+ CONSYS_REG_BIT_POLLING(REG_SPM_BASE_ADDR + SPM_PWR_STATUS, 1, 1, 10, 500, check);
+ if (check != 0)
+ pr_err("Check conn_infra_on primary power fail. 0x1000_616C is 0x%08x. Expect [1] as 1.\n",
+ CONSYS_REG_READ(REG_SPM_BASE_ADDR + SPM_PWR_STATUS));
+#endif
+
+ /* Assert "conn_infra_on" secondary part power on, set "connsys_on_domain_pwr_on_s"=1
+ * Address: 0x1000_6304[3]
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, (0x1<<3));
+
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ /* Check "conn_infra_on" secondary part power status,
+ * check "connsys_on_domain_pwr_ack_s"=1
+ * (polling "10 times" and each polling interval is "0.5ms")
+ * Address: 0x1000_6170[1]
+ * Data: 1'b1
+ * Action: polling
+ */
+ check = 0;
+ CONSYS_REG_BIT_POLLING(REG_SPM_BASE_ADDR + SPM_PWR_STATUS_2ND, 1, 1, 10, 500, check);
+ if (check != 0)
+ pr_err("Check conn_infra_on secondary power fail. 0x1000_6170 is 0x%08x. Expect [1] as 1.\n",
+ CONSYS_REG_READ(REG_SPM_BASE_ADDR + SPM_PWR_STATUS_2ND));
+#endif
+
+ /* Turn on AP-to-CONNSYS bus clock, set "conn_clk_dis"=0
+ * (apply this for bus clock toggling)
+ * Address: 0x1000_6304[4]
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, (0x1<<4));
+
+ /* Wait 1 us */
+ udelay(1);
+
+ /* De-assert "conn_infra_on" isolation, set "connsys_iso_en"=0
+ * Address: 0x1000_6304[1]
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, (0x1<<1));
+
+ /* De-assert CONNSYS S/W reset (TOP RGU CR),
+ * set "ap_sw_rst_b"=1
+ * Address: WDT_SWSYSRST[9] (0x1000_7018[9])
+ * WDT_SWSYSRST[31:24] (0x1000_7018[31:24])
+ * Data: [9]=1'b0
+ * [31:24]=8'h88 (key)
+ * Action: Write
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_TOP_RGU_ADDR + TOP_RGU_WDT_SWSYSRST, 0x88000000, 0xff000200);
+
+ /* De-assert CONNSYS S/W reset (SPM CR), set "ap_sw_rst_b"=1
+ * Address: CONN_PWR_CON[0] (0x1000_6304[0])
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x1);
+
+ /* Wait 0.5ms */
+ udelay(500);
+
+ /* conn2ap/ap2conn slpprot disable */
+ /* Turn off AHB RX bus sleep protect (AP2CONN AHB Bus protect)
+ * (apply this for INFRA AHB bus accessing when CONNSYS had been turned on)
+ * Address: 0x1000_12A4[31:0] (INFRA_TOPAXI_PROTECTEN_CLR)
+ * Data: 32'h1000_0000
+ * Action: write
+ */
+ CONSYS_REG_WRITE(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_CLR, 0x10000000);
+
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ /* Check AHB RX bus sleep protect turn off
+ * (polling "100 times" and each polling interval is "0.5ms")
+ * Address: 0x1000_1228[28] (INFRA_TOPAXI_PROTECTEN2_STA1[2])
+ * Data: 1'b0
+ * Action: polling
+ */
+ check = 0;
+ CONSYS_REG_BIT_POLLING(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1, 28, 0x0, 100, 500, check);
+ if (check != 0)
+ pr_err("Polling AHB RX bus sleep protect turn off fail. status=0x%08x\n",
+ CONSYS_REG_READ(REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1));
+#endif
+
+ /* Turn off AXI Rx bus sleep protect (CONN2AP AXI Rx Bus protect)
+ * (disable sleep protection when CONNSYS had been turned on)
+ * Note : Should turn off AXI Rx sleep protection first.
+ * Address:
+ * INFRA_TOPAXI_PROTECTEN_CLR (0x1000_12A4[31:0])
+ * Value: 32'h0000_4000
+ * Action: write32
+ */
+ CONSYS_REG_WRITE(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_CLR, 0x00004000);
+
+ /* Turn off AXI TX bus sleep protect (AP2CONN AXI Bus protect)
+ * (apply this for INFRA AXI bus accessing when CONNSYS had been turned on)
+ *
+ * INFRA_TOPAXI_PROTECTEN_CLR (0x1000_12A4) = 32'h0800_0000
+ */
+ CONSYS_REG_WRITE(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_CLR, 0x08000000);
+
+ /* Turn off AHB TX bus sleep protect (AP2CONN AXI Bus protect)
+ * (apply this for INFRA AXI bus accessing when CONNSYS had been turned on)
+ *
+ * INFRA_TOPAXI_PROTECTEN_CLR (0x1000_12A4[31:0]) = 32'h0000_2000
+ */
+ CONSYS_REG_WRITE(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_CLR, 0x00002000);
+
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ /* Check AHB TX bus sleep protect turn off
+ * (polling ""100 times"" and each polling interval is ""0.5ms"")
+ * If AP2CONN (TX/RX) protect turn off fail, power on fail.
+ * (DRV access connsys CR will trigger bus hang,
+ * because bus transaction wiil queue at GALS, )
+ *
+ * INFRA_TOPAXI_PROTECTEN_STA1[13] (0x1000_1228[13]) = 1'b0
+ * Action: polling
+ * Note: AP2CONN AHB bus related setting
+ */
+ check = 0;
+ CONSYS_REG_BIT_POLLING(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1, 13, 0x0, 100, 500, check);
+ if (check != 0) {
+ pr_err("Polling 0x1000_1228[13] fail, exp is 0 but get 0x%08x",
+ CONSYS_REG_READ(REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1));
+ return -1;
+ }
+#endif /* CONFIG_FPGA_EARLY_PORTING */
+ /* Wait 6ms (apply this for CONNSYS XO clock ready) */
+ msleep(6);
+#endif /* MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE */
+ } else {
+ /* conn2ap/ap2conn slpprot enable */
+#if MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE
+ pr_info("Turn off conn_infra power by SPM API\n");
+ ret = consys_platform_spm_conn_ctrl(enable);
+ if (ret) {
+ pr_err("Turn off conn_infra power fail, ret=%d\n", ret);
+ return -1;
+ }
+#else
+ /* Turn on AHB TX bus sleep protect (AP2CONN AXI Bus protect)
+ * (apply this for INFRA AXI bus protection to prevent bus hang when
+ * CONNSYS had been turned off)
+ * Address: 0x1000_12a0[31:0]
+ * Data: 0x0000_2000
+ * Action: write
+ */
+ CONSYS_REG_WRITE(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_SET,
+ 0x00002000);
+
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ /* check AHB TX bus sleep protect turn on (polling "100 times")
+ * Address: 0x1000_1228[13]
+ * Data: 1'b1
+ * Action: polling
+ */
+ check = 0;
+ CONSYS_REG_BIT_POLLING(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1,
+ 13, 1, 100, 1000, check);
+ if (check)
+ pr_err("Polling AHB TX bus sleep protect turn on fail.\n");
+#endif /* CONFIG_FPGA_EARLY_PORTING */
+
+ /* Turn on AXI Tx bus sleep protect (CONN2AP AXI Tx Bus protect)
+ * (apply this for INFRA AXI bus protection to prevent bus hang
+ * when CONNSYS had been turned off)
+ * Note:
+ * Should turn on AXI Tx sleep protection first.
+ * Address:
+ * INFRA_TOPAXI_PROTECTEN_SET
+ * 0x1000_12A0[31:0]=32'h0800_0000
+ */
+ CONSYS_REG_WRITE(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_SET,
+ 0x08000000);
+
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ /* Check AXI Tx bus sleep protect turn on
+ * (polling "100 times", polling interval is 1ms)
+ * Address: INFRA_TOPAXI_PROTECTEN_STA1[27] (0x1000_1228[27])
+ * Value: 1'b1
+ */
+ check = 0;
+ CONSYS_REG_BIT_POLLING(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1,
+ 27, 1, 100, 1000, check);
+ if (check)
+ pr_err("Polling AXI Tx bus sleep protect turn on fail.");
+#endif
+
+ /* Turn on AXI Rx bus sleep protect (CONN2AP AXI RX Bus protect)
+ * (apply this for INFRA AXI bus protection to prevent bus hang when
+ * CONNSYS had been turned off)
+ * Note:
+ * Should turn on AXI Rx sleep protection after
+ * AXI Tx sleep protection has been turn on.
+ * Address: 0x1000_12A0[31:0]
+ * Data: 0x0000_4000
+ * Action: write
+ */
+ CONSYS_REG_WRITE(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_SET,
+ 0x00004000);
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ /* check AXI Rx bus sleep protect turn on
+ * (polling "100 times", polling interval is 1ms)
+ * Address: 0x1000_1228[14]
+ * Data: 1'b1
+ * Action: polling
+ */
+ check = 0;
+ CONSYS_REG_BIT_POLLING(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1,
+ 14, 1, 100, 1000, check);
+ if (check)
+ pr_err("Polling AXI Rx bus sleep protect turn on fail.\n");
+#endif
+ /* Turn on AHB RX bus sleep protect (AP2CONN AXI Bus protect)
+ * (apply this for INFRA AXI bus protection to prevent bus hang
+ * when CONNSYS had been turned off)
+ * INFRA_TOPAXI_PROTECTEN_SET
+ * 0x1000_12A0[31:0]=32'h1000_0000
+ */
+ CONSYS_REG_WRITE(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_SET,
+ 0x10000000);
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ /* Check AHB RX bus sleep protect turn on (polling "10 times")
+ * INFRA_TOPAXI_PROTECTEN_STA1[28] (0x1000_1228[28]), value: 1'b1
+ */
+ check = 0;
+ CONSYS_REG_BIT_POLLING(
+ REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1,
+ 28, 1, 100, 1000, check);
+ if (check)
+ pr_err("Polling AHB RX bus (AP2CONN) sleep protect turn on fail.");
+#endif
+ /* Power off connsys MTCMOS */
+ /* Assert "conn_infra_on" isolation, set "connsys_iso_en"=1
+ * Address: CONN_PWR_CON[1] (0x1000_6304[1])
+ * Value: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, (0x1<<1));
+
+ /* Assert CONNSYS S/W reset (SPM CR), set "ap_sw_rst_b"=0
+ * Address: CONN_PWR_CON[0] (0x1000_6304[0])
+ * Value: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x1);
+
+ /* Assert CONNSYS S/W reset(TOP RGU CR), set "ap_sw_rst_b"=0
+ * Address: WDT_SWSYSRST[9] (0x1000_7018[9])
+ * WDT_SWSYSRST[31:24] (0x1000_7018[31:24])
+ * Value: [9]=1'b1
+ * [31:24]=8'h88 (key)
+ * Action: write
+ * Note: this CR value for reset control is active high (0: not reset, 1: reset)
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_TOP_RGU_ADDR + TOP_RGU_WDT_SWSYSRST,
+ 0x88000200,
+ 0xff000200);
+
+ /* Turn off AP-to-CONNSYS bus clock, set "conn_clk_dis"=1
+ * (apply this for bus clock gating)
+ * Address: CONN_PWR_CON[4] (0x1000_6304[4])
+ * Value: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, (0x1<<4));
+
+ /* wait 1us (?) */
+ udelay(1);
+
+ /* De-assert "conn_infra_on" primary part power on,
+ * set "connsys_on_domain_pwr_on"=0
+ * Address: CONN_PWR_CON[2] (0x1000_6304[2])
+ * Value: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, (0x1<<2));
+
+ /* De-assert "conn_infra_on" secondary part power on,
+ * set "connsys_on_domain_pwr_on_s"=0
+ * Address: CONN_PWR_CON[3] (0x1000_6304[3])
+ * Value: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, (0x1<<3));
+#endif /* MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE */
+ }
+ return 0;
+}
+
+int consys_conninfra_wakeup(void)
+{
+ /* Wake up conn_infra
+ * Address: CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP (0x180601a0)
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_REG_WRITE(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP,
+ 0x1);
+
+ /* Check CONNSYS version ID
+ * (polling "10 times" for specific project code and each polling interval is "1ms")
+ */
+ if (consys_polling_chipid_int(10, 1) != 0) {
+ pr_err("[%s] Polling chip id fail\n", __func__);
+ return -1;
+ }
+ return 0;
+}
+
+int consys_conninfra_sleep(void)
+{
+ /* Release conn_infra force on
+ * Address: CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP (0x180601a0)
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_REG_WRITE(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP,
+ 0x0);
+ return 0;
+}
+
+void consys_set_if_pinmux(unsigned int enable)
+{
+ if (enable) {
+ /* Set pinmux for the interface between D-die and A-die (Aux1)
+ * (CONN_HRST_B/CONN_TOP_CLK/CONN_TOP_DATA)
+ * Address:
+ * 0x1000_53F8 = 32'hF0000000 (GPIO_MODE15_CLR[30:28]: GPIO127
+ * 0x1000_53F4 = 32'h10000000 (GPIO_MODE15_SET[30:28]: GPIO127
+ * 0x1000_5408 = 32'h000000FF (GPIO_MODE16_CLR[2:0]: GPIO128, [6:4]:GPIO129)
+ * 0x1000_5404 = 32'h00000011 (GPIO_MODE16_SET[2:0]: GPIO128, [6:4]:GPIO129)
+ * Note: GPIO127/GPIO128/GPIO129
+ */
+ CONSYS_REG_WRITE(REG_GPIO_BASE_ADDR + GPIO_MODE15_CLR, 0xf0000000);
+ CONSYS_REG_WRITE(REG_GPIO_BASE_ADDR + GPIO_MODE15_SET, 0x10000000);
+ CONSYS_REG_WRITE(REG_GPIO_BASE_ADDR + GPIO_MODE16_CLR, 0x000000ff);
+ CONSYS_REG_WRITE(REG_GPIO_BASE_ADDR + GPIO_MODE16_SET, 0x00000011);
+
+ /* Set pinmux driving to 2mA
+ * Address:
+ * 0x11D1_0008 = 32'h000001ff
+ * (DRV_CFG0_CLR[2:0]: conn_hrst_b, [5:3]: conn_top_clk, [8:6]: conn_top_data)
+ * Action: write32
+ * CODA: IOCFG_BM
+ */
+ CONSYS_REG_WRITE(REG_IOCFG_BM_ADDR + IOCFG_BM_DRV_CFG0_CLR, 0x000001ff);
+
+ /* POS update: 20200325, fix typo */
+ /* Set CONN_TOP_CLK/CONN_TOP_DATA driving to 4mA
+ * Address:
+ * 0x11D1_0004 = 32'h00000048 (00000000_00000000_00000000_01001000)
+ * (DRV_CFG0_SET[2:0]: conn_hrst_b, [5:3]: conn_top_clk, [8:6]: conn_top_data)
+ * Action: write32
+ * CODA: IOCFG_BM
+ */
+ CONSYS_REG_WRITE(REG_IOCFG_BM_ADDR + IOCFG_BM_DRV_CFG0_SET, 0x00000048);
+
+ /* Set pinmux PUPD setting
+ * Clear CONN_TOP_DATA PD setting
+ * Address:
+ * 0x11D1_00d8 = 32'h00000010
+ * (PD_CFG0_CLR[4]: conn_top_data, 1:CLEAR bit)
+ * CODA: IOCFG_BM
+ */
+ CONSYS_REG_WRITE(REG_IOCFG_BM_ADDR + IOCFG_BM_PD_CFG0_CLR, 0x00000010);
+
+ /* Set pinmux PUPD setting
+ * CONN_TOP_DATA as PU
+ * Address:
+ * 0x11D1_0114 = 32'h00000010
+ * (PU_CFG0_SET[4]: conn_top_data, 1: SET bit)
+ * CODA: IOCFG_BM
+ */
+ CONSYS_REG_WRITE(REG_IOCFG_BM_ADDR + IOCFG_BM_PU_CFG0_SET, 0x00000010);
+ } else {
+ /* Set pinmux for the interface between D-die and A-die (Aux0)
+ * 0x1000_53F8=32'hF0000000
+ * 0x1000_5408=32'h000000FF
+ */
+ CONSYS_REG_WRITE(REG_GPIO_BASE_ADDR + GPIO_MODE15_CLR, 0xf0000000);
+ CONSYS_REG_WRITE(REG_GPIO_BASE_ADDR + GPIO_MODE16_CLR, 0x000000ff);
+ /* Set pinmux PUPD setting
+ * Clear CONN_TOP_DATA PU setting
+ * 0x11D1_0118=32'h00000010
+ * [2]: conn_hrst_b
+ * [3]: conn_top_clk
+ * [4]: conn_top_data
+ */
+ CONSYS_REG_WRITE(REG_GPIO_BASE_ADDR + IOCFG_BM_PU_CFG0_CLR, 0x00000010);
+ /* Set pinmux PUPD setting
+ * CONN_TOP_DATA as PD
+ * 0x11D1_00d4=32'h00000010
+ * [2]: conn_hrst_b
+ * [3]: conn_top_clk
+ * [4]: conn_top_data
+ */
+ CONSYS_REG_WRITE(REG_GPIO_BASE_ADDR + IOCFG_BM_PD_CFG0_SET, 0x00000010);
+ }
+#ifdef CONFIG_FPGA_EARLY_PORTING
+ pr_info("[%s] not for FPGA\n", __func__);
+#endif
+}
+
+int consys_polling_chipid_int(unsigned int retry, unsigned int sleep_ms)
+{
+ unsigned int count = retry + 1;
+ unsigned int consys_hw_ver = 0;
+ unsigned int consys_configuration_id = 0;
+
+ while (--count > 0) {
+ consys_hw_ver = CONSYS_REG_READ(
+ REG_CONN_INFRA_CFG_ADDR +
+ CONN_HW_VER_OFFSET);
+ if (consys_hw_ver == CONN_HW_VER) {
+ consys_configuration_id = CONSYS_REG_READ(
+ REG_CONN_INFRA_CFG_ADDR + CONN_CFG_ID_OFFSET);
+ pr_info("Consys HW version id(0x%x) cfg_id=(0x%x)\n",
+ consys_hw_ver, consys_configuration_id);
+ break;
+ }
+ msleep(sleep_ms);
+ }
+
+ if (count == 0) {
+ pr_err("Read CONSYS version id fail. Expect 0x%x but get 0x%x\n",
+ CONN_HW_VER, consys_hw_ver);
+ return -1;
+ }
+
+ return 0;
+}
+
+int consys_polling_chipid(void)
+{
+ return consys_polling_chipid_int(10, 1);
+}
+
+int connsys_d_die_cfg(void)
+{
+ unsigned int efuse;
+ /* Read D-die Efuse
+ * Address: AP2CONN_EFUSE_DATA (0x1800_1020)
+ * Data:
+ * Action: read
+ */
+ efuse = CONSYS_REG_READ(REG_CONN_INFRA_CFG_ADDR + AP2CONN_EFUSE_DATA);
+ pr_info("D-die efuse: 0x%08x", efuse);
+
+ /* POS update: 20200325: Update conn_infra sysram hwctrl setting
+ */
+#if 0
+ /* conn_infra sysram hw control setting -> disable hw power down
+ * Address: CONN_INFRA_RGU_SYSRAM_HWCTL_PDN_SYSRAM_HWCTL_PDN (0x1800_0050)
+ * Data: 32'h0
+ * Action: write
+ */
+ CONSYS_REG_WRITE(
+ REG_CONN_INFRA_RGU_ADDR + CONN_INFRA_RGU_SYSRAM_HWCTL_PDN_SYSRAM_HWCTL_PDN, 0x0);
+
+ /* conn_infra sysram hw control setting -> enable hw sleep
+ * Address: CONN_INFRA_RGU_SYSRAM_HWCTL_SLP_SYSRAM_HWCTL_SLP (0x1800_0054)
+ * Data: 32'h0000_00FF
+ * Action: write
+ */
+ CONSYS_REG_WRITE(
+ REG_CONN_INFRA_RGU_ADDR + CONN_INFRA_RGU_SYSRAM_HWCTL_SLP_SYSRAM_HWCTL_SLP,
+ 0x000000ff);
+#endif
+ return 0;
+}
+
+int connsys_spi_master_cfg(unsigned int next_status)
+{
+ /* TOP_CK_ADDR 0x18005084[11:0] 0x02C
+ *
+ * GPS_CK_ADDR 0x18005088[11:0] 0xA0C
+ * GPS_L5_CK_ADDR 0x18005088[27:16] 0xAFC
+ * => 0x1800_5088=0x0afc_0a0c
+ *
+ * GPS_RFBUF_ADR 0x18005094[11:0] 0x0FC
+ * GPS_L5_EN_ADDR 0x18005098[11:0] 0x0F8
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_TOP_CK_ADDR,
+ 0x02c, 0xfff);
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_GPS_CK_ADDR,
+ 0x0afc0a0c, 0x0fff0fff);
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_GPS_RFBUF_ADDR,
+ 0x0fc, 0xfff);
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_GPS_L5_EN_ADDR,
+ 0x0f8, 0xfff);
+
+ /* CMD_LENGTH 0x18005004[4:0] 0x8
+ * WB_BG_ADDR1 0x18005010 0xA03C
+ * WB_BG_ADDR2 0x18005014 0xA03C
+ * WB_BG_ADDR3 0x18005018 0xAA18
+ * WB_BG_ADDR4 0x1800501C 0xAA18
+ * WB_BG_ADDR5 0x18005020 0xA0C8
+ * WB_BG_ADDR6 0x18005024 0xAA00
+ * WB_BG_ADDR7 0x18005028 0xA0B4
+ * WB_BG_ADDR8 0x1800502C 0xA34C
+ * WB_BG_ON1 0x18005030 0x00000000
+ * WB_BG_ON2 0x18005034 0x00000000
+ * WB_BG_ON3 0x18005038 0x74E0FFF5
+ * WB_BG_ON4 0x1800503C 0x76E8FFF5
+ * WB_BG_ON5 0x18005040 0x00000000
+ * WB_BG_ON6 0x18005044 0xFFFFFFFF
+ * WB_BG_ON7 0x18005048 0x00000019
+ * WB_BG_ON8 0x1800504C 0x00010400
+ * WB_BG_OFF1 0x18005050 0x57400000
+ * WB_BG_OFF2 0x18005054 0x57400000
+ * WB_BG_OFF3 0x18005058 0x44E0FFF5
+ * WB_BG_OFF4 0x1800505C 0x44E0FFF5
+ * WB_BG_OFF5 0x18005060 0x00000001
+ * WB_BG_OFF6 0x18005064 0x00000000
+ * WB_BG_OFF7 0x18005068 0x00040019
+ * WB_BG_OFF8 0x1800506C 0x00410440
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_SLP_CTL,
+ 0x8, 0x1f);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR1,
+ 0xa03c);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR2,
+ 0xa03c);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR3,
+ 0xaa18);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR4,
+ 0xaa18);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR5,
+ 0xa0c8);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR6,
+ 0xaa00);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR7,
+ 0xa0b4);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR8,
+ 0xa34c);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON1,
+ 0x0);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON2,
+ 0x0);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON3,
+ 0x74E0FFF5);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON4,
+ 0x76E8FFF5);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON5,
+ 0x0);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON6,
+ 0xFFFFFFFF);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON7,
+ 0x00000019);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON8,
+ 0x00010400);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF1,
+ 0x57400000);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF2,
+ 0x57400000);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF3,
+ 0x44E0FFF5);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF4,
+ 0x44E0FFF5);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF5,
+ 0x00000001);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF6,
+ 0x00000000);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF7,
+ 0x00040019);
+ CONSYS_REG_WRITE(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF8,
+ 0x00410440);
+
+ return 0;
+}
+
+#ifndef CONFIG_FPGA_EARLY_PORTING
+/*****************************************************************************
+* FUNCTION
+* connsys_a_die_efuse_read
+* DESCRIPTION
+* Read a-die efuse
+* PARAMETERS
+* efuse_addr: read address
+* RETURNS
+* int
+* 0: fail, efuse is invalid
+* 1: success, efuse is valid
+*****************************************************************************/
+static int connsys_a_die_efuse_read_nolock(
+ unsigned int efuse_addr,
+ unsigned int* data0, unsigned int* data1,
+ unsigned int* data2, unsigned int* data3)
+{
+ int ret = 0;
+ int retry = 0;
+ int ret0, ret1, ret2, ret3;
+
+ if (data0 == NULL || data1 == NULL || data2 == NULL || data3 == NULL) {
+ pr_err("[%s] invalid parameter (%p, %p, %p, %p)",
+ __func__, data0, data1, data2, data3);
+ return 0;
+ }
+ /* Efuse control clear, clear Status /trigger
+ * Address: ATOP EFUSE_CTRL_write_efsrom_kick_and_read_kick_busy_flag (0x108[30])
+ * Data: 1'b0
+ * Action: TOPSPI_WR
+ */
+ consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret);
+ ret &= ~(0x1 << 30);
+ consys_spi_write_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, ret);
+
+ /* Efuse Read 1st 16byte
+ * Address:
+ * ATOP EFUSE_CTRL_efsrom_mode (0x108[7:6]) = 2'b00
+ * ATOP EFUSE_CTRL_efsrom_ain (0x108[25:16]) = efuse_addr (0)
+ * ATOP EFUSE_CTRL_write_efsrom_kick_and_read_kick_busy_flag (0x108[30]) = 1'b1
+ * Action: TOPSPI_WR
+ */
+ consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret);
+ ret &= ~(0x43ff00c0);
+ ret |= (0x1 << 30);
+ ret |= ((efuse_addr << 16) & 0x3ff0000);
+ consys_spi_write_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, ret);
+
+ /* Polling EFUSE busy = low
+ * (each polling interval is "30us" and polling timeout is 2ms)
+ * Address:
+ * ATOP EFUSE_CTRL_write_efsrom_kick_and_read_kick_busy_flag (0x108[30]) = 1'b0
+ * Action: TOPSPI_Polling
+ */
+ consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret);
+ while ((ret & (0x1 << 30)) != 0 && retry < 70) {
+ retry++;
+ udelay(30);
+ consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret);
+ }
+ if ((ret & (0x1 << 30)) != 0) {
+ pr_info("[%s] EFUSE busy, retry failed(%d)\n", __func__, retry);
+ }
+
+ /* Check efuse_valid & return
+ * Address: ATOP EFUSE_CTRL_csri_efsrom_dout_vld_sync_1_ (0x108[29])
+ * Action: TOPSPI_RD
+ */
+ /* if (efuse_valid == 1'b1)
+ * Read Efuse Data to global var
+ */
+ consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret);
+ if (((ret & (0x1 << 29)) >> 29) == 1) {
+ ret0 = consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_RDATA0, data0);
+ ret1 = consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_RDATA1, data1);
+ ret2 = consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_RDATA2, data2);
+ ret3 = consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_RDATA3, data3);
+
+ pr_info("efuse = [0x%08x, 0x%08x, 0x%08x, 0x%08x]", *data0, *data1, *data2, *data3);
+ if (ret0 || ret1 || ret2 || ret3)
+ pr_err("efuse read error: [%d, %d, %d, %d]", ret0, ret1, ret2, ret3);
+ ret = 1;
+ } else {
+ pr_err("EFUSE is invalid\n");
+ ret = 0;
+ }
+ return ret;
+}
+#endif
+
+#if CFG_CONNINFRA_THERMAL_SUPPORT
+static int connsys_a_die_thermal_cal(
+ int efuse_valid,
+ unsigned int efuse0, unsigned int efuse1, unsigned int efuse2, unsigned int efuse3)
+{
+ struct consys_plat_thermal_data input;
+
+ memset(&input, 0, sizeof(struct consys_plat_thermal_data));
+ if (efuse_valid) {
+ if (efuse1 & (0x1 << 7)) {
+ consys_spi_write_offset_range_nolock(
+ SYS_SPI_TOP, ATOP_RG_TOP_THADC_BG, efuse1, 12, 3, 4);
+ consys_spi_write_offset_range_nolock(
+ SYS_SPI_TOP, ATOP_RG_TOP_THADC, efuse1, 23, 0, 3);
+ }
+ if(efuse1 & (0x1 << 15)) {
+ consys_spi_write_offset_range_nolock(
+ SYS_SPI_TOP, ATOP_RG_TOP_THADC, efuse1, 26, 13, 2);
+ input.slop_molecule = (efuse1 & 0x1f00) >> 8;
+ pr_info("slop_molecule=[%d]", input.slop_molecule);
+ }
+ if (efuse1 & (0x1 << 23)) {
+ /* [22:16] */
+ input.thermal_b = (efuse1 & 0x7f0000) >> 16;
+ pr_info("thermal_b =[%d]", input.thermal_b);
+ }
+ if (efuse1 & (0x1 << 31)) {
+ input.offset = (efuse1 & 0x7f000000) >> 24;
+ pr_info("offset=[%d]", input.offset);
+ }
+ }
+ input.efuse0 = efuse0;
+ input.efuse1 = efuse1;
+ input.efuse2 = efuse2;
+ input.efuse3 = efuse3;
+
+ update_thermal_data(&input);
+ return 0;
+}
+#endif /* CFG_CONNINFRA_THERMAL_SUPPORT */
+
+int connsys_a_die_cfg(void)
+{
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ int check;
+ unsigned int adie_chip_id = 0x0;
+ int efuse_valid = 0;
+ unsigned int efuse0 = 0, efuse1 = 0, efuse2 = 0, efuse3 = 0;
+
+ /* De-assert A-die reset
+ * Address:
+ * CONN_INFRA_CFG_ADIE_CTL_ADIE_RSTB (0x18001030[0])
+ * Value: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(REG_CONN_INFRA_CFG_ADDR + CONN_INFRA_CFG_ADIE_CTL, 0x1);
+
+ /* Get semaphore once */
+ if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) {
+ pr_err("[%s] Require semaphore fail\n", __func__);
+ return -1;
+ }
+
+ /* Read MT6635 ID
+ * Address:
+ * ATOP CHIP_ID
+ * 0x02C[31:16]: hw_code
+ * 0x02C[15:0]: hw_ver
+ * Action: TOPSPI_RD
+ * Note:
+ * MT6635 E1 : read 0x02C = 0x66358A00;
+ * MT6635 E2 : read 0x02C = 0x66358A10;
+ * MT6635 E3 : read 0x02C = 0x66358A11;
+ */
+ check = consys_spi_read_nolock(SYS_SPI_TOP, ATOP_CHIP_ID, &adie_chip_id);
+ if (check) {
+ /* Release semaphore */
+ consys_sema_release(CONN_SEMA_RFSPI_INDEX);
+ pr_err("[%s] Get ATOP_CHIP_ID fail, check=%d", __func__, check);
+ return -1;
+ }
+ pr_info("A-die CHIP ID is 0x%x", adie_chip_id);
+ conn_hw_env.adie_hw_version = adie_chip_id;
+ conn_hw_env.is_rc_mode = 0;
+
+ /* Update spi fm read extra bit setting
+ * CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_EN 0x1800400C[15]=1'b0
+ * CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_CNT 0x1800400C[7:0]=8'h0
+ * Action: write
+ * Note:
+ * Need update this setting when fm is at power-off state,
+ * otherwise spi access FM CR will fail
+ */
+ CONSYS_CLR_BIT(REG_CONN_RFSPI_ADDR + CONN_RF_SPI_MST_REG_FM_CTRL, (0x1 << 15));
+ CONSYS_CLR_BIT(REG_CONN_RFSPI_ADDR + CONN_RF_SPI_MST_REG_FM_CTRL, (0xff));
+
+ /* Update Thermal addr for 6635
+ * CONN_TOP_THERM_CTL_THERM_AADDR
+ * 0x18002018=32'h50305A00
+ */
+ CONSYS_REG_WRITE(REG_CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_AADDR, 0x50305A00);
+
+ /* Rread efuse Data(000) */
+ efuse_valid = connsys_a_die_efuse_read_nolock(0x0, &efuse0, &efuse1, &efuse2, &efuse3);
+ /* Thermal Cal (TOP) */
+#if CFG_CONNINFRA_THERMAL_SUPPORT
+ connsys_a_die_thermal_cal(efuse_valid, efuse0, efuse1, efuse2, efuse3);
+#endif
+ /* Increase XOBUF supply-V
+ * ATOP RG_TOP_XTAL_01 (0XA18) = 32'hF6E8FFF5
+ * Action: TOPSPI_WR
+ */
+ consys_spi_write_nolock(SYS_SPI_TOP, ATOP_RG_TOP_XTAL_01, 0xF6E8FFF5);
+
+ /* Increase XOBUF supply-R for MT6635 E1
+ * ATOP RG_TOP_XTAL_02 (0XA1C)
+ * if(MT6635 E1) //rf_hw_ver = 0x8a00
+ * 32'hD5555FFF
+ * else
+ * 32'h0x55555FFF
+ * Action: TOPSPI_WR
+ */
+ if (adie_chip_id == 0x66358a00)
+ consys_spi_write_nolock(SYS_SPI_TOP, ATOP_RG_TOP_XTAL_02, 0xD5555FFF);
+ else
+ consys_spi_write_nolock(SYS_SPI_TOP, ATOP_RG_TOP_XTAL_02, 0x55555FFF);
+
+ /* Release semaphore */
+ consys_sema_release(CONN_SEMA_RFSPI_INDEX);
+#endif
+
+ return 0;
+}
+
+int connsys_afe_wbg_cal(void)
+{
+ /* 20200622:
+ * Confirmed with DE, all config are default value, now.
+ */
+ return 0;
+}
+
+int connsys_subsys_pll_initial(void)
+{
+ /* Check with DE, only 26M on mobile phone */
+ /* CONN_AFE_CTL_RG_PLL_STB_TIME_RG_WBG_BPLL_STB_TIME 0x180030F4[30:16] 0x314
+ * CONN_AFE_CTL_RG_PLL_STB_TIME_RG_WBG_WPLL_STB_TIME 0x180030F4[14:0] 0x521
+ * CONN_AFE_CTL_RG_DIG_EN_02_RG_WBG_EN_BT_PLL 0x18003004[7:6] 0x1
+ * CONN_AFE_CTL_RG_DIG_EN_02_RG_WBG_EN_WF_PLL 0x18003004[1:0] 0x3
+ * CONN_AFE_CTL_RG_DIG_EN_02_RG_WBG_EN_MCU_PLL 0x18003004[3:2] 0x1
+ * CONN_AFE_CTL_RG_DIG_EN_02_RG_WBG_EN_MCU_PLL_WF 0x18003004[17:16] 0x3
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_PLL_STB_TIME,
+ 0x03140521, 0x7fff7fff);
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_02,
+ 0x30047, 0x300cf);
+
+ return 0;
+}
+
+int connsys_low_power_setting(unsigned int curr_status, unsigned int next_status)
+{
+ /* For this 6880, only GPS is need. Other should be reject. */
+ if (curr_status != 0 || next_status != (0x1 << CONNDRV_TYPE_GPS)) {
+ pr_err("[%s] Unsupport status: curr(0x%08x), next(0x%08x)",
+ __func__, curr_status, next_status);
+ return -1;
+ }
+ /* Unmask on2off/off2on slpprot_rdy enable checker @conn_infra off power off
+ * => check slpprot_rdy = 1'b1 and go to sleep
+ *
+ * CONN_INFRA_CFG_PWRCTRL0_CONN_INFRA_CFG_SLP_RDY_MASK
+ * 0x18001200[15:12] = 4'h1
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_INFRA_CFG_ADDR + CONN_INFRA_CFG_PWRCTRL0, (0x1 << 12), 0xf000);
+
+ if (!consys_is_rc_mode_enable()) {
+ /* Legacy mode */
+ /* Disable conn_top rc osc_ctrl_top
+ * CONN_INFRA_CFG_RC_CTL_0_CONN_INFRA_OSC_RC_EN
+ * 0x18001380[7] = 1'b0
+ */
+ CONSYS_CLR_BIT(REG_CONN_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0, (0x1<<7));
+ /* Legacy OSC control stable time
+ *
+ * CONN_INFRA_CFG_OSC_CTL_0_XO_VCORE_RDY_STABLE_TIME
+ * 0x18001300[7:0]=8'd6
+ * CONN_INFRA_CFG_OSC_CTL_0_XO_INI_STABLE_TIME
+ * 0x18001300[15:8]=8'd7
+ * CONN_INFRA_CFG_OSC_CTL_0_XO_BG_STABLE_TIME
+ * 0x18001300[23:16]=8'd8
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_INFRA_CFG_ADDR + CONN_INFRA_CFG_OSC_CTL_0,
+ 0x080706, 0x00ffffff);
+ /* Legacy OSC control unmask conn_srcclkena_ack
+ * CONN_INFRA_CFG_OSC_CTL_1_ACK_FOR_XO_STATE_MASK
+ * 0x18001304[16] = 1'b0
+ */
+ CONSYS_CLR_BIT(
+ REG_CONN_INFRA_CFG_ADDR + CONN_INFRA_CFG_OSC_CTL_1, (0x1<<16));
+ } else {
+ /* RC mode */
+ /* GPS RC OSC control stable time
+ * CONN_INFRA_CFG_RC_CTL_1_GPS_XO_VCORE_RDY_STABLE_TIME_0
+ * 0x18001394[7:0]=8'd6
+ * CONN_INFRA_CFG_RC_CTL_1_GPS_XO_INI_STABLE_TIME_0
+ * 0x18001394[15:8]=8'd7
+ * CONN_INFRA_CFG_RC_CTL_1_GPS_XO_BG_STABLE_TIME_0
+ * 0x18001394[23:16]=8'd8
+ * CONN_INFRA_CFG_RC_CTL_1_GPS_XO_VCORE_OFF_STABLE_TIME_0
+ * 0x18001394[31:24]=8'd2
+ * 0x18001394[7:0]
+ */
+ CONSYS_REG_WRITE(
+ REG_CONN_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_1_GPS, 0x02080706);
+ /* GPS RC OSC control unmask conn_srcclkena_ack
+ * CONN_INFRA_CFG_RC_CTL_0_GPS_ACK_FOR_XO_STATE_MASK_0
+ * 0x18001390[15] = 1'b0
+ */
+ CONSYS_CLR_BIT(
+ REG_CONN_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0_GPS, (0x1<<15));
+ /* TOP RC OSC control stable time
+ * CONN_INFRA_CFG_RC_CTL_1_TOP_XO_VCORE_RDY_STABLE_TIME_3
+ * 0x180013C4[7:0]=8'd6
+ * CONN_INFRA_CFG_RC_CTL_1_TOP_XO_INI_STABLE_TIME_3
+ * 0x180013C4[15:8]=8'd7
+ * CONN_INFRA_CFG_RC_CTL_1_TOP_XO_BG_STABLE_TIME_3
+ * 0x180013C4[23:16]=8'd8
+ * CONN_INFRA_CFG_RC_CTL_1_TOP_XO_VCORE_OFF_STABLE_TIME_3
+ * 0x180013C4[31:24]=8'd2"
+ */
+ CONSYS_REG_WRITE(
+ REG_CONN_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_1_TOP,
+ 0x02080706);
+ /* TOP RC OSC control unmask conn_srcclkena_ack
+ * CONN_INFRA_CFG_RC_CTL_0_TOP_ACK_FOR_XO_STATE_MASK_3
+ * 0x180013C0[15]=1'b0
+ */
+ CONSYS_CLR_BIT(
+ REG_CONN_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0_TOP, (0x1<<15));
+
+ /* Enable conn_top rc osc_ctrl_gps
+ * CONN_INFRA_CFG_RC_CTL_0_GPSSYS_OSC_RC_EN
+ * 0x18001380[4]=1'b1
+ */
+ CONSYS_SET_BIT(
+ REG_CONN_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0, (0x1<<4));
+ /* Set conn_srcclkena control by conn_infra_emi_ctl
+ * CONN_INFRA_CFG_EMI_CTL_0_CONN_EMI_RC_EN
+ * 0x18001400[0]=1'b1
+ */
+ CONSYS_SET_BIT(
+ REG_CONN_INFRA_CFG_ADDR + CONN_INFRA_CFG_EMI_CTL_0, 0x1);
+
+ /* Disable legacy osc control
+ * CONN_INFRA_CFG_RC_CTL_0_OSC_LEGACY_EN
+ * 0x18001380[0]=1'b0
+ */
+ CONSYS_CLR_BIT(
+ REG_CONN_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0, 0x1);
+ }
+ /* conn2ap sleep protect release bypass ddr_en_ack check
+ * CONN_INFRA_CFG_EMI_CTL_0_DDR_EN_BP_PROT
+ * 0x18001400[18]=1'b1
+ */
+ CONSYS_SET_BIT(
+ REG_CONN_INFRA_CFG_ADDR + CONN_INFRA_CFG_EMI_CTL_0, (0x1<<18));
+ /* Enable ddr_en timeout, timeout value = 1023T (Bus clock)
+ * CONN_INFRA_CFG_EMI_CTL_0_DDR_CNT_LIMIT
+ * 0x18001400[14:4]=11'd1023
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_INFRA_CFG_ADDR + CONN_INFRA_CFG_EMI_CTL_0, 0x3ff0, 0x7ff0);
+ /* Enable ddr_en timeout value update (rising edge)
+ * CONN_INFRA_CFG_EMI_CTL_0_DDR_EN_CNT_UPDATE
+ * 0x18001400[15]=1'b1
+ */
+ CONSYS_SET_BIT(
+ REG_CONN_INFRA_CFG_ADDR + CONN_INFRA_CFG_EMI_CTL_0, (0x1<<15));
+ /* Disable ddr_en timeout value update (falling edge)
+ * CONN_INFRA_CFG_EMI_CTL_0_DDR_EN_CNT_UPDATE
+ * 0x18001400[15]=1'b0
+ */
+ CONSYS_CLR_BIT(
+ REG_CONN_INFRA_CFG_ADDR + CONN_INFRA_CFG_EMI_CTL_0, (0x1<<15));
+
+ /* Disable conn_infra off pwr_ack mask
+ * CONN_INFRA_RGU_CONN_INFRA_OFF_TOP_PWR_CTL_CONN_INFRA_OFF_TOP_PWR_ACK_S_MASK
+ * 0x18000000[31:16]=16'h494E (key)
+ * 0x18000000[6]=1'b0
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_INFRA_RGU_ADDR + CONN_INFRA_RGU_CONN_INFRA_OFF_TOP_PWR_CTL,
+ 0x494e0000, 0xffff0040);
+
+ /* Disable A-die top_ck_en (for Bring-up keep a-die dig_top ck on)
+ * Call common API
+ * ATOP Clock default on, need to turn off manually
+ */
+ consys_adie_top_ck_en_top_ctrl(0);
+
+ /* Select conn_infra_cfg debug_sel to low power related
+ * CONN_HOST_CSR_TOP_CONN_INFRA_CFG_DBG_SEL_CONN_INFRA_CFG_DBG_SEL
+ * 0x1806015c[2:0]=3'b000
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_CFG_DBG_SEL,
+ 0x0, 0x7);
+
+ /* OFF domain AHB slaves timeout limit setting
+ * CONN_INFRA_BUS_CR_CONN_INFRA_BUS_OFF_TIMEOUT_CTRL_CONN_INFRA_OFF_TIMEOUT_LIMIT
+ * 0x1800E300[14:7]=8'h02
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_INFRA_BUS_CR_ADDR + CONN_INFRA_BUS_OFF_TIMEOUT_CTRL,
+ (0x2 << 7), 0x7f80);
+
+ /* Enable off domain AHB slaves timeout
+ * CONN_INFRA_BUS_CR_CONN_INFRA_BUS_OFF_TIMEOUT_CTRL_CONN_INFRA_OFF_TIMEOUT_EN
+ * 0x1800E300[2]=1'b1
+ * CONN_INFRA_BUS_CR_CONN_INFRA_BUS_OFF_TIMEOUT_CTRL_CONN_INFRA_OFF_AHB_MUX_EN
+ * 0x1800E300[1]=1'b1
+ * CONN_INFRA_BUS_CR_CONN_INFRA_BUS_OFF_TIMEOUT_CTRL_CONN_INFRA_OFF_APB_MUX_EN
+ * 0x1800E300[0]=1'b1
+ */
+ CONSYS_SET_BIT(
+ REG_CONN_INFRA_BUS_CR_ADDR + CONN_INFRA_BUS_OFF_TIMEOUT_CTRL,
+ 0x7);
+
+ /* ON domain APB slaves timeout limit setting
+ * CONN_INFRA_BUS_CR_CONN_INFRA_BUS_ON_TIMEOUT_CTRL_CONN_INFRA_ON_TIMEOUT_LIMIT
+ * 0x1800E31C[14:7]=8'h02
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_INFRA_BUS_CR_ADDR + CONN_INFRA_BUS_ON_TIMEOUT_CTRL,
+ (0x2 << 7), 0x7f80);
+
+ /* Enable on domain APB slaves timeout
+ * CONN_INFRA_BUS_CR_CONN_INFRA_BUS_ON_TIMEOUT_CTRL_CONN_INFRA_ON_TIMEOUT_EN
+ * 0x1800E31C[2]=1'b1
+ * CONN_INFRA_BUS_CR_CONN_INFRA_BUS_ON_TIMEOUT_CTRL_CONN_INFRA_ON_AHB_MUX_EN
+ * 0x1800E31C[1]=1'b1
+ * CONN_INFRA_BUS_CR_CONN_INFRA_BUS_ON_TIMEOUT_CTRL_CONN_INFRA_ON_APB_MUX_EN
+ * 0x1800E31C[0]=1'b1
+ */
+ CONSYS_SET_BIT(
+ REG_CONN_INFRA_BUS_CR_ADDR + CONN_INFRA_BUS_ON_TIMEOUT_CTRL,
+ 0x7);
+
+ /* Hold timeout reset
+ * CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_VDNR_GEN_ON_U_DEBUG_CTRL_AO_CONN_INFRA_ON_CTRL0_reset_setting
+ * 0x1802F000[9] = 1'b1
+ */
+ CONSYS_SET_BIT(
+ REG_CONN_INFRA_DEBUG_CTRL_AO + CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_ON_CTRL0,
+ (0x1 << 9));
+
+ /* Set conn_infra bus timeout value
+ * CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_VDNR_GEN_ON_U_DEBUG_CTRL_AO_CONN_INFRA_ON_CTRL0_timeout_thres
+ * 0x1802F000[31:16]=16'h23BC
+ */
+ CONSYS_REG_WRITE_MASK(
+ REG_CONN_INFRA_DEBUG_CTRL_AO + CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_ON_CTRL0,
+ 0x23BC0000, 0xFFFF0000);
+
+ /* Enable conn_infra bus timeout
+ * CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_VDNR_GEN_ON_U_DEBUG_CTRL_AO_CONN_INFRA_ON_CTRL0_debug_en
+ * 0x1802F000[2]=1'b1
+ * CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_VDNR_GEN_ON_U_DEBUG_CTRL_AO_CONN_INFRA_ON_CTRL0_debug_cken
+ * 0x1802F000[3]=1'b1
+ */
+ CONSYS_SET_BIT(
+ REG_CONN_INFRA_DEBUG_CTRL_AO + CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_ON_CTRL0,
+ 0xc);
+
+ /* Release timeout reset
+ * CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_VDNR_GEN_ON_U_DEBUG_CTRL_AO_CONN_INFRA_ON_CTRL0_reset_setting
+ * 0x1802F000[9] = 1'b0
+ */
+ CONSYS_CLR_BIT(
+ REG_CONN_INFRA_DEBUG_CTRL_AO + CONN_INFRA_DEBUG_CTRL_AO_CONN_INFRA_ON_CTRL0,
+ (0x1 << 9));
+
+ /* Enable conn_infra_cfg setting
+ * (osc_en would pull low after conn_infra mtcmos off)
+ * CONN_INFRA_CFG_PWRCTRL0_HWCTL_OSC_ON_CHECK_TOP_PWR_EN
+ * 0x1800_1200[9]=1'b1
+ */
+ CONSYS_SET_BIT(
+ REG_CONN_INFRA_CFG_ADDR + CONN_INFRA_CFG_PWRCTRL0, (0x1 << 9));
+
+ /* Enable bpll divder2 enable for conn_infra bus hclk
+ * CONN_INFRA_CLKGEN_ON_TOP_CKGEN_BUS_BPLL_DIV_2_BPLL_DIV_2_DIV_EN
+ * 0x18009004[0]=1'b1
+ */
+ CONSYS_SET_BIT(
+ REG_CONN_INFRA_CLKGEN_ON_TOP_ADDR + CONN_INFRA_CKGEN_BUS_BPLL_DIV_2, 0x1);
+
+ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+ /* !!!!!!!!!!!!!!!!!!!!!! CANNOT add code after HERE!!!!!!!!!!!!!!!!!!!!!!!!!! */
+ /* !!!!!!!!!!!!!!!!!!!!!!! conninfra may go to sleep !!!!!!!!!!!!!!!!!!!!!!!!! */
+ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+ /* Disable conn_infra bus clock sw control ==> conn_infra bus clock hw control
+ * CONN_INFRA_CFG_CKGEN_BUS_HCLK_CKSEL_SWCTL
+ * 0x1800_9A00[23]=1'b0
+ */
+ CONSYS_CLR_BIT(
+ REG_CONN_INFRA_CLKGEN_ON_TOP_ADDR + CONN_INFRA_CLKGEN_ON_TOP_CKGEN_BUS, (0x1<<23));
+ /* Conn_infra HW_CONTROL => conn_infra enter dsleep mode
+ * CONN_INFRA_CFG_PWRCTRL0_HW_CONTROL
+ * 0x1800_1200[0]=1'b1
+ */
+ CONSYS_SET_BIT(
+ REG_CONN_INFRA_CFG_ADDR + CONN_INFRA_CFG_PWRCTRL0, 0x1);
+ return 0;
+}
+
+static int consys_sema_acquire(enum conn_semaphore_type index)
+{
+ if (CONSYS_REG_READ_BIT(
+ REG_CONN_SEMAPHORE_ADDR + CONN_SEMAPHORE_M2_OWN_STA + index*4, 0x1) == 0x1) {
+ return CONN_SEMA_GET_SUCCESS;
+ } else {
+ return CONN_SEMA_GET_FAIL;
+ }
+}
+
+int consys_sema_acquire_timeout(unsigned int index, unsigned int usec)
+{
+ int i;
+
+ if (index >= CONN_SEMA_NUM_MAX) {
+ pr_err("[%s] wrong index: %d", __func__, index);
+ return CONN_SEMA_GET_FAIL;
+ }
+
+ for (i = 0; i < usec; i++) {
+ if (consys_sema_acquire(index) == CONN_SEMA_GET_SUCCESS) {
+ return CONN_SEMA_GET_SUCCESS;
+ }
+ udelay(1);
+ }
+ pr_err("Get semaphore 0x%x timeout, dump status:\n", index);
+ pr_err("M2:[0x%x] M3:[0x%x]\n",
+ CONSYS_REG_READ(REG_CONN_SEMAPHORE_ADDR + CONN_SEMA_OWN_BY_M2_STA_REP),
+ CONSYS_REG_READ(REG_CONN_SEMAPHORE_ADDR + CONN_SEMA_OWN_BY_M3_STA_REP));
+ return CONN_SEMA_GET_FAIL;
+}
+
+void consys_sema_release(unsigned int index)
+{
+ if (index >= CONN_SEMA_NUM_MAX) {
+ pr_err("[%s] wrong index: %d", __func__, index);
+ return;
+ }
+
+ CONSYS_REG_WRITE(
+ (REG_CONN_SEMAPHORE_ADDR + CONN_SEMAPHORE_M2_OWN_REL + index*4), 0x1);
+}
+
+struct spi_op {
+ unsigned int busy_cr;
+ unsigned int polling_bit;
+ unsigned int addr_cr;
+ unsigned int read_addr_format;
+ unsigned int write_addr_format;
+ unsigned int write_data_cr;
+ unsigned int read_data_cr;
+ unsigned int read_data_mask;
+};
+
+static const struct spi_op spi_op_array[SYS_SPI_MAX] = {
+ /* SYS_SPI_WF1 */
+ {
+ CONN_RF_SPI_MST_REG_SPI_STA, 1,
+ CONN_RF_SPI_MST_REG_SPI_WF_ADDR, 0x00001000, 0x00000000,
+ CONN_RF_SPI_MST_REG_SPI_WF_WDAT,
+ CONN_RF_SPI_MST_REG_SPI_WF_RDAT, 0xffffffff
+ },
+ /* SYS_SPI_WF */
+ {
+ CONN_RF_SPI_MST_REG_SPI_STA, 1,
+ CONN_RF_SPI_MST_REG_SPI_WF_ADDR, 0x00003000, 0x00002000,
+ CONN_RF_SPI_MST_REG_SPI_WF_WDAT,
+ CONN_RF_SPI_MST_REG_SPI_WF_RDAT, 0xffffffff
+ },
+ /* SYS_SPI_BT */
+ {
+ CONN_RF_SPI_MST_REG_SPI_STA, 2,
+ CONN_RF_SPI_MST_REG_SPI_BT_ADDR, 0x00005000, 0x00004000,
+ CONN_RF_SPI_MST_REG_SPI_BT_WDAT,
+ CONN_RF_SPI_MST_REG_SPI_BT_RDAT, 0x000000ff
+ },
+ /* SYS_SPI_FM */
+ {
+ CONN_RF_SPI_MST_REG_SPI_STA, 3,
+ CONN_RF_SPI_MST_REG_SPI_FM_ADDR, 0x00007000, 0x00006000,
+ CONN_RF_SPI_MST_REG_SPI_FM_WDAT,
+ CONN_RF_SPI_MST_REG_SPI_FM_RDAT, 0x0000ffff
+ },
+ /* SYS_SPI_GPS */
+ {
+ CONN_RF_SPI_MST_REG_SPI_STA, 4,
+ CONN_RF_SPI_MST_REG_SPI_GPS_GPS_ADDR, 0x00009000, 0x00008000,
+ CONN_RF_SPI_MST_REG_SPI_GPS_GPS_WDAT,
+ CONN_RF_SPI_MST_REG_SPI_GPS_GPS_RDAT, 0x0000ffff
+ },
+ /* SYS_SPI_TOP */
+ {
+ CONN_RF_SPI_MST_REG_SPI_STA, 5,
+ CONN_RF_SPI_MST_REG_SPI_TOP_ADDR, 0x0000b000, 0x0000a000,
+ CONN_RF_SPI_MST_REG_SPI_TOP_WDAT,
+ CONN_RF_SPI_MST_REG_SPI_TOP_RDAT, 0xffffffff
+ },
+ /* SYS_SPI_WF2 */
+ {
+ CONN_RF_SPI_MST_REG_SPI_STA, 1,
+ CONN_RF_SPI_MST_REG_SPI_WF_ADDR, 0x0000d000, 0x0000c000,
+ CONN_RF_SPI_MST_REG_SPI_WF_WDAT,
+ CONN_RF_SPI_MST_REG_SPI_WF_RDAT, 0xffffffff
+ },
+ /* SYS_SPI_WF3 */
+ {
+ CONN_RF_SPI_MST_REG_SPI_STA, 1,
+ CONN_RF_SPI_MST_REG_SPI_WF_ADDR, 0x0000f000, 0x0000e000,
+ CONN_RF_SPI_MST_REG_SPI_WF_WDAT,
+ CONN_RF_SPI_MST_REG_SPI_WF_RDAT, 0xffffffff
+ },
+};
+
+static int consys_spi_read_nolock(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data)
+{
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ /* Read action:
+ * 1. Polling busy_cr[polling_bit] should be 0
+ * 2. Write addr_cr with data being {read_addr_format | addr[11:0]}
+ * 3. Trigger SPI by writing write_data_cr as 0
+ * 4. Polling busy_cr[polling_bit] as 0
+ * 5. Read data_cr[data_mask]
+ */
+ int check = 0;
+ const struct spi_op* op = &spi_op_array[subsystem];
+
+ if (!data) {
+ pr_err("[%s] invalid data ptr\n", __func__);
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+
+ CONSYS_REG_BIT_POLLING(
+ REG_CONN_RFSPI_ADDR + op->busy_cr,
+ op->polling_bit, 0, 100, 50, check);
+ if (check != 0) {
+ pr_err("[%s][%d][STEP1] polling 0x%08lx bit %d fail. Value=0x%08x\n",
+ __func__, subsystem, REG_CONN_RFSPI_ADDR + op->busy_cr,
+ op->polling_bit,
+ CONSYS_REG_READ(REG_CONN_RFSPI_ADDR + op->busy_cr));
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+
+ CONSYS_REG_WRITE(
+ REG_CONN_RFSPI_ADDR + op->addr_cr,
+ (op->read_addr_format | addr));
+
+ CONSYS_REG_WRITE(REG_CONN_RFSPI_ADDR + op->write_data_cr, 0);
+
+ check = 0;
+ CONSYS_REG_BIT_POLLING(
+ REG_CONN_RFSPI_ADDR + op->busy_cr,
+ op->polling_bit, 0, 100, 50, check);
+ if (check != 0) {
+ pr_err("[%s][%d][STEP4] polling 0x%08lx bit %d fail. Value=0x%08x\n",
+ __func__, subsystem, REG_CONN_RFSPI_ADDR + op->busy_cr,
+ op->polling_bit,
+ CONSYS_REG_READ(REG_CONN_RFSPI_ADDR + op->busy_cr));
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+
+ check = CONSYS_REG_READ_BIT(REG_CONN_RFSPI_ADDR + op->read_data_cr, op->read_data_mask);
+ *data = check;
+#else
+ *data = 0;
+#endif /* CONFIG_FPGA_EARLY_PORTING */
+ return 0;
+}
+
+int consys_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data)
+{
+ int ret;
+
+ /* Get semaphore before read */
+ if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) {
+ pr_err("[SPI READ] Require semaphore fail\n");
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+
+ ret = consys_spi_read_nolock(subsystem, addr, data);
+
+ consys_sema_release(CONN_SEMA_RFSPI_INDEX);
+
+ return ret;
+}
+
+static int consys_spi_write_nolock(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data)
+{
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ int check = 0;
+ const struct spi_op* op = &spi_op_array[subsystem];
+
+ /* Write action:
+ * 1. Wait busy_cr[polling_bit] as 0
+ * 2. Write addr_cr with data being {write_addr_format | addr[11:0]
+ * 3. Write write_data_cr ad data
+ * 4. Wait busy_cr[polling_bit] as 0
+ */
+ CONSYS_REG_BIT_POLLING(
+ REG_CONN_RFSPI_ADDR + op->busy_cr,
+ op->polling_bit, 0, 100, 50, check);
+ if (check != 0) {
+ pr_err("[%s][%d][STEP1] polling 0x%08lx bit %d fail. Value=0x%08x\n",
+ __func__, subsystem, REG_CONN_RFSPI_ADDR + op->busy_cr,
+ op->polling_bit,
+ CONSYS_REG_READ(REG_CONN_RFSPI_ADDR + op->busy_cr));
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+
+ CONSYS_REG_WRITE(REG_CONN_RFSPI_ADDR + op->addr_cr, (op->write_addr_format | addr));
+
+ CONSYS_REG_WRITE(REG_CONN_RFSPI_ADDR + op->write_data_cr, data);
+
+ check = 0;
+ CONSYS_REG_BIT_POLLING(
+ REG_CONN_RFSPI_ADDR + op->busy_cr,
+ op->polling_bit, 0, 100, 50, check);
+ if (check != 0) {
+ pr_err("[%s][%d][STEP4] polling 0x%08lx bit %d fail. Value=0x%08x\n",
+ __func__, subsystem, REG_CONN_RFSPI_ADDR + op->busy_cr,
+ op->polling_bit,
+ CONSYS_REG_READ(REG_CONN_RFSPI_ADDR + op->busy_cr));
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+#endif /* CONFIG_FPGA_EARLY_PORTING */
+ return 0;
+
+}
+
+
+int consys_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data)
+{
+ int ret;
+
+ /* Get semaphore before read */
+ if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) {
+ pr_err("[SPI WRITE] Require semaphore fail\n");
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+
+ ret = consys_spi_write_nolock(subsystem, addr, data);
+
+ consys_sema_release(CONN_SEMA_RFSPI_INDEX);
+ return ret;
+}
+
+int consys_spi_write_offset_range(
+ enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int value,
+ unsigned int reg_offset, unsigned int value_offset, unsigned int size)
+{
+ if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) {
+ pr_err("[SPI READ] Require semaphore fail\n");
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+ consys_spi_write_offset_range_nolock(
+ subsystem, addr, value, reg_offset, value_offset, size);
+
+ consys_sema_release(CONN_SEMA_RFSPI_INDEX);
+ return 0;
+}
+
+static void consys_spi_write_offset_range_nolock(
+ enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int value,
+ unsigned int reg_offset, unsigned int value_offset, unsigned int size)
+{
+ unsigned int data = 0, data2;
+ unsigned int reg_mask;
+ int ret;
+
+ pr_info("[%s][%s] addr=0x%04x value=0x%08x reg_offset=%d value_offset=%d size=%d",
+ __func__, g_spi_system_name[subsystem], addr, value, reg_offset, value_offset, size);
+ value = (value >> value_offset);
+ value = GET_BIT_RANGE(value, size, 0);
+ value = (value << reg_offset);
+ ret = consys_spi_read_nolock(subsystem, addr, &data);
+ if (ret) {
+ pr_err("[%s][%s] Get 0x%08x error, ret=%d",
+ __func__, g_spi_system_name[subsystem], addr, ret);
+ return;
+ }
+ reg_mask = GENMASK(reg_offset + size - 1, reg_offset);
+ data2 = data & (~reg_mask);
+ data2 = (data2 | value);
+ consys_spi_write_nolock(subsystem, addr, data2);
+ pr_info("[%s][%s] Write CR:0x%08x from 0x%08x to 0x%08x",
+ __func__, g_spi_system_name[subsystem],
+ addr, data, data2);
+}
+
+static int consys_adie_top_ck_en_top_ctrl(bool on)
+{
+ int check = 0;
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ /* 0x18005120[0] == 1'b1/1'b0
+ * 1'b1/1'b0: Enable/Disable dig_top_ck in Adie
+ * Adress in Adie: 12'hA00
+ */
+ if (on)
+ CONSYS_SET_BIT(REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_WB_SLP_TOP_CK_0, (0x1 << 0));
+ else
+ CONSYS_CLR_BIT(REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_WB_SLP_TOP_CK_0, (0x1 << 0));
+
+ /* POLLING 0x18005120[1] == 1'b0
+ * Wait 0x18005120[1] == 1'b0 (Wait finish status)
+ */
+ CONSYS_REG_BIT_POLLING(
+ REG_CONN_WT_SPL_CTL_ADDR + CONN_WT_SLP_WB_SLP_TOP_CK_0,
+ 1, 0, 10, 10, check);
+ if (check == -1) {
+ pr_err("[%s] %s fail\n", __func__, (on? "turn on" : "turn off"));
+ }
+#endif
+ return check;
+}
+
+bool consys_is_rc_mode_enable(void)
+{
+ /* Not support RC mode */
+ return 0;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/include/mt6885.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/include/mt6885.h
new file mode 100755
index 0000000..6b06700
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/include/mt6885.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_MT6885_H_
+#define _PLATFORM_MT6885_H_
+
+enum conn_semaphore_type
+{
+ CONN_SEMA_CHIP_POWER_ON_INDEX = 0,
+ CONN_SEMA_CALIBRATION_INDEX = 1,
+ CONN_SEMA_FW_DL_INDEX = 2,
+ CONN_SEMA_CLOCK_SWITCH_INDEX = 3,
+ CONN_SEMA_CCIF_INDEX = 4,
+ CONN_SEMA_COEX_INDEX = 5,
+ CONN_SEMA_USB_EP0_INDEX = 6,
+ CONN_SEMA_USB_SHARED_INFO_INDEX = 7,
+ CONN_SEMA_USB_SUSPEND_INDEX = 8,
+ CONN_SEMA_USB_RESUME_INDEX = 9,
+ CONN_SEMA_PCIE_INDEX = 10,
+ CONN_SEMA_RFSPI_INDEX = 11,
+ CONN_SEMA_EFUSE_INDEX = 12,
+ CONN_SEMA_THERMAL_INDEX = 13,
+ CONN_SEMA_FLASH_INDEX = 14,
+ CONN_SEMA_DEBUG_INDEX = 15,
+ CONN_SEMA_WIFI_LP_INDEX = 16,
+ CONN_SEMA_PATCH_DL_INDEX = 17,
+ CONN_SEMA_SHARED_VAR_INDEX = 18,
+ CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX = 19,
+ CONN_SEMA_NUM_MAX = 32 /* can't be omitted */
+};
+
+int consys_platform_spm_conn_ctrl(unsigned int enable);
+int consys_co_clock_type(void);
+
+struct consys_plat_thermal_data {
+ int thermal_b;
+ int slop_molecule;
+ int offset;
+};
+
+void update_thermal_data(struct consys_plat_thermal_data* input);
+#endif /* _PLATFORM_MT6885_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/include/mt6885_consys_reg.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/include/mt6885_consys_reg.h
new file mode 100755
index 0000000..70fc7cd
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/include/mt6885_consys_reg.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_MT6885_CONSYS_REG_H_
+#define _PLATFORM_MT6885_CONSYS_REG_H_
+
+#include "consys_reg_base.h"
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+enum consys_base_addr_index {
+ CONN_INFRA_RGU_BASE_INDEX = 0,
+ CONN_INFRA_CFG_BASE_INDEX = 1,
+ CONN_HOST_CSR_TOP_BASE_INDEX = 2,
+ INFRACFG_AO_BASE_INDEX = 3,
+ TOPRGU_BASE_INDEX= 4,
+ SPM_BASE_INDEX = 5,
+ INFRACFG_BASE_INDEX = 6,
+ CONN_WT_SLP_CTL_REG_INDEX = 7,
+ CONN_AFE_CTL_INDEX = 8,
+ CONN_INFRA_SYSRAM_INDEX = 9,
+ GPIO_INDEX = 10,
+ CONN_RF_SPI_MST_REG_INDEX = 11,
+ CONN_SEMAPHORE_INDEX = 12,
+ CONN_TOP_THERM_CTL_INDEX = 13,
+ IOCFG_RT_INDEX = 14, /* Base: 0x11EA_0000 */
+ CONN_DEBUG_CTRL = 15, /* Base: 0x1800_f000 */
+
+ CONSYS_BASE_ADDR_MAX
+};
+
+
+struct consys_base_addr {
+ struct consys_reg_base_addr reg_base_addr[CONSYS_BASE_ADDR_MAX];
+};
+
+extern struct consys_base_addr conn_reg;
+
+#define CON_REG_INFRA_RGU_ADDR conn_reg.reg_base_addr[CONN_INFRA_RGU_BASE_INDEX].vir_addr
+#define CON_REG_INFRA_CFG_ADDR conn_reg.reg_base_addr[CONN_INFRA_CFG_BASE_INDEX].vir_addr
+#define CON_REG_HOST_CSR_ADDR conn_reg.reg_base_addr[CONN_HOST_CSR_TOP_BASE_INDEX].vir_addr
+#define CON_REG_INFRACFG_AO_ADDR conn_reg.reg_base_addr[INFRACFG_AO_BASE_INDEX].vir_addr
+
+#define CON_REG_TOP_RGU_ADDR conn_reg.reg_base_addr[TOPRGU_BASE_INDEX].vir_addr
+#define CON_REG_SPM_BASE_ADDR conn_reg.reg_base_addr[SPM_BASE_INDEX].vir_addr
+#define CON_REG_INFRACFG_BASE_ADDR conn_reg.reg_base_addr[INFRACFG_BASE_INDEX].vir_addr
+#define CON_REG_WT_SPL_CTL_ADDR conn_reg.reg_base_addr[CONN_WT_SLP_CTL_REG_INDEX].vir_addr
+
+#define CONN_AFE_CTL_BASE_ADDR conn_reg.reg_base_addr[CONN_AFE_CTL_INDEX].vir_addr
+#define CONN_INFRA_SYSRAM_BASE_ADDR conn_reg.reg_base_addr[CONN_INFRA_SYSRAM_INDEX].vir_addr
+#define GPIO_BASE_ADDR conn_reg.reg_base_addr[GPIO_INDEX].vir_addr
+#define CONN_REG_RFSPI_ADDR conn_reg.reg_base_addr[CONN_RF_SPI_MST_REG_INDEX].vir_addr
+
+#define CONN_REG_SEMAPHORE_ADDR conn_reg.reg_base_addr[CONN_SEMAPHORE_INDEX].vir_addr
+#define CONN_TOP_THERM_CTL_ADDR conn_reg.reg_base_addr[CONN_TOP_THERM_CTL_INDEX].vir_addr
+#define IOCFG_RT_ADDR conn_reg.reg_base_addr[IOCFG_RT_INDEX].vir_addr
+#define CONN_DEBUG_CTRL_ADDR conn_reg.reg_base_addr[CONN_DEBUG_CTRL].vir_addr
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+struct consys_base_addr* get_conn_reg_base_addr(void);
+
+#endif /* _PLATFORM_MT6885_CONSYS_REG_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/include/mt6885_consys_reg_offset.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/include/mt6885_consys_reg_offset.h
new file mode 100755
index 0000000..0dc808e
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/include/mt6885_consys_reg_offset.h
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_MT6885_CONSYS_REG_OFFSET_H_
+#define _PLATFORM_MT6885_CONSYS_REG_OFFSET_H_
+
+
+/**********************************************************************/
+/* Base: infracfg_ao (0x1000_1000) */
+/**********************************************************************/
+#define INFRA_TOPAXI_PROTECTEN_STA1_OFFSET 0x0228
+#define INFRA_TOPAXI_PROTECTEN_SET_OFFSET 0x02a0
+#define INFRA_TOPAXI_PROTECTEN_CLR_OFFSET 0x02a4
+#define INFRA_TOPAXI_PROTECTEN2_CLR_OFFSET 0x0718
+#define INFRA_TOPAXI_PROTECTEN2_SET_OFFSET 0x0714
+#define INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET 0x0724
+
+/**********************************************************************/
+/* Base: GPIO (0x1000_5000) */
+/**********************************************************************/
+#define GPIO_DIR5_SET 0x0054
+
+#define GPIO_DOUT5_SET 0x0154
+
+#define GPIO_MODE19 0x0430
+#define GPIO_MODE21 0x0450
+#define GPIO_MODE22 0x0460
+
+/**********************************************************************/
+/* Base: SPM (0x1000_6000) */
+/**********************************************************************/
+#define SPM_POWERON_CONFIG_EN 0x0000
+#define SPM_PCM_REG13_DATA 0x0110
+#define SPM_PCM_REG7_DATA 0x0100
+#define SPM_SRC_REQ_STA_0 0x0114
+#define SPM_BUS_PROTECT_RDY 0x0150
+#define SPM_BUS_PROTECT2_RDY 0x0158
+#define SPM_PWR_STATUS 0x016c
+#define SPM_PWR_STATUS_2ND 0x0170
+#define SPM_CONN_PWR_CON 0x0304
+#define SPM_PLL_CON 0x044C
+#define SPM_RC_CENTRAL_CFG1 0x0504
+#define SPM_PCM_WDT_LATCH_SPARE_0 0x084C
+
+#define SPM_RC_RC_M04_REQ_STA_0 0xE28
+#define SPM_RC_RC_M05_REQ_STA_0 0xE2C
+#define SPM_RC_RC_M06_REQ_STA_0 0xE30
+#define SPM_RC_RC_M07_REQ_STA_0 0xE34
+
+/**********************************************************************/
+/* Base: TOP RGU (0x1000_7000) */
+/**********************************************************************/
+#define TOP_RGU_WDT_SWSYSRST 0x0018
+
+
+/**********************************************************************/
+/* Base: INFRACFG (0x1020_e000) */
+/**********************************************************************/
+#define INFRA_AP2MD_GALS_CTL 0x0504
+#define INFRA_CONN2AP_GLAS_RC_ST 0x0804
+
+/**********************************************************************/
+/* Base: IOCFG_RT (0x11EA_0000) */
+/**********************************************************************/
+#define IOCFG_RT_DRV_CFG0 0x0000
+#define IOCFG_RT_PD_CFG0_SET 0x0054
+#define IOCFG_RT_PD_CFG0_CLR 0x0058
+#define IOCFG_RT_PU_CFG0_SET 0x0074
+#define IOCFG_RT_PU_CFG0_CLR 0x0078
+
+/**********************************************************************/
+/* Base: conn_infra_rgu (0x1800_0000) */
+/**********************************************************************/
+#define CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_CTL 0x0008
+#define CONN_INFRA_RGU_SYSRAM_HWCTL_PDN 0x0038
+#define CONN_INFRA_RGU_SYSRAM_HWCTL_SLP 0x003c
+#define CONN_INFRA_RGU_CO_EXT_MEM_HWCTL_PDN 0x0050
+#define CONN_INFRA_RGU_CO_EXT_MEM_HWCTL_SLP 0x0054
+#define CONN_INFRA_RGU_DEBUG_SEL 0x0090
+
+/**********************************************************************/
+/* Base: conn_infra_cfg (0x1800_1000) */
+/**********************************************************************/
+#define CONN_HW_VER_OFFSET 0x0000
+#define CONN_CFG_ID_OFFSET 0x0004
+#define CONN_INFRA_CFG_LIGHT_SECURITY_CTRL 0x00f0
+
+#define CONN_INFRA_CFG_GALS_AP2CONN_GALS_DBG 0x0160
+#define CONN_INFRA_CFG_GALS_CONN2AP_TX_SLP_CTRL 0x0630
+#define CONN_INFRA_CFG_GALS_CONN2AP_RX_SLP_CTRL 0x0634
+#define CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL 0x061C
+#define CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL 0x0618
+#define CONN_INFRA_CFG_GALS_BT2CONN_SLP_CTRL 0x0614
+#define CONN_INFRA_CFG_GALS_CONN2BT_SLP_CTRL 0x0610
+
+#define CONN_INFRA_CFG_WF_SLP_CTRL 0x0620
+#define CONN_INFRA_CFG_ON_BUS_SLP_CTRL 0x0628
+#define CONN_INFRA_CFG_OFF_BUS_SLP_CTRL 0x062C
+
+
+#define CONN_INFRA_CFG_OSC_CTL_0 0x0800
+#define CONN_INFRA_CFG_OSC_CTL_1 0x0804
+#define CONN_INFRA_CFG_OSC_STATUS 0x080C
+#define CONN_INFRA_CFG_PLL_STATUS 0x0810
+
+#define AP2CONN_EFUSE_DATA 0x0818
+#define CONN_INFRA_CFG_RC_CTL_0 0x0834
+#define CONN_INFRA_CFG_RC_CTL_0 0x0834
+#define CONN_INFRA_CFG_RC_CTL_0_GPS 0x0838
+#define CONN_INFRA_CFG_RC_CTL_1_GPS 0x083C
+#define CONN_INFRA_CFG_RC_CTL_0_BT 0x0840
+#define CONN_INFRA_CFG_RC_CTL_1_BT 0x0844
+#define CONN_INFRA_CFG_RC_CTL_0_WF 0x0848
+#define CONN_INFRA_CFG_RC_CTL_1_WF 0x084c
+#define CONN_INFRA_CFG_RC_CTL_1_TOP 0x0854
+#define CONN_INFRA_CFG_RC_CTL_0_TOP 0x0850
+#define CONN_INFRA_CFG_PWRCTRL0 0x0860
+#define CONN_INFRA_CFG_ADIE_CTL 0x0900
+#define CONN_INFRA_CFG_CKGEN_BUS 0x0a00
+#define CONN_INFRA_CFG_DBG_MUX_SEL 0x0b00
+#define CONN_INFRA_CFG_EMI_CTL_0 0x0c00
+
+#define CONN_HW_VER 0x20010000
+#define CONN_CFG_ID 0x3
+
+/**********************************************************************/
+/* Base: conn_top_therm_ctl (0x1800_2000) */
+/**********************************************************************/
+#define CONN_TOP_THERM_CTL_THERMCR1 0x0004
+#define CONN_TOP_THERM_CTL_THERM_AADDR 0x0018
+#define CONN_TOP_THERM_CTL_THERM_CAL_EN 0x0024
+
+/**********************************************************************/
+/* Base: conn_afe_ctl(0x1800_3000) */
+/**********************************************************************/
+#define CONN_AFE_CTL_RG_DIG_EN_01 0x0000
+#define CONN_AFE_CTL_RG_DIG_EN_02 0x0004
+#define CONN_AFE_CTL_RG_DIG_EN_03 0x0008
+#define CONN_AFE_CTL_RG_WBG_AFE_01 0x0010
+#define CONN_AFE_CTL_RG_WBG_RCK_01 0x0018
+#define CONN_AFE_CTL_RG_WBG_GL1_01 0x0040
+#define CONN_AFE_CTL_RG_WBG_BT_TX_03 0x0058
+#define CONN_AFE_CTL_RG_WBG_WF0_TX_03 0x0078
+#define CONN_AFE_CTL_RG_WBG_WF1_TX_03 0x0094
+#define CONN_AFE_CTL_RG_PLL_STB_TIME 0x00f4
+#define CONN_AFE_CTL_RG_WBG_GL5_01 0x0100
+
+
+/**********************************************************************/
+/* Base: conn_rf_spi_mst_reg(0x1800_4000) */
+/**********************************************************************/
+#define CONN_RF_SPI_MST_REG_SPI_STA 0x0000
+#define CONN_RF_SPI_MST_REG_SPI_CRTL 0x0004
+#define CONN_RF_SPI_MST_REG_FM_CTRL 0x000c
+#define CONN_RF_SPI_MST_REG_SPI_WF_ADDR 0x0010
+#define CONN_RF_SPI_MST_REG_SPI_WF_WDAT 0x0014
+#define CONN_RF_SPI_MST_REG_SPI_WF_RDAT 0x0018
+#define CONN_RF_SPI_MST_REG_SPI_BT_ADDR 0x0020
+#define CONN_RF_SPI_MST_REG_SPI_BT_WDAT 0x0024
+#define CONN_RF_SPI_MST_REG_SPI_BT_RDAT 0x0028
+#define CONN_RF_SPI_MST_REG_SPI_FM_ADDR 0x0030
+#define CONN_RF_SPI_MST_REG_SPI_FM_WDAT 0x0034
+#define CONN_RF_SPI_MST_REG_SPI_FM_RDAT 0x0038
+#define CONN_RF_SPI_MST_REG_SPI_TOP_ADDR 0x0050
+#define CONN_RF_SPI_MST_REG_SPI_TOP_WDAT 0x0054
+#define CONN_RF_SPI_MST_REG_SPI_TOP_RDAT 0x0058
+#define CONN_RF_SPI_MST_REG_SPI_GPS_GPS_ADDR 0x0210
+#define CONN_RF_SPI_MST_REG_SPI_GPS_GPS_WDAT 0x0214
+#define CONN_RF_SPI_MST_REG_SPI_GPS_GPS_RDAT 0x0218
+
+
+/**********************************************************************/
+/* Base: conn_wt_slp_ctl_reg(0x1800_5000) */
+/**********************************************************************/
+#define CONN_WTSLP_CTL_REG_WB_STA 0x0008
+#define CONN_WT_SLP_CTL_REG_WB_SLP_CTL 0x0004
+#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR1 0x0010
+#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR2 0x0014
+#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR3 0x0018
+#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR4 0x001c
+#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR5 0x0020
+#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR6 0x0024
+#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR7 0x0028
+#define CONN_WT_SLP_CTL_REG_WB_BG_ADDR8 0x002c
+#define CONN_WT_SLP_CTL_REG_WB_BG_ON1 0x0030
+#define CONN_WT_SLP_CTL_REG_WB_BG_ON2 0x0034
+#define CONN_WT_SLP_CTL_REG_WB_BG_ON3 0x0038
+#define CONN_WT_SLP_CTL_REG_WB_BG_ON4 0x003c
+#define CONN_WT_SLP_CTL_REG_WB_BG_ON5 0x0040
+#define CONN_WT_SLP_CTL_REG_WB_BG_ON6 0x0044
+#define CONN_WT_SLP_CTL_REG_WB_BG_ON7 0x0048
+#define CONN_WT_SLP_CTL_REG_WB_BG_ON8 0x004c
+#define CONN_WT_SLP_CTL_REG_WB_BG_OFF1 0x0050
+#define CONN_WT_SLP_CTL_REG_WB_BG_OFF2 0x0054
+#define CONN_WT_SLP_CTL_REG_WB_BG_OFF3 0x0058
+#define CONN_WT_SLP_CTL_REG_WB_BG_OFF4 0x005c
+#define CONN_WT_SLP_CTL_REG_WB_BG_OFF5 0x0060
+#define CONN_WT_SLP_CTL_REG_WB_BG_OFF6 0x0064
+#define CONN_WT_SLP_CTL_REG_WB_BG_OFF7 0x0068
+#define CONN_WT_SLP_CTL_REG_WB_BG_OFF8 0x006c
+#define CONN_WT_SLP_CTL_REG_WB_WF_CK_ADDR 0x0070
+#define CONN_WT_SLP_CTL_REG_WB_WF_WAKE_ADDR 0x0074
+#define CONN_WT_SLP_CTL_REG_WB_WF_ZPS_ADDR 0x0078
+#define CONN_WT_SLP_CTL_REG_WB_BT_CK_ADDR 0x007c
+#define CONN_WT_SLP_CTL_REG_WB_BT_WAKE_ADDR 0x0080
+#define CONN_WT_SLP_CTL_REG_WB_TOP_CK_ADDR 0x0084
+#define CONN_WT_SLP_CTL_REG_WB_GPS_CK_ADDR 0x0088
+#define CONN_WT_SLP_CTL_REG_WB_WF_B0_CMD_ADDR 0x008c
+#define CONN_WT_SLP_CTL_REG_WB_WF_B1_CMD_ADDR 0x0090
+#define CONN_WT_SLP_CTL_REG_WB_GPS_RFBUF_ADDR 0x0094
+#define CONN_WT_SLP_CTL_REG_WB_GPS_L5_EN_ADDR 0x0098
+
+/**********************************************************************/
+/* Base: GPT2 timer (0x1800_a000) */
+/**********************************************************************/
+#define CONN_GPT2_CTRL_BASE 0x1800a000
+#define CONN_GPT2_CTRL_THERMAL_EN 0x38
+
+/**********************************************************************/
+/* Base: debug_ctrl (0x1800_f000) */
+/**********************************************************************/
+#define CONN_DEBUG_CTRL_REG_OFFSET 0x0000
+
+
+/**********************************************************************/
+/* Base: conn_infra_sysram(0x1805_0000) */
+/**********************************************************************/
+#define CONN_INFRA_SYSRAM_SW_CR_A_DIE_CHIP_ID 0x2800
+#define CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_0 0x2804
+#define CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_1 0x2808
+#define CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_2 0x280C
+#define CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_3 0x2810
+
+#define CONN_INFRA_SYSRAM_SW_CR_D_DIE_EFUSE 0x2820
+
+#define CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL 0x2830
+#define CONN_INFRA_SYSRAM_SW_CR_RADIO_STATUS 0x2834
+
+#define CONN_INFRA_SYSRAM_SW_CR_OFFSET 0x2800
+#define CONN_INFRA_SYSRAM_SW_CR_SIZE (4 * 1024)
+
+
+/**********************************************************************/
+/* Base: conn_host_csr_top (0x1806_0000) */
+/**********************************************************************/
+#define CONN_HOST_CSR_TOP_CSR_DEADFEED_EN_CR 0x0124
+#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS 0x0128
+#define CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT 0x0148
+#define CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL 0x0184
+#define CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP 0x01a0
+/* remap */
+#define CONN2AP_REMAP_MCU_EMI_BASE_ADDR_OFFSET 0x01c4
+#define CONN2AP_REMAP_MD_SHARE_EMI_BASE_ADDR_OFFSET 0x01cc
+#define CONN2AP_REMAP_GPS_EMI_BASE_ADDR_OFFSET 0x01d0
+#define CONN2AP_REMAP_WF_PERI_BASE_ADDR_OFFSET 0x01d4
+#define CONN2AP_REMAP_BT_PERI_BASE_ADDR_OFFSET 0x01d8
+#define CONN2AP_REMAP_GPS_PERI_BASE_ADDR_OFFSET 0x01dc
+
+#define CONN_HOST_CSR_WM_MCU_PC_DBG 0x0204
+#define CONN_HOST_CSR_WM_MCU_GPR_DBG 0x0208
+#define CONN_HOST_CSR_BGF_MCU_PC_DBG 0x022C
+
+#define CONN_HOST_CSR_DBG_DUMMY_0 0x02C0
+#define CONN_HOST_CSR_DBG_DUMMY_2 0x02C8
+#define CONN_HOST_CSR_DBG_DUMMY_3 0x02CC
+#define CONN_HOST_CSR_DBG_DUMMY_4 0x02D0
+#define CONN_HOST_CSR_TOP_BUS_TIMEOUT_IRQ 0x02d4
+
+#define TOP_BUS_MUC_STAT_HCLK_FR_CK_DETECT_BIT (0x1 << 1)
+#define TOP_BUS_MUC_STAT_OSC_CLK_DETECT_BIT (0x1 << 2)
+#define TOP_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_ACK_BIT (0x1 << 5)
+
+/**********************************************************************/
+/* Base: conn_semaphore(0x1807_0000) */
+/**********************************************************************/
+#define CONN_SEMA_OWN_BY_M0_STA_REP 0x0400
+#define CONN_SEMA_OWN_BY_M1_STA_REP 0x1400
+#define CONN_SEMAPHORE_M2_OWN_STA 0x2000
+#define CONN_SEMAPHORE_M2_OWN_REL 0x2200
+#define CONN_SEMA_OWN_BY_M2_STA_REP 0x2400
+#define CONN_SEMA_OWN_BY_M3_STA_REP 0x3400
+
+/**********************************************************************/
+/* A-die CR */
+/**********************************************************************/
+#define ATOP_CHIP_ID 0x02c
+#define ATOP_RG_TOP_THADC_BG 0x034
+#define ATOP_RG_TOP_THADC 0x038
+#define ATOP_WRI_CTR2 0x064
+#define ATOP_RG_ENCAL_WBTAC_IF_SW 0x070
+#define ATOP_SMCTK11 0x0BC
+#define ATOP_EFUSE_CTRL 0x108
+#define ATOP_EFUSE_RDATA0 0x130
+#define ATOP_EFUSE_RDATA1 0x134
+#define ATOP_EFUSE_RDATA2 0x138
+#define ATOP_EFUSE_RDATA3 0x13c
+#define ATOP_RG_WF0_TOP_01 0x380
+#define ATOP_RG_WF0_BG 0x384
+#define ATOP_RG_WF1_BG 0x394
+#define ATOP_RG_WF1_TOP_01 0x390
+#define ATOP_RG_TOP_XTAL_01 0xA18
+#define ATOP_RG_TOP_XTAL_02 0xA1C
+
+
+#endif /* _PLATFORM_MT6885_CONSSY_REG_OFFSET_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/include/mt6885_emi.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/include/mt6885_emi.h
new file mode 100755
index 0000000..2d62bf5
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/include/mt6885_emi.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_MT6885_EMI_H_
+#define _PLATFORM_MT6885_EMI_H_
+
+#include "osal.h"
+#include "emi_mng.h"
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+struct consys_platform_emi_ops* get_consys_platform_emi_ops(void);
+
+struct consys_emi_addr_info* consys_emi_get_phy_addr(void);
+int consys_emi_mpu_set_region_protection(void);
+void consys_emi_get_md_shared_emi(phys_addr_t*, unsigned int*);
+unsigned int consys_emi_get_fw_emi_size(void);
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _PLATFORM_MT6885_EMI_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/include/mt6885_pmic.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/include/mt6885_pmic.h
new file mode 100755
index 0000000..d39491e
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/include/mt6885_pmic.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_MT6885_H_
+#define _PLATFORM_MT6885_H_
+
+#include "osal.h"
+#include "pmic_mng.h"
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+struct consys_platform_pmic_ops* get_consys_platform_pmic_ops(void);
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _PLATFORM_MT6885_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/include/mt6885_pos.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/include/mt6885_pos.h
new file mode 100755
index 0000000..c28c0ce
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/include/mt6885_pos.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _PLATFORM_MT6885_POS_H_
+#define _PLATFORM_MT6885_POS_H_
+
+
+unsigned int consys_emi_set_remapping_reg(phys_addr_t, phys_addr_t);
+
+int consys_conninfra_on_power_ctrl(unsigned int enable);
+int consys_conninfra_wakeup(void);
+int consys_conninfra_sleep(void);
+void consys_set_if_pinmux(unsigned int enable);
+int consys_polling_chipid(void);
+
+int connsys_d_die_cfg(void);
+int connsys_spi_master_cfg(unsigned int);
+int connsys_a_die_cfg(void);
+int connsys_afe_wbg_cal(void);
+int connsys_subsys_pll_initial(void);
+int connsys_low_power_setting(unsigned int, unsigned int);
+
+int consys_sema_acquire_timeout(enum conn_semaphore_type index, unsigned int usec);
+void consys_sema_release(enum conn_semaphore_type index);
+
+int consys_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data);
+int consys_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data);
+int consys_spi_write_offset_range(
+ enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int value,
+ unsigned int reg_offset, unsigned int value_offset, unsigned int size);
+
+int consys_adie_top_ck_en_on(enum consys_adie_ctl_type type);
+int consys_adie_top_ck_en_off(enum consys_adie_ctl_type type);
+
+int consys_spi_clock_switch(enum connsys_spi_speed_type type);
+int consys_subsys_status_update(bool, int);
+bool consys_is_rc_mode_enable(void);
+
+void consys_config_setup(void);
+
+#endif /* _PLATFORM_MT6885_POS_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/mt6885.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/mt6885.c
new file mode 100755
index 0000000..f66ec53
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/mt6885.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/memblock.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <mtk_clkbuf_ctl.h>
+
+#include <connectivity_build_in_adapter.h>
+
+#include "osal.h"
+#include "conninfra.h"
+#include "conninfra_conf.h"
+#include "consys_hw.h"
+#include "consys_reg_mng.h"
+#include "consys_reg_util.h"
+#include "mt6885.h"
+#include "emi_mng.h"
+#include "mt6885_emi.h"
+#include "mt6885_consys_reg.h"
+#include "mt6885_consys_reg_offset.h"
+#include "mt6885_pos.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+#define CONSYS_PWR_SPM_CTRL 1
+#define PLATFORM_SOC_CHIP 0x6885
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+static int consys_clk_get_from_dts(struct platform_device *pdev);
+static int consys_clock_buffer_ctrl(unsigned int enable);
+static unsigned int consys_soc_chipid_get(void);
+static unsigned int consys_get_hw_ver(void);
+static void consys_clock_fail_dump(void);
+static int consys_thermal_query(void);
+static int consys_power_state(void);
+static int consys_bus_clock_ctrl(enum consys_drv_type, unsigned int, int);
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+struct consys_hw_ops_struct g_consys_hw_ops_mt6885 = {
+ /* load from dts */
+ /* TODO: mtcmos should move to a independent module */
+ .consys_plt_clk_get_from_dts = consys_clk_get_from_dts,
+
+ /* clock */
+ .consys_plt_clock_buffer_ctrl = consys_clock_buffer_ctrl,
+ .consys_plt_co_clock_type = consys_co_clock_type,
+
+ /* POS */
+ .consys_plt_conninfra_on_power_ctrl = consys_conninfra_on_power_ctrl,
+ .consys_plt_set_if_pinmux = consys_set_if_pinmux,
+
+ .consys_plt_polling_consys_chipid = consys_polling_chipid,
+ .consys_plt_d_die_cfg = connsys_d_die_cfg,
+ .consys_plt_spi_master_cfg = connsys_spi_master_cfg,
+ .consys_plt_a_die_cfg = connsys_a_die_cfg,
+ .consys_plt_afe_wbg_cal = connsys_afe_wbg_cal,
+ .consys_plt_subsys_pll_initial = connsys_subsys_pll_initial,
+ .consys_plt_low_power_setting = connsys_low_power_setting,
+ .consys_plt_soc_chipid_get = consys_soc_chipid_get,
+ .consys_plt_conninfra_wakeup = consys_conninfra_wakeup,
+ .consys_plt_conninfra_sleep = consys_conninfra_sleep,
+ .consys_plt_is_rc_mode_enable = consys_is_rc_mode_enable,
+
+ /* debug */
+ .consys_plt_clock_fail_dump = consys_clock_fail_dump,
+ .consys_plt_get_hw_ver = consys_get_hw_ver,
+ /* debug, used by STEP */
+ //.consys_plt_is_connsys_reg;
+
+ .consys_plt_sema_acquire_timeout = consys_sema_acquire_timeout,
+ .consys_plt_sema_release = consys_sema_release,
+ .consys_plt_spi_read = consys_spi_read,
+ .consys_plt_spi_write = consys_spi_write,
+ .consys_plt_adie_top_ck_en_on = consys_adie_top_ck_en_on,
+ .consys_plt_adie_top_ck_en_off = consys_adie_top_ck_en_off,
+ .consys_plt_spi_clock_switch = consys_spi_clock_switch,
+ .consys_plt_subsys_status_update = consys_subsys_status_update,
+
+ .consys_plt_thermal_query = consys_thermal_query,
+ .consys_plt_power_state = consys_power_state,
+ .consys_plt_config_setup = consys_config_setup,
+ .consys_plt_bus_clock_ctrl = consys_bus_clock_ctrl,
+};
+
+
+struct clk *clk_scp_conn_main; /*ctrl conn_power_on/off */
+struct consys_plat_thermal_data g_consys_plat_therm_data;
+
+/* For mt6885 */
+extern struct consys_hw_ops_struct g_consys_hw_ops_mt6885;
+extern struct consys_reg_mng_ops g_dev_consys_reg_ops_mt6885;
+extern struct consys_platform_emi_ops g_consys_platform_emi_ops_mt6885;
+extern struct consys_platform_pmic_ops g_consys_platform_pmic_ops_mt6885;
+
+const struct conninfra_plat_data mt6885_plat_data = {
+ .chip_id = PLATFORM_SOC_CHIP,
+ .hw_ops = &g_consys_hw_ops_mt6885,
+ .reg_ops = &g_dev_consys_reg_ops_mt6885,
+ .platform_emi_ops = &g_consys_platform_emi_ops_mt6885,
+ .platform_pmic_ops = &g_consys_platform_pmic_ops_mt6885,
+};
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#if 0
+struct consys_hw_ops_struct* get_consys_platform_ops(void)
+{
+ return &g_consys_hw_ops_mt6885;
+}
+#endif
+
+/* mtcmos contorl */
+int consys_clk_get_from_dts(struct platform_device *pdev)
+{
+ clk_scp_conn_main = devm_clk_get(&pdev->dev, "conn");
+ if (IS_ERR(clk_scp_conn_main)) {
+ pr_err("[CCF]cannot get clk_scp_conn_main clock.\n");
+ return PTR_ERR(clk_scp_conn_main);
+ }
+ pr_debug("[CCF]clk_scp_conn_main=%p\n", clk_scp_conn_main);
+
+ return 0;
+}
+
+int consys_platform_spm_conn_ctrl(unsigned int enable)
+{
+ int ret = 0;
+
+ if (enable) {
+ ret = clk_prepare_enable(clk_scp_conn_main);
+ if (ret) {
+ pr_err("Turn on oonn_infra power fail. Ret=%d\n", ret);
+ return -1;
+ }
+ } else {
+ clk_disable_unprepare(clk_scp_conn_main);
+
+ }
+
+ return ret;
+}
+
+int consys_clock_buffer_ctrl(unsigned int enable)
+{
+ /* This function call didn't work now.
+ * clock buffer is HW controlled, not SW controlled.
+ * Keep this function call to update status.
+ */
+ if (enable)
+ KERNEL_clk_buf_ctrl(CLK_BUF_CONN, true); /*open XO_WCN*/
+ else
+ KERNEL_clk_buf_ctrl(CLK_BUF_CONN, false); /*close XO_WCN*/
+ return 0;
+}
+
+int consys_co_clock_type(void)
+{
+ const struct conninfra_conf *conf;
+
+ /* Default solution */
+ conf = conninfra_conf_get_cfg();
+ if (NULL == conf) {
+ pr_err("[%s] Get conf fail", __func__);
+ return -1;
+ }
+ /* TODO: for co-clock mode, there are two case: 26M and 52M. Need something to distinguish it. */
+ if (conf->tcxo_gpio != 0)
+ return CONNSYS_CLOCK_SCHEMATIC_26M_EXTCXO;
+ else
+ return CONNSYS_CLOCK_SCHEMATIC_26M_COTMS;
+}
+
+unsigned int consys_soc_chipid_get(void)
+{
+ return PLATFORM_SOC_CHIP;
+}
+
+unsigned int consys_get_hw_ver(void)
+{
+ return CONN_HW_VER;
+}
+
+void consys_clock_fail_dump(void)
+{
+ pr_info("[%s]", __func__);
+}
+
+
+void update_thermal_data(struct consys_plat_thermal_data* input)
+{
+ memcpy(&g_consys_plat_therm_data, input, sizeof(struct consys_plat_thermal_data));
+ /* Special factor, not in POS */
+ /* THERMCR1 [16:17]*/
+ CONSYS_REG_WRITE(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERMCR1,
+ (CONSYS_REG_READ(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERMCR1) |
+ (0x3 << 16)));
+
+}
+
+int calculate_thermal_temperature(int y)
+{
+ struct consys_plat_thermal_data *data = &g_consys_plat_therm_data;
+ int t;
+ int const_offset = 25;
+
+ /*
+ * MT6635 E1 : read 0x02C = 0x66358A00
+ * MT6635 E2 : read 0x02C = 0x66358A10
+ * MT6635 E3 : read 0x02C = 0x66358A11
+ */
+ if (conn_hw_env.adie_hw_version == 0x66358A10 ||
+ conn_hw_env.adie_hw_version == 0x66358A11)
+ const_offset = 28;
+
+ /* temperature = (y-b)*slope + (offset) */
+ /* TODO: offset + 25 : this is only for E1, E2 is 28 */
+ t = (y - (data->thermal_b == 0 ? 0x36 : data->thermal_b)) *
+ ((data->slop_molecule + 209) / 100) + (data->offset + const_offset);
+
+ pr_info("y=[%d] b=[%d] constOffset=[%d] [%d] [%d] => t=[%d]\n",
+ y, data->thermal_b, const_offset, data->slop_molecule, data->offset,
+ t);
+
+ return t;
+}
+
+int consys_thermal_query(void)
+{
+#define THERMAL_DUMP_NUM 11
+#define LOG_TMP_BUF_SZ 256
+#define TEMP_SIZE 13
+ void __iomem *addr = NULL;
+ int cal_val, res = 0;
+ /* Base: 0x1800_2000, CONN_TOP_THERM_CTL */
+ const unsigned int thermal_dump_crs[THERMAL_DUMP_NUM] = {
+ 0x00, 0x04, 0x08, 0x0c,
+ 0x10, 0x14, 0x18, 0x1c,
+ 0x20, 0x24, 0x28,
+ };
+ char tmp[TEMP_SIZE] = {'\0'};
+ char tmp_buf[LOG_TMP_BUF_SZ] = {'\0'};
+ unsigned int i;
+ unsigned int efuse0, efuse1, efuse2, efuse3;
+
+ addr = ioremap_nocache(CONN_GPT2_CTRL_BASE, 0x100);
+ if (addr == NULL) {
+ pr_err("GPT2_CTRL_BASE remap fail");
+ return -1;
+ }
+
+ consys_adie_top_ck_en_on(CONNSYS_ADIE_CTL_HOST_CONNINFRA);
+
+ /* Hold Semaphore, TODO: may not need this, because
+ thermal cr seperate for different */
+ if (consys_sema_acquire_timeout(CONN_SEMA_THERMAL_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) {
+ pr_err("[THERM QRY] Require semaphore fail\n");
+ consys_adie_top_ck_en_off(CONNSYS_ADIE_CTL_HOST_CONNINFRA);
+ iounmap(addr);
+ return -1;
+ }
+
+ /* therm cal en */
+ CONSYS_REG_WRITE(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN,
+ (CONSYS_REG_READ(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN) |
+ (0x1 << 19)));
+ /* GPT2 En */
+ CONSYS_REG_WRITE(addr + CONN_GPT2_CTRL_THERMAL_EN,
+ (CONSYS_REG_READ(addr + CONN_GPT2_CTRL_THERMAL_EN) |
+ 0x1));
+
+ /* thermal trigger */
+ CONSYS_REG_WRITE(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN,
+ (CONSYS_REG_READ(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN) |
+ (0x1 << 18)));
+ udelay(500);
+ /* get thermal value */
+ cal_val = CONSYS_REG_READ(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN);
+ cal_val = (cal_val >> 8) & 0x7f;
+
+ /* thermal debug dump */
+ efuse0 = CONSYS_REG_READ(CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_0);
+ efuse1 = CONSYS_REG_READ(CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_1);
+ efuse2 = CONSYS_REG_READ(CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_2);
+ efuse3 = CONSYS_REG_READ(CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_3);
+ for (i = 0; i < THERMAL_DUMP_NUM; i++) {
+ snprintf(
+ tmp, TEMP_SIZE, "[0x%08x]",
+ CONSYS_REG_READ(CONN_TOP_THERM_CTL_ADDR + thermal_dump_crs[i]));
+ strncat(tmp_buf, tmp, strlen(tmp));
+ }
+ pr_info("[%s] efuse:[0x%08x][0x%08x][0x%08x][0x%08x] thermal dump: %s",
+ __func__, efuse0, efuse1, efuse2, efuse3, tmp_buf);
+
+ res = calculate_thermal_temperature(cal_val);
+
+ /* GPT2 disable, no effect on 6885 */
+ CONSYS_REG_WRITE(addr + CONN_GPT2_CTRL_THERMAL_EN,
+ (CONSYS_REG_READ(addr + CONN_GPT2_CTRL_THERMAL_EN) &
+ ~(0x1)));
+
+ /* disable */
+ CONSYS_REG_WRITE(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN,
+ (CONSYS_REG_READ(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_CAL_EN) &
+ ~(0x1 << 19)));
+
+ consys_sema_release(CONN_SEMA_THERMAL_INDEX);
+ consys_adie_top_ck_en_off(CONNSYS_ADIE_CTL_HOST_CONNINFRA);
+
+ iounmap(addr);
+
+ return res;
+}
+
+
+int consys_power_state(void)
+{
+ const char* osc_str[] = {
+ "fm ", "gps ", "bgf ", "wf ", "ap2conn ", "conn_thm ", "conn_pta ", "conn_infra_bus "
+ };
+ char buf[256] = {'\0'};
+ int r = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_2);
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ if ((r & (0x1 << (18 + i))) > 0)
+ strncat(buf, osc_str[i], strlen(osc_str[i]));
+ }
+ pr_info("[%s] [0x%x] %s", __func__, r, buf);
+ return 0;
+}
+
+int consys_bus_clock_ctrl(enum consys_drv_type drv_type, unsigned int bus_clock, int status)
+{
+ static unsigned int conninfra_bus_clock_wpll_state = 0;
+ static unsigned int conninfra_bus_clock_bpll_state = 0;
+ unsigned int wpll_state = conninfra_bus_clock_wpll_state;
+ unsigned int bpll_state = conninfra_bus_clock_bpll_state;
+ bool wpll_switch = false, bpll_switch = false;
+ int check;
+
+ if (status) {
+ /* Turn on */
+ /* Enable BPLL */
+ if (bus_clock & CONNINFRA_BUS_CLOCK_BPLL) {
+
+ if (conninfra_bus_clock_bpll_state == 0) {
+ CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 21));
+ udelay(30);
+ bpll_switch = true;
+ }
+ conninfra_bus_clock_bpll_state |= (0x1 << drv_type);
+ }
+ /* Enable WPLL */
+ if (bus_clock & CONNINFRA_BUS_CLOCK_WPLL) {
+ if (conninfra_bus_clock_wpll_state == 0) {
+ CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 20));
+ udelay(50);
+ wpll_switch = true;
+ }
+ conninfra_bus_clock_wpll_state |= (0x1 << drv_type);
+ }
+ pr_info("drv=[%d] conninfra_bus_clock_wpll=[%u]->[%u] %s conninfra_bus_clock_bpll=[%u]->[%u] %s",
+ drv_type,
+ wpll_state, conninfra_bus_clock_wpll_state, (wpll_switch ? "enable" : ""),
+ bpll_state, conninfra_bus_clock_bpll_state, (bpll_switch ? "enable" : ""));
+ } else {
+ /* Turn off */
+ /* Turn off WPLL */
+ if (bus_clock & CONNINFRA_BUS_CLOCK_WPLL) {
+ conninfra_bus_clock_wpll_state &= ~(0x1<<drv_type);
+ if (conninfra_bus_clock_wpll_state == 0) {
+ CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 20));
+ wpll_switch = true;
+ }
+ }
+ /* Turn off BPLL */
+ if (bus_clock & CONNINFRA_BUS_CLOCK_BPLL) {
+ conninfra_bus_clock_bpll_state &= ~(0x1<<drv_type);
+ if (conninfra_bus_clock_bpll_state == 0) {
+ CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 21));
+ bpll_switch = true;
+ }
+ }
+ pr_info("drv=[%d] conninfra_bus_clock_wpll=[%u]->[%u] %s conninfra_bus_clock_bpll=[%u]->[%u] %s",
+ drv_type,
+ wpll_state, conninfra_bus_clock_wpll_state, (wpll_switch ? "disable" : ""),
+ bpll_state, conninfra_bus_clock_bpll_state, (bpll_switch ? "disable" : ""));
+ if (consys_reg_mng_reg_readable() == 0) {
+ check = consys_reg_mng_is_bus_hang();
+ pr_info("[%s] not readable, bus hang check=[%d]", __func__, check);
+ }
+ }
+ return 0;
+}
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/mt6885_consys_reg.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/mt6885_consys_reg.c
new file mode 100755
index 0000000..13d83be
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/mt6885_consys_reg.c
@@ -0,0 +1,817 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#include <linux/memblock.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/random.h>
+
+#include <connectivity_build_in_adapter.h>
+
+#include "consys_reg_mng.h"
+#include "mt6885_consys_reg.h"
+#include "mt6885_consys_reg_offset.h"
+#include "consys_hw.h"
+#include "consys_reg_util.h"
+
+#define LOG_TMP_BUF_SZ 256
+#define CONSYS_POWER_MODE_LEGACY "Legacy"
+#define CONSYS_POWER_MODE_RC "RC"
+
+static int consys_reg_init(struct platform_device *pdev);
+static int consys_reg_deinit(void);
+static int consys_check_reg_readable(void);
+static int consys_is_consys_reg(unsigned int addr);
+static int consys_is_bus_hang(void);
+static int consys_dump_bus_status(void);
+static int consys_dump_conninfra_status(void);
+static int consys_dump_cpupcr(enum conn_dump_cpupcr_type, int times, unsigned long interval_us);
+static int consys_is_host_csr(unsigned long addr);
+
+static unsigned long consys_reg_validate_idx_n_offset(unsigned int idx, unsigned long offset);
+static int consys_find_can_write_reg(unsigned int *idx, unsigned long *offset);
+
+static unsigned long consys_reg_get_phy_addr_by_idx(unsigned int idx);
+static unsigned long consys_reg_get_virt_addr_by_idx(unsigned int idx);
+
+static int consys_reg_get_chip_id_idx_offset(unsigned int *idx, unsigned long *offset);
+static int consys_reg_get_reg_symbol_num(void);
+
+struct consys_reg_mng_ops g_dev_consys_reg_ops_mt6885 = {
+ .consys_reg_mng_init = consys_reg_init,
+ .consys_reg_mng_deinit = consys_reg_deinit,
+
+ .consys_reg_mng_check_reable = consys_check_reg_readable,
+ .consys_reg_mng_is_consys_reg = consys_is_consys_reg,
+ .consys_reg_mng_is_bus_hang = consys_is_bus_hang,
+ .consys_reg_mng_dump_bus_status = consys_dump_bus_status,
+ .consys_reg_mng_dump_conninfra_status = consys_dump_conninfra_status,
+ .consys_reg_mng_dump_cpupcr = consys_dump_cpupcr,
+ .consys_reg_mng_is_host_csr = consys_is_host_csr,
+
+ /* step */
+ .consys_reg_mng_validate_idx_n_offset = consys_reg_validate_idx_n_offset,
+ .consys_reg_mng_find_can_write_reg = consys_find_can_write_reg,
+
+ .consys_reg_mng_get_phy_addr_by_idx = consys_reg_get_phy_addr_by_idx,
+ .consys_reg_mng_get_virt_addr_by_idx = consys_reg_get_virt_addr_by_idx,
+ .consys_reg_mng_get_chip_id_idx_offset = consys_reg_get_chip_id_idx_offset,
+ .consys_reg_mng_get_reg_symbol_num = consys_reg_get_reg_symbol_num
+};
+
+
+const char* consys_base_addr_index_to_str[CONSYS_BASE_ADDR_MAX] = {
+ "CONN_INFRA_RGU_BASE",
+ "CONN_INFRA_CFG_BASE",
+ "CONN_HOST_CSR_TOP_BASE",
+ "INFRACFG_AO_BASE",
+ "TOPRGU_BASE",
+ "SPM_BASE",
+ "INFRACFG_BASE",
+ "CONN_WT_SLP_CTL_REG",
+ "CONN_AFE_CTL_REG",
+ "CONN_INFRA_SYSRAM",
+ "GPIO",
+ "CONN_RF_SPI_MST_REG",
+ "CONN_SEMAPHORE",
+ "CONN_TOP_THERM_CTL",
+ "IOCFG_RT",
+};
+
+struct consys_base_addr conn_reg;
+
+#if 0
+struct consys_reg_mng_ops* get_consys_reg_mng_ops(void)
+{
+ return &g_dev_consys_reg_ops_mt6885;
+}
+#endif
+
+struct consys_base_addr* get_conn_reg_base_addr()
+{
+ return &conn_reg;
+}
+
+static void consys_bus_hang_dump_c(void)
+{
+ unsigned long debug_addr, out_addr;
+ unsigned long value;
+ int i;
+ unsigned long debug_setting[] = {
+ 0xf0001, 0xe0001, 0xd0001, 0xc0001, 0xb0001, 0xa0001,
+ 0x90001, 0x80001, 0x70001, 0x60001, 0x50001, 0x40001,
+ 0x30001, 0x20001, 0x10001, 0x30002, 0x20002, 0x10002,
+ 0x40003, 0x30003, 0x20003, 0x10003
+ };
+
+ /* CONN2AP GALS RX status
+ * 0x1020_E804
+ *
+ * CONNINFRA sleep protect
+ * 0x1000_6158[2] ap2conn gals rx slp prot
+ * 0x1000_6150[13] ap2conn gals tx slp prot
+ *
+ * conninfra on2off off2on slp prot
+ * 0x1806_0184[5] conn_infra on2off slp prot
+ * 0x1806_0184[3] conn_infra off2on slp prot
+ */
+ pr_info("[CONN_BUS_C] [%x][%x][%x] [%x]",
+ CONSYS_REG_READ(CON_REG_INFRACFG_BASE_ADDR + INFRA_CONN2AP_GLAS_RC_ST),
+ CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_BUS_PROTECT2_RDY),
+ CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_BUS_PROTECT_RDY),
+ CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL)
+ );
+
+ debug_addr = CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_AO_DEBUGSYS;
+ out_addr = CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_DEBUG_CTRL_AO2SYS_OUT;
+
+ for (i = 0; i < ARRAY_SIZE(debug_setting); i++) {
+ CONSYS_REG_WRITE(debug_addr, debug_setting[i]);
+ value = CONSYS_REG_READ(out_addr);
+ pr_info("[CONN_BUS_C] addr=0x%x value=0x%08x", debug_setting[i], value);
+ }
+}
+
+static void consys_bus_hang_dump_a_rc(void)
+{
+ unsigned int i;
+ char tmp[LOG_TMP_BUF_SZ] = {'\0'};
+ char tmp_buf[LOG_TMP_BUF_SZ] = {'\0'};
+
+ for (i = 0xE50; i <= 0xE94; i += 4) {
+ snprintf(tmp, LOG_TMP_BUF_SZ, "[%x]",
+ CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + i));
+ strncat(tmp_buf, tmp, strlen(tmp));
+ }
+ pr_info("[rc_trace] %s", tmp_buf);
+
+ memset(tmp_buf, '\0', LOG_TMP_BUF_SZ);
+ for (i = 0xE98; i <= 0xED4; i += 4) {
+ snprintf(tmp, LOG_TMP_BUF_SZ, "[%x]",
+ CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + i));
+ strncat(tmp_buf, tmp, strlen(tmp));
+ }
+ pr_info("[rc_timer] %s", tmp_buf);
+}
+
+static void consys_bus_hang_dump_a(void)
+{
+ void __iomem *addr = NULL;
+ unsigned int r1, r2, r3, r4, r5, r6, r7 = 0, r8 = 0, r9 = 0, r10, r11;
+ char tmp_buf[LOG_TMP_BUF_SZ] = {'\0'};
+ char rc_buf[LOG_TMP_BUF_SZ] = {'\0'};
+
+ /*
+ * r1 : 0x1000_6110
+ * r2 : 0x1000_6114
+ */
+ snprintf(tmp_buf, LOG_TMP_BUF_SZ, "[%s] [0x%x][0x%x]",
+ (conn_hw_env.is_rc_mode ? CONSYS_POWER_MODE_RC : CONSYS_POWER_MODE_LEGACY),
+ CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PCM_REG13_DATA),
+ CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_SRC_REQ_STA_0));
+
+ /* RC REQ STA
+ * r3 : 0x1000_6E28
+ * r4 : 0x1000_6E2C
+ * r5 : 0x1000_6E30
+ * r6 : 0x1000_6E34
+ */
+ snprintf(rc_buf, LOG_TMP_BUF_SZ, "[%x][%x][%x][%x]",
+ CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_RC_RC_M04_REQ_STA_0),
+ CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_RC_RC_M05_REQ_STA_0),
+ CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_RC_RC_M06_REQ_STA_0),
+ CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_RC_RC_M07_REQ_STA_0));
+
+ /*
+ * 0x1000684C [28] DEBUG_IDX_VTCXO_STATE
+ * 0x1000684C [29] DEBUG_IDX_INFRA_STATE
+ * 0x1000684C [30] DEBUG_IDX_VRF18_STATE
+ * 0x1000684C [31] DEBUG_IDX_APSRC_STATE
+ * r7: 0x1000684C
+ */
+ r1 = CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PCM_WDT_LATCH_SPARE_0);
+
+ /*
+ * 0x10006100[0] sc_26m_ck_off 1'b0: 26M on; 1'b1
+ * 0x10006100[3] sc_axi_ck_off 1'b0: bus ck on; 1'b1 bus ck off
+ * 0x10006100[5] sc_md26m_ck_off 1'b0: MD 26M on; 1'b1 MD 26M off
+ * 0x10006100[20] sc_cksq0_off 1'b0: clock square0 on; 1'b1 clock square off
+ * r8:0x10006100
+ */
+ r2 = CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PCM_REG7_DATA);
+
+ /*
+ * 0x1000_6304[2] : pwr_on
+ * 0x1000_616c[1] : pwr_ack
+ * 0x1000_6304[3] : pwr_on_s
+ * 0x1000_6170[1] : pwr_ack_s
+ * 0x1000_6304[1] : iso_en
+ * 0x1000_6304[0] : ap_sw_rst
+ * r9 : 0x1000_616C
+ * r10 : 0x1000_6170
+ * r11 : 0x1000_6304
+ */
+ r3 = CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PWR_STATUS);
+ r4 = CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PWR_STATUS_2ND);
+ r5 = CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON);
+
+ /*
+ * sc_md_32k_ck_off
+ * r12 : 0x1000_644C
+ */
+ r6 = CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PLL_CON);
+
+ /*
+ * infra bus clock
+ * r13 : 0x1000_0000 pdn_conn_32k
+ * r14 : 0x1000_0010[2:0]
+ * 0: tck_26m_mx9_ck => 26M
+ * 1: mainpll_d4_d4 => 136.5M
+ * 2: mainpll_d7_d2 => 156M
+ * 3: mainpll_d4_d2 => 273M
+ * 4: mainpll_d5_d2 => 218.4M
+ * 5: mainpll_d6_d2 => 182M
+ * 6: osc_d4 => 65M
+ */
+ addr = ioremap_nocache(0x10000000, 0x20);
+ if (addr != NULL) {
+ r7 = CONSYS_REG_READ(addr);
+ r8 = CONSYS_REG_READ(addr + 0x10);
+ iounmap(addr);
+ }
+
+ /*
+ * r15 : 0x1000_0200 sc_md2_32k_off_en
+ */
+ addr = ioremap_nocache(0x10000200, 0x20);
+ if (addr != NULL) {
+ r9 = CONSYS_REG_READ(addr);
+ iounmap(addr);
+ }
+
+ /* ap2conn gals sleep protect status
+ * - 0x1000_1724 [2] / 0x1000_1228 [13] (infracfg_ao)(rx/tx) (sleep protect enable raedy)
+ * r16 : 0x1000_1724
+ * r17 : 0x1000_1228
+ */
+ r10 = CONSYS_REG_READ(CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET);
+ r11 = CONSYS_REG_READ(CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET);
+
+ pr_info("[CONN_BUS_A] %s %s [%x][%x][%x][%x][%x][%x] [%x][%x] [%x][%x][%x]", tmp_buf,
+ rc_buf, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11);
+
+ consys_bus_hang_dump_a_rc();
+}
+
+static void consys_bus_hang_dump_b(void)
+{
+ char tmp_buf[LOG_TMP_BUF_SZ] = {'\0'};
+ unsigned int r1, r2, r3, r4, r5, r6, r7;
+
+ /* Legacy Mode */
+ /*
+ * 0x180602c0
+ * [4]: conn_srcclkena_ack
+ * [5]: conn_ap_bus_ack
+ * [6]: conn_apsrc_ack
+ * [7]: conn_ddr_en_ack
+ * cr1 : 0x1806_02c0
+ */
+ snprintf(tmp_buf, LOG_TMP_BUF_SZ, "[%s] [%x]",
+ (conn_hw_env.is_rc_mode ? CONSYS_POWER_MODE_RC : CONSYS_POWER_MODE_LEGACY),
+ CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_0));
+
+ /* RC Mode */
+ /*
+ * debug sel 0x18001B00[2:0] 3'b010
+ * 0x1806_02C8
+ * [12] conn_srcclkena_0_bblpm_ack
+ * [13] conn_srcclkena_0_fpm_ack
+ * [28] conn_srcclkena_1_bblpm_ack
+ * [29] conn_srcclkena_1_fpm_ack
+ * cr2 : 0x1806_02c8
+ */
+ r1 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_2);
+
+ /*
+ * Consys status check
+ * debug sel 0x18001B00[2:0] 3'b011
+ * 0x1806_02C8
+ * [25] conninfra_bus_osc_en
+ * [24] conn_pta_osc_en
+ * [23] conn_thm_osc_en
+ * [22] ap2conn_osc_en
+ * [21] wfsys_osc_en
+ * [20] bgfsys_osc_en
+ * [19] gpssys_osc_en
+ * [18] fmsys_osc_en
+ */
+ /*CONSYS_REG_WRITE_MASK(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_DBG_MUX_SEL,
+ 0x2, 0x7);*/
+ /*r1 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_3);*/
+
+ /* Conninfra Off power state
+ * 0x1806_02CC
+ * [15] power_enable
+ * [14] power_on
+ * [13] pwer_ack
+ * [12] pwr_on_s
+ * [11] pwr_ack_s
+ * [10] iso_en
+ * [9] conn_infra_off_xreset_b
+ * [8] conn_infra_off_hreset_b
+ *
+ * cr3 : 0x1806_02CC
+ */
+ r2 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_3);
+
+
+ /* conn_infra_on clock 0x1020E504[0] = 1’b1
+ *
+ * cr4 : 0x1020_E504
+ */
+ r3 = CONSYS_REG_READ(CON_REG_INFRACFG_BASE_ADDR +
+ INFRA_AP2MD_GALS_CTL);
+
+ /* Check conn_infra off bus clock
+ * - write 0x1 to 0x1806_0000[0], reset clock detect
+ * - 0x1806_0000[2] conn_infra off bus clock (should be 1'b1 if clock exist)
+ * - 0x1806_0000[1] osc clock (should be 1'b1 if clock exist)
+ *
+ * cr5 : 0x1806_0000
+ */
+ CONSYS_SET_BIT(CON_REG_HOST_CSR_ADDR, 0x1);
+ udelay(200);
+ r4 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR);
+
+ /* conn_infra on2off sleep protect status
+ * - 0x1806_0184[5] (sleep protect enable raedy), should be 1'b0
+ * cr6 : 0x1806_0000
+ */
+ r5 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL);
+
+ /* CONN_HOST_CSR_DBG_DUMMY_4
+ * cr7 : 0x1806_02D0
+ */
+ r6 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_4);
+
+ /* 0x1806_02D4: dump bus timeout irq status
+ * cr8 : 0x1806_02D4
+ */
+ r7 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_BUS_TIMEOUT_IRQ);
+
+ pr_info("[CONN_BUS_B] infra_off %s [%x][%x] [%x][%x][%x] [%x] [%x]"
+ , tmp_buf, r1, r2, r3, r4, r5, r6, r7);
+ pr_info("[CONN_BUS_B] 0x1806_0294:[0x%08x] 0x1806_0220:[0x%08x]\n",
+ CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + 0x0294),
+ CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + 0x0220));
+}
+
+#if 0
+static void consys_bus_hang_dump_d(void)
+{
+ int r1;
+
+ /* check if consys off on
+ * 0x1806_02cc[8] 1'b1 ==> pwr on, 1'b0 ==> pwr off
+ */
+ r1 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_3);
+ if (((r1 >> 8) & 0x01) == 0) {
+ pr_info("[CONN_BUS_D] conninfra off is not on");
+ return;
+ }
+
+ /* PLL & OSC status
+ * 0x18001810[1] bpll_rdy
+ * 0x18001810[0] wpll_rdy
+ *
+ * OSC
+ * 0x1800_180C
+ * [3] : bus_bpll_sw_rdy, 1'b1 conninfra bus clock=166.4M
+ * [2] : bus_bpll_sw_rdy, 1'b1 conninfra bus clock=83.2M
+ * [1] : bus_bpll_sw_rdy, 1'b1 conninfra bus clock=32M
+ * [0] : bus_bpll_sw_rdy, 1'b1 conninfra bus clock=osc
+ *
+ * 0x1800_1160[22] ap2conn gals rx slp prot
+ * 0x1800_1630[3] conn2ap gals tx slp prot
+ * 0x1800_1634[3] conn2ap gals rx slp prot
+ *
+ * 0x1800_1628[3] conn_infra on2off slp pro
+ * 0x1800_162c[3] conn_infra off2on slp pro
+ *
+ * 0x1800_161C[3] gps2conn gals tx slp prot
+ * 0x1800_161C[7] gps2conn gals rx slp prot
+ * 0x1800_1618[7] conn2gps gals rx slp prot
+ * 0x1800_1618[3] conn2gps gals tx slp prot
+ *
+ * 0x1800_1614[3] bt2conn gals tx slp prot
+ * 0x1800_1614[7] bt2conn gals rx slp prot
+ * 0x1800_1610[3] conn2bt gals tx slp prot
+ * 0x1800_1610[7] conn2bt gals rx slp prot
+ *
+ * 0x1800_1620[3] wf2conn slp prot
+ */
+ pr_info("[CONN_BUS_D] [%x][%x] [%x][%x][%x] [%x][%x] [%x][%x] [%x][%x] [%x]",
+ CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_PLL_STATUS), /* PLL */
+ CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_OSC_STATUS), /* OSC */
+
+ CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_AP2CONN_GALS_DBG),
+ CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_CONN2AP_TX_SLP_CTRL),
+ CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_CONN2AP_RX_SLP_CTRL),
+
+ CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_ON_BUS_SLP_CTRL), /* on2off */
+ CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_OFF_BUS_SLP_CTRL),/* off2on */
+
+ CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_GPS2CONN_SLP_CTRL), /* gps2conn */
+ CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_CONN2GPS_SLP_CTRL), /* conn2gps */
+
+ CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_BT2CONN_SLP_CTRL), /* bt2conn */
+ CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_GALS_CONN2BT_SLP_CTRL), /* conn2bt */
+
+ CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_WF_SLP_CTRL) /* w2conn */
+ );
+}
+#endif
+
+static int consys_dump_bus_status(void)
+{
+ consys_bus_hang_dump_c();
+ return 0;
+}
+
+static int consys_dump_conninfra_status(void)
+{
+ consys_bus_hang_dump_a();
+ consys_bus_hang_dump_b();
+ return 0;
+}
+
+int consys_dump_cpupcr(enum conn_dump_cpupcr_type type, int times, unsigned long interval_us)
+{
+ int i;
+
+ for (i = 0; i < times; i++) {
+ pr_info("%s: wm pc=0x%x, wm lp=0x%x, bt pc=0x%x",
+ __func__,
+ CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_WM_MCU_PC_DBG),
+ CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_WM_MCU_GPR_DBG),
+ CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_BGF_MCU_PC_DBG));
+ if (interval_us > 1000)
+ usleep_range(interval_us - 100, interval_us + 100);
+ else
+ udelay(interval_us);
+ }
+
+ return 0;
+}
+
+static int consys_is_bus_hang(void)
+{
+ int r;
+
+ /* dump SPM register */
+ consys_bus_hang_dump_a();
+
+ /* STEP - 1 */
+ /*
+ * check kernel API lastbus_timeout_dump
+ * if return > 0 -> return 0x1
+ */
+
+ /* 1. Check ap2conn gals sleep protect status
+ * - 0x1000_1724 [2] / 0x1000_1228 [13] (infracfg_ao)(rx/tx) (sleep protect enable raedy)
+ * both of them should be 1'b0 (CR at ap side)
+ */
+ r = CONSYS_REG_READ_BIT(CON_REG_INFRACFG_AO_ADDR +
+ INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET, (0x1 << 2));
+ if (r != 0)
+ return CONNINFRA_AP2CONN_RX_SLP_PROT_ERR;
+
+
+ r = CONSYS_REG_READ_BIT(CON_REG_INFRACFG_AO_ADDR +
+ INFRA_TOPAXI_PROTECTEN_STA1_OFFSET, (0x1 << 13));
+ if (r != 0)
+ return CONNINFRA_AP2CONN_TX_SLP_PROT_ERR;
+
+ /* STEP - 2 */
+ consys_bus_hang_dump_b();
+
+ /* 2. Check conn_infra_on clock 0x1020E504[0] = 1’b1 */
+ r = CONSYS_REG_READ_BIT(CON_REG_INFRACFG_BASE_ADDR +
+ INFRA_AP2MD_GALS_CTL, 0x1);
+ if (r != 1)
+ return CONNINFRA_AP2CONN_CLK_ERR;
+
+#if 0
+ /* 3. Check conn_infra off bus clock
+ * - write 0x1 to 0x1806_0000[0], reset clock detect
+ * - 0x1806_0000[2] conn_infra off bus clock (should be 1'b1 if clock exist)
+ * - 0x1806_0000[1] osc clock (should be 1'b1 if clock exist)
+ */
+ CONSYS_SET_BIT(CON_REG_HOST_CSR_ADDR, 0x1);
+ udelay(500);
+ r = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR);
+ if ((r & TOP_BUS_MUC_STAT_HCLK_FR_CK_DETECT_BIT) == 0 ||
+ (r & TOP_BUS_MUC_STAT_OSC_CLK_DETECT_BIT) == 0)
+ ret |= CONNINFRA_INFRA_BUS_CLK_ERR;
+#endif
+
+ /* 4. Check conn_infra off domain bus hang irq status
+ * - 0x1806_02d4[0], should be 1'b1, or means conn_infra off bus might hang
+ */
+ r = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_BUS_TIMEOUT_IRQ);
+
+ if ((r & 0x1) != 0x1) {
+ pr_err("conninfra off bus might hang cirq=[0x%08x]", r);
+ consys_bus_hang_dump_c();
+ return CONNINFRA_INFRA_BUS_HANG_IRQ;
+ }
+ consys_bus_hang_dump_c();
+
+#if 0
+ /* 5. Check conn_infra on2off sleep protect status
+ * - 0x1806_0184[5] (sleep protect enable raedy), should be 1'b0
+ */
+ r = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL);
+ if (r & TOP_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_ACK_BIT)
+ ret |= CONNINFRA_ON2OFF_SLP_PROT_ERR;
+ if (ret) {
+ pr_info("[%s] ret=[%x]", __func__, ret);
+ consys_bus_hang_dump_c();
+ return ret;
+ }
+#endif
+ /*consys_bus_hang_dump_d();*/
+
+ return 0;
+
+}
+
+int consys_check_reg_readable(void)
+{
+ int r;
+ unsigned int rnd;
+ int delay_time = 1, spent = delay_time, max_wait = 16000; // 1.6 ms
+ int retry = max_wait / 10;
+
+ /* STEP - 1 */
+ /*
+ * check kernel API lastbus_timeout_dump
+ * if return > 0 -> return 0x1
+ */
+
+
+ /* 1. Check ap2conn gals sleep protect status
+ * - 0x1000_1724 [2] / 0x1000_1228 [13] (infracfg_ao)(rx/tx) (sleep protect enable raedy)
+ * both of them should be 1'b0 (CR at ap side)
+ */
+ r = CONSYS_REG_READ_BIT(CON_REG_INFRACFG_AO_ADDR +
+ INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET, (0x1 << 2));
+ if (r != 0)
+ return 0;
+
+ r = CONSYS_REG_READ_BIT(CON_REG_INFRACFG_AO_ADDR +
+ INFRA_TOPAXI_PROTECTEN_STA1_OFFSET, (0x1 << 13));
+ if (r != 0)
+ return 0;
+
+ /* STEP - 2 */
+
+ /* 2. Check conn_infra_on clock 0x1020E504[0] = 1’b1 */
+ r = CONSYS_REG_READ_BIT(CON_REG_INFRACFG_BASE_ADDR +
+ INFRA_AP2MD_GALS_CTL, 0x1);
+ if (r != 1)
+ return 0;
+
+ /* 3. Check conn_infra off bus clock
+ * - write 0x1 to 0x1806_0000[0], reset clock detect
+ * - 0x1806_0000[1] conn_infra off bus clock (should be 1'b1 if clock exist)
+ * - 0x1806_0000[2] osc clock (should be 1'b1 if clock exist)
+ */
+
+ while (retry > 0 && spent < max_wait) {
+ CONSYS_SET_BIT(CON_REG_HOST_CSR_ADDR, 0x1);
+ udelay(delay_time);
+ r = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR);
+ if ((r & TOP_BUS_MUC_STAT_HCLK_FR_CK_DETECT_BIT) == 0 ||
+ (r & TOP_BUS_MUC_STAT_OSC_CLK_DETECT_BIT) == 0) {
+ spent += delay_time;
+ retry--;
+ if (retry == 0)
+ pr_info("[%s] retry=0 r=[%x]", __func__, r);
+ else
+ delay_time = 10;
+ rnd = get_random_int() % 10;
+ spent += rnd;
+ udelay(rnd);
+ continue;
+ }
+ break;
+ }
+ if (retry == 0 || spent >= max_wait) {
+ pr_info("[%s] readable fail = bus clock retry=[%d] spent=[%d]", __func__,
+ retry, spent);
+ return 0;
+ }
+
+ /* 4. Check conn_infra off domain bus hang irq status
+ * - 0x1806_02d4[0], should be 1'b1, or means conn_infra off bus might hang
+ */
+ r = CONSYS_REG_READ_BIT(CON_REG_HOST_CSR_ADDR +
+ CONN_HOST_CSR_TOP_BUS_TIMEOUT_IRQ, 0x1);
+ if (r != 0x1)
+ return 0;
+
+ /* 5. Check conn_infra on2off sleep protect status
+ * - 0x1806_0184[5] (sleep protect enable raedy), should be 1'b0
+ */
+ r = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL);
+ if (r & TOP_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_ACK_BIT)
+ return 0;
+
+ return 1;
+}
+
+
+int consys_is_consys_reg(unsigned int addr)
+{
+ return 0;
+}
+
+
+static int consys_is_host_csr(unsigned long addr)
+{
+ struct consys_reg_base_addr *host_csr_addr =
+ &conn_reg.reg_base_addr[CONN_HOST_CSR_TOP_BASE_INDEX];
+
+ if (addr >= host_csr_addr->phy_addr &&
+ addr < host_csr_addr->phy_addr + host_csr_addr->size)
+ return 1;
+ return 0;
+}
+
+unsigned long consys_reg_validate_idx_n_offset(unsigned int idx, unsigned long offset)
+{
+ unsigned long res;
+
+ if (idx < 0 || idx >= CONSYS_BASE_ADDR_MAX) {
+ pr_warn("ConsysReg failed: No support the base %d\n", idx);
+ return 0;
+ }
+
+ res = conn_reg.reg_base_addr[idx].phy_addr;
+
+ if (res == 0) {
+ pr_warn("ConsysReg failed: No support the base idx is 0 index=[%d]\n", idx);
+ return 0;
+ }
+
+ if (offset >= conn_reg.reg_base_addr[idx].size) {
+ pr_warn("ConnReg failed: index(%d), offset(%d) over max size(%llu) %s\n",
+ idx, (int) offset, conn_reg.reg_base_addr[idx].size);
+ return 0;
+ }
+ return res;
+}
+
+int consys_find_can_write_reg(unsigned int *idx, unsigned long *offset)
+{
+ int i;
+ size_t addr = 0, addr_offset;
+ int max, mask = 0x0000000F;
+ int before, after, ret;
+
+ addr = conn_reg.reg_base_addr[CONN_INFRA_RGU_BASE_INDEX].vir_addr;
+ max = conn_reg.reg_base_addr[CONN_INFRA_RGU_BASE_INDEX].size;
+
+ pr_info("[%s] addr=[%p]\n", __func__, addr);
+
+ for (i = 0x0; i < max; i += 0x4) {
+ ret = 0;
+ addr_offset = addr + i;
+ before = CONSYS_REG_READ(addr_offset);
+ CONSYS_REG_WRITE_MASK(addr_offset, 0xFFFFFFFF, mask);
+ after = CONSYS_REG_READ(addr_offset);
+ if ((after & mask) != (0xFFFFFFFF & mask))
+ ret = -1;
+
+ CONSYS_REG_WRITE_MASK(addr_offset, 0x0, mask);
+ after = CONSYS_REG_READ(addr_offset);
+ if ((after & mask) != (0x0 & mask))
+ ret = -1;
+
+ CONSYS_REG_WRITE_MASK(addr_offset, before, mask);
+
+ pr_info("[%s] addr=[%p] [%d]\n", __func__, addr_offset, ret);
+ if (ret == 0) {
+ *idx = CONN_INFRA_RGU_BASE_INDEX;
+ *offset = i;
+ return 0;
+ }
+ }
+ return -1;
+
+}
+
+
+unsigned long consys_reg_get_phy_addr_by_idx(unsigned int idx)
+{
+ if (idx >= CONSYS_BASE_ADDR_MAX)
+ return 0;
+ return conn_reg.reg_base_addr[idx].phy_addr;
+}
+
+unsigned long consys_reg_get_virt_addr_by_idx(unsigned int idx)
+{
+ if (idx >= CONSYS_BASE_ADDR_MAX)
+ return 0;
+ return conn_reg.reg_base_addr[idx].vir_addr;
+}
+
+
+int consys_reg_get_chip_id_idx_offset(unsigned int *idx, unsigned long *offset)
+{
+ *idx = CONN_INFRA_CFG_BASE_INDEX;
+ *offset = CONN_CFG_ID_OFFSET;
+ return 0;
+}
+
+int consys_reg_get_reg_symbol_num(void)
+{
+ return CONSYS_BASE_ADDR_MAX;
+}
+
+
+int consys_reg_init(struct platform_device *pdev)
+{
+ int ret = -1;
+ struct device_node *node = NULL;
+ struct consys_reg_base_addr *base_addr = NULL;
+ struct resource res;
+ int flag, i = 0;
+
+ node = pdev->dev.of_node;
+ pr_info("[%s] node=[%p]\n", __func__, node);
+ if (node) {
+ for (i = 0; i < CONSYS_BASE_ADDR_MAX; i++) {
+ base_addr = &conn_reg.reg_base_addr[i];
+
+ ret = of_address_to_resource(node, i, &res);
+ if (ret) {
+ pr_err("Get Reg Index(%d-%s) failed",
+ i, consys_base_addr_index_to_str[i]);
+ continue;
+ }
+
+ base_addr->phy_addr = res.start;
+ base_addr->vir_addr =
+ (unsigned long) of_iomap(node, i);
+ of_get_address(node, i, &(base_addr->size), &flag);
+
+ pr_info("Get Index(%d-%s) phy(0x%zx) baseAddr=(0x%zx) size=(0x%zx)",
+ i, consys_base_addr_index_to_str[i], base_addr->phy_addr,
+ base_addr->vir_addr, base_addr->size);
+ }
+
+ } else {
+ pr_err("[%s] can't find CONSYS compatible node\n", __func__);
+ return ret;
+ }
+ return 0;
+
+}
+
+static int consys_reg_deinit(void)
+{
+ int i = 0;
+
+ for (i = 0; i < CONSYS_BASE_ADDR_MAX; i++) {
+ if (conn_reg.reg_base_addr[i].vir_addr) {
+ pr_info("[%d] Unmap %s (0x%zx)",
+ i, consys_base_addr_index_to_str[i],
+ conn_reg.reg_base_addr[i].vir_addr);
+ iounmap((void __iomem*)conn_reg.reg_base_addr[i].vir_addr);
+ conn_reg.reg_base_addr[i].vir_addr = 0;
+ }
+ }
+
+ return 0;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/mt6885_emi.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/mt6885_emi.c
new file mode 100755
index 0000000..ab5e9b2
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/mt6885_emi.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__
+
+#include <linux/memblock.h>
+#include <linux/platform_device.h>
+#ifdef CONFIG_MTK_EMI
+#include <mt_emi_api.h>
+#endif
+#include <linux/of_reserved_mem.h>
+
+#include <memory/mediatek/emi.h>
+#include "mt6885_emi.h"
+#include "mt6885.h"
+#include "mt6885_consys_reg.h"
+#include "consys_hw.h"
+#include "consys_reg_util.h"
+#include "mt6885_pos.h"
+
+/* For MCIF */
+#include <mtk_ccci_common.h>
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+#define REGION_CONN 27
+
+#define DOMAIN_AP 0
+#define DOMAIN_CONN 2
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+extern unsigned long long gConEmiSize;
+extern phys_addr_t gConEmiPhyBase;
+
+struct consys_platform_emi_ops g_consys_platform_emi_ops_mt6885 = {
+ .consys_ic_emi_mpu_set_region_protection = consys_emi_mpu_set_region_protection,
+ .consys_ic_emi_set_remapping_reg = consys_emi_set_remapping_reg,
+ .consys_ic_emi_get_md_shared_emi = consys_emi_get_md_shared_emi,
+ .consys_ic_emi_get_fw_emi_size = consys_emi_get_fw_emi_size,
+};
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#if 0
+struct consys_platform_emi_ops* get_consys_platform_emi_ops(void)
+{
+ return &g_consys_platform_emi_ops_mt6885;
+}
+#endif
+
+int consys_emi_mpu_set_region_protection(void)
+{
+ struct emimpu_region_t region;
+ unsigned long long start = gConEmiPhyBase;
+ unsigned long long end = gConEmiPhyBase + gConEmiSize - 1;
+
+ mtk_emimpu_init_region(®ion, REGION_CONN);
+ mtk_emimpu_set_addr(®ion, start, end);
+ mtk_emimpu_set_apc(®ion, DOMAIN_AP, MTK_EMIMPU_NO_PROTECTION);
+ mtk_emimpu_set_apc(®ion, DOMAIN_CONN, MTK_EMIMPU_NO_PROTECTION);
+ mtk_emimpu_set_protection(®ion);
+ mtk_emimpu_free_region(®ion);
+
+ pr_info("setting MPU for EMI share memory\n");
+ return 0;
+}
+
+void consys_emi_get_md_shared_emi(phys_addr_t* base, unsigned int* size)
+{
+#ifdef CONFIG_MTK_ECCCI_DRIVER
+ phys_addr_t mdPhy = 0;
+ int ret;
+
+ mdPhy = get_smem_phy_start_addr(MD_SYS1, SMEM_USER_RAW_MD_CONSYS, &ret);
+ if (ret) {
+ pr_info("MCIF base=0x%llx size=0x%x", mdPhy, ret);
+ if (base)
+ *base = mdPhy;
+ if (size)
+ *size = ret;
+ } else
+ pr_info("MCIF is not supported");
+#else
+ pr_info("[%s] ECCCI Driver is not supported.\n", __func__);
+ if (base)
+ *base = 0;
+ if (size)
+ *size = 0;
+
+#endif
+}
+
+unsigned int consys_emi_get_fw_emi_size(void)
+{
+ return 0x450000;
+}
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/mt6885_pmic.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/mt6885_pmic.c
new file mode 100755
index 0000000..56ba9e7
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/mt6885_pmic.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__
+
+#include <connectivity_build_in_adapter.h>
+#include <linux/memblock.h>
+#include <linux/platform_device.h>
+#include <linux/of_reserved_mem.h>
+#include <upmu_common.h>
+#include <linux/regulator/consumer.h>
+#include <linux/notifier.h>
+#include <pmic_api_buck.h>
+
+#include "consys_hw.h"
+#include "consys_reg_util.h"
+#include "osal.h"
+#include "mt6885_pmic.h"
+#include "mt6885_pos.h"
+#include "mt6885_consys_reg.h"
+#include "mt6885_consys_reg_offset.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+static int consys_plt_pmic_get_from_dts(struct platform_device *pdev, struct conninfra_dev_cb* dev_cb);
+
+static int consys_plt_pmic_common_power_ctrl(unsigned int enable);
+static int consys_plt_pmic_wifi_power_ctrl(unsigned int enable);
+static int consys_plt_pmic_bt_power_ctrl(unsigned int enable);
+static int consys_plt_pmic_gps_power_ctrl(unsigned int enable);
+static int consys_plt_pmic_fm_power_ctrl(unsigned int enable);
+/* VCN33_1 is enable when BT or Wi-Fi is on */
+static int consys_pmic_vcn33_1_power_ctl(bool enable, struct regulator* reg_VCN33_1);
+/* VCN33_2 is enable when Wi-Fi is on */
+static int consys_pmic_vcn33_2_power_ctl(bool enable);
+
+static int consys_plt_pmic_event_notifier(unsigned int id, unsigned int event);
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+struct consys_platform_pmic_ops g_consys_platform_pmic_ops_mt6885 = {
+ .consys_pmic_get_from_dts = consys_plt_pmic_get_from_dts,
+ /* vcn 18 */
+ .consys_pmic_common_power_ctrl = consys_plt_pmic_common_power_ctrl,
+ .consys_pmic_wifi_power_ctrl = consys_plt_pmic_wifi_power_ctrl,
+ .consys_pmic_bt_power_ctrl = consys_plt_pmic_bt_power_ctrl,
+ .consys_pmic_gps_power_ctrl = consys_plt_pmic_gps_power_ctrl,
+ .consys_pmic_fm_power_ctrl = consys_plt_pmic_fm_power_ctrl,
+ .consys_pmic_event_notifier = consys_plt_pmic_event_notifier,
+};
+
+struct regulator *reg_VCN13;
+struct regulator *reg_VCN18;
+struct regulator *reg_VCN33_1_BT;
+struct regulator *reg_VCN33_1_WIFI;
+struct regulator *reg_VCN33_2_WIFI;
+struct notifier_block vcn13_nb;
+
+static struct conninfra_dev_cb* g_dev_cb;
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+#if 0
+struct consys_platform_pmic_ops* get_consys_platform_pmic_ops(void)
+{
+ return &g_consys_platform_pmic_ops_mt6885;
+}
+#endif
+
+static int consys_vcn13_oc_notify(struct notifier_block *nb, unsigned long event,
+ void *unused)
+{
+ if (event != REGULATOR_EVENT_OVER_CURRENT)
+ return NOTIFY_OK;
+
+ if (g_dev_cb != NULL && g_dev_cb->conninfra_pmic_event_notifier != NULL)
+ g_dev_cb->conninfra_pmic_event_notifier(0, 0);
+ return NOTIFY_OK;
+}
+
+static int consys_plt_pmic_event_notifier(unsigned int id, unsigned int event)
+{
+#define ATOP_DUMP_NUM 10
+#define LOG_TMP_BUF_SZ 256
+ static int oc_counter = 0;
+ int ret;
+ unsigned int adie_value = 0;
+ unsigned int value1 = 0, value2 = 0, value3 = 0;
+ const unsigned int adie_cr_list[ATOP_DUMP_NUM] = {
+ 0xa10, 0x90, 0x94, 0xa0,
+ 0xa18, 0xa1c, 0xc8, 0x3c,
+ 0x0b4, 0x34c
+ };
+ int index;
+ char tmp[LOG_TMP_BUF_SZ] = {'\0'};
+ char tmp_buf[LOG_TMP_BUF_SZ] = {'\0'};
+
+ oc_counter++;
+ pr_info("[%s] VCN13 OC times: %d\n", __func__, oc_counter);
+
+ consys_hw_is_bus_hang();
+ ret = consys_hw_force_conninfra_wakeup();
+ if (ret) {
+ pr_err("[%s] force conninfra wakeup fail\n", __func__);
+ return NOTIFY_OK;
+ }
+
+ value1 = CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_ADIE_CTL);
+ value2 = CONSYS_REG_READ(CON_REG_WT_SPL_CTL_ADDR + 0xa8);
+ if (consys_sema_acquire_timeout(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_SUCCESS) {
+ value3 = CONSYS_REG_READ(CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL);
+ consys_sema_release(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX);
+ pr_info("[VCN13 OC] D-die: 0x1800_1900:0x%08x 0x1800_50A8:0x%08x 0x1805_2830:0x%08x\n", value1, value2, value3);
+ } else {
+ pr_info("[VCN13 OC] D-die: 0x1800_1900:0x%08x 0x1800_50A8:0x%08x\n", value1, value2);
+ }
+
+ for (index = 0; index < ATOP_DUMP_NUM; index++) {
+ consys_spi_read(SYS_SPI_TOP, adie_cr_list[index], &adie_value);
+ snprintf(tmp, LOG_TMP_BUF_SZ, " [0x%04x: 0x%08x]", adie_cr_list[index], adie_value);
+ strncat(tmp_buf, tmp, strlen(tmp));
+ }
+ pr_info("[VCN13 OC] ATOP:%s\n", tmp_buf);
+ consys_hw_force_conninfra_sleep();
+
+ return NOTIFY_OK;
+}
+
+int consys_plt_pmic_get_from_dts(struct platform_device *pdev, struct conninfra_dev_cb* dev_cb)
+{
+ int ret;
+
+ g_dev_cb = dev_cb;
+//#if CONSYS_PMIC_CTRL_ENABLE
+ reg_VCN13 = devm_regulator_get_optional(&pdev->dev, "vcn13");
+ if (!reg_VCN13)
+ pr_err("Regulator_get VCN_13 fail\n");
+ else {
+ vcn13_nb.notifier_call = consys_vcn13_oc_notify;
+ ret = devm_regulator_register_notifier(reg_VCN13, &vcn13_nb);
+ if (ret) {
+ pr_info("VCN13 regulator notifier request failed\n");
+ }
+ }
+ reg_VCN18 = regulator_get(&pdev->dev, "vcn18");
+ if (!reg_VCN18)
+ pr_err("Regulator_get VCN_18 fail\n");
+ reg_VCN33_1_BT = regulator_get(&pdev->dev, "vcn33_1_bt");
+ if (!reg_VCN33_1_BT)
+ pr_err("Regulator_get VCN33_1_BT fail\n");
+ reg_VCN33_1_WIFI = regulator_get(&pdev->dev, "vcn33_1_wifi");
+ if (!reg_VCN33_1_WIFI)
+ pr_err("Regulator_get VCN33_1_WIFI fail\n");
+ reg_VCN33_2_WIFI = regulator_get(&pdev->dev, "vcn33_2_wifi");
+ if (!reg_VCN33_2_WIFI)
+ pr_err("Regulator_get VCN33_WIFI fail\n");
+//#endif
+ return 0;
+}
+
+int consys_pmic_vcn33_1_power_ctl(bool enable, struct regulator *reg_VCN33_1)
+{
+ int ret;
+ if (enable) {
+ if (consys_is_rc_mode_enable()) {
+ /* PMRC_EN[6][5] HW_OP_EN = 1, HW_OP_CFG = 0 */
+ KERNEL_pmic_ldo_vcn33_1_lp(SRCLKEN6, 0, 1, HW_OFF);
+ KERNEL_pmic_ldo_vcn33_1_lp(SRCLKEN5, 0, 1, HW_OFF);
+ /* SW_LP =0 */
+ KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN33_1_LP, 0);
+ regulator_set_voltage(reg_VCN33_1, 3300000, 3300000);
+ /* SW_EN=0 */
+ /* For RC mode, we don't have to control VCN33_1 & VCN33_2 */
+ #if 0
+ /* regulator_disable(reg_VCN33_1); */
+ #endif
+ } else {
+ /* HW_OP_EN = 1, HW_OP_CFG = 0 */
+ KERNEL_pmic_ldo_vcn33_1_lp(SRCLKEN0, 1, 1, HW_OFF);
+ /* SW_LP =0 */
+ KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN33_1_LP, 0);
+ regulator_set_voltage(reg_VCN33_1, 3300000, 3300000);
+ /* SW_EN=1 */
+ ret = regulator_enable(reg_VCN33_1);
+ if (ret)
+ pr_err("Enable VCN33_1 fail. ret=%d\n", ret);
+ }
+ } else {
+ if (consys_is_rc_mode_enable()) {
+ /* Do nothing */
+ } else {
+ regulator_disable(reg_VCN33_1);
+ }
+ }
+ return 0;
+}
+
+int consys_pmic_vcn33_2_power_ctl(bool enable)
+{
+ int ret;
+
+ if (enable) {
+ if (consys_is_rc_mode_enable()) {
+ /* PMRC_EN[6] HW_OP_EN = 1, HW_OP_CFG = 0 */
+ KERNEL_pmic_ldo_vcn33_2_lp(SRCLKEN6, 0, 1, HW_OFF);
+ /* SW_LP =0 */
+ KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN33_2_LP, 0);
+ regulator_set_voltage(reg_VCN33_2_WIFI, 3300000, 3300000);
+ /* SW_EN=0 */
+ /* For RC mode, we don't have to control VCN33_1 & VCN33_2 */
+ #if 0
+ regulator_disable(reg_VCN33_2_WIFI);
+ #endif
+ } else {
+ /* HW_OP_EN = 1, HW_OP_CFG = 0 */
+ KERNEL_pmic_ldo_vcn33_2_lp(SRCLKEN0, 1, 1, HW_OFF);
+ /* SW_LP =0 */
+ KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN33_2_LP, 0);
+ regulator_set_voltage(reg_VCN33_2_WIFI, 3300000, 3300000);
+ /* SW_EN=1 */
+ ret = regulator_enable(reg_VCN33_2_WIFI);
+ if (ret)
+ pr_err("Enable VCN33_2 fail. ret=%d\n", ret);
+ }
+ } else {
+ if (consys_is_rc_mode_enable()) {
+ /* Do nothing */
+ } else {
+ regulator_disable(reg_VCN33_2_WIFI);
+ }
+ }
+ return 0;
+}
+
+int consys_plt_pmic_common_power_ctrl(unsigned int enable)
+{
+ int ret;
+
+ if (enable) {
+ if (consys_is_rc_mode_enable()) {
+ /* RC mode */
+ /* VCN18 */
+ /* PMRC_EN[7][6][5][4] HW_OP_EN = 1, HW_OP_CFG = 0 */
+ KERNEL_pmic_ldo_vcn18_lp(SRCLKEN7, 0, 1, HW_OFF);
+ KERNEL_pmic_ldo_vcn18_lp(SRCLKEN6, 0, 1, HW_OFF);
+ KERNEL_pmic_ldo_vcn18_lp(SRCLKEN5, 0, 1, HW_OFF);
+ KERNEL_pmic_ldo_vcn18_lp(SRCLKEN4, 0, 1, HW_OFF);
+ /* SW_LP =1 */
+ KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN18_LP, 1);
+ regulator_set_voltage(reg_VCN18, 1800000, 1800000);
+ ret = regulator_enable(reg_VCN18);
+ if (ret)
+ pr_err("Enable VCN18 fail. ret=%d\n", ret);
+
+ /* VCN13 */
+ /* PMRC_EN[7][6][5][4] HW_OP_EN = 1, HW_OP_CFG = 0 */
+ KERNEL_pmic_ldo_vcn13_lp(SRCLKEN7, 0, 1, HW_OFF);
+ KERNEL_pmic_ldo_vcn13_lp(SRCLKEN6, 0, 1, HW_OFF);
+ KERNEL_pmic_ldo_vcn13_lp(SRCLKEN5, 0, 1, HW_OFF);
+ KERNEL_pmic_ldo_vcn13_lp(SRCLKEN4, 0, 1, HW_OFF);
+ /* SW_LP =1 */
+ KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN13_LP, 1);
+ regulator_set_voltage(reg_VCN13, 1300000, 1300000);
+ ret = regulator_enable(reg_VCN13);
+ if (ret)
+ pr_err("Enable VCN13 fail. ret=%d\n", ret);
+ } else {
+ /* Legacy mode */
+ /* HW_OP_EN = 1, HW_OP_CFG = 1 */
+ KERNEL_pmic_ldo_vcn18_lp(SRCLKEN0, 1, 1, HW_LP);
+ /* SW_LP=0 */
+ KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN18_LP, 0);
+ regulator_set_voltage(reg_VCN18, 1800000, 1800000);
+ /* SW_EN=1 */
+ ret = regulator_enable(reg_VCN18);
+ if (ret)
+ pr_err("Enable VCN18 fail. ret=%d\n", ret);
+
+ /* HW_OP_EN = 1, HW_OP_CFG = 1 */
+ KERNEL_pmic_ldo_vcn13_lp(SRCLKEN0, 1, 1, HW_LP);
+ regulator_set_voltage(reg_VCN13, 1300000, 1300000);
+ /* SW_LP=0 */
+ KERNEL_pmic_set_register_value(PMIC_RG_LDO_VCN13_LP, 0);
+ /* SW_EN=1 */
+ ret = regulator_enable(reg_VCN13);
+ if (ret)
+ pr_err("Enable VCN13 fail. ret=%d\n", ret);
+ }
+ } else {
+ regulator_disable(reg_VCN13);
+ regulator_disable(reg_VCN18);
+ }
+ return 0;
+}
+
+int consys_plt_pmic_wifi_power_ctrl(unsigned int enable)
+{
+ int ret;
+
+ ret = consys_pmic_vcn33_1_power_ctl(enable, reg_VCN33_1_WIFI);
+ if (ret)
+ pr_err("%s VCN33_1 fail\n", (enable? "Enable" : "Disable"));
+ ret = consys_pmic_vcn33_2_power_ctl(enable);
+ if (ret)
+ pr_err("%s VCN33_2 fail\n", (enable? "Enable" : "Disable"));
+ return ret;
+}
+
+int consys_plt_pmic_bt_power_ctrl(unsigned int enable)
+{
+ if (enable) {
+ /* request VS2 to 1.4V by VS2 VOTER (use bit 4) */
+ KERNEL_pmic_set_register_value(PMIC_RG_BUCK_VS2_VOTER_EN_SET, 0x10);
+ /* Set VCN13 to 1.32V */
+ KERNEL_pmic_set_register_value(PMIC_RG_VCN13_VOCAL, 0x2);
+ } else {
+ /* restore VCN13 to 1.3V */
+ KERNEL_pmic_set_register_value(PMIC_RG_VCN13_VOCAL, 0);
+ /* clear bit 4 of VS2 VOTER then VS2 can restore to 1.35V */
+ KERNEL_pmic_set_register_value(PMIC_RG_BUCK_VS2_VOTER_EN_CLR, 0x10);
+ }
+ return consys_pmic_vcn33_1_power_ctl(enable, reg_VCN33_1_BT);
+}
+
+int consys_plt_pmic_gps_power_ctrl(unsigned int enable)
+{
+ return 0;
+}
+
+int consys_plt_pmic_fm_power_ctrl(unsigned int enable)
+{
+ return 0;
+}
+
+
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/mt6885_pos.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/mt6885_pos.c
new file mode 100755
index 0000000..267f0d2
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/mt6885/mt6885_pos.c
@@ -0,0 +1,2310 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include "consys_hw.h" /* for semaphore index */
+/* platform dependent */
+#include "plat_def.h"
+/* macro for read/write cr */
+#include "consys_reg_util.h"
+#include "consys_reg_mng.h"
+/* cr base address */
+#include "mt6885_consys_reg.h"
+/* cr offset */
+#include "mt6885_consys_reg_offset.h"
+/* For function declaration */
+#include "mt6885_pos.h"
+#include "mt6885.h"
+
+#include <linux/ratelimit.h>
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+#define CONN_INFRA_SYSRAM__A_DIE_DIG_TOP_CK_EN_MASK 0x7f
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+struct a_die_reg_config {
+ unsigned int reg;
+ unsigned int mask;
+ unsigned int config;
+};
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+const static char* gAdieCtrlType[CONNSYS_ADIE_CTL_MAX] =
+{
+ "CONNSYS_ADIE_CTL_HOST_BT",
+ "CONNSYS_ADIE_CTL_HOST_FM",
+ "CONNSYS_ADIE_CTL_HOST_GPS",
+ "CONNSYS_ADIE_CTL_HOST_WIFI",
+ "CONNSYS_ADIE_CTL_HOST_CONNINFRA",
+ "CONNSYS_ADIE_CTL_FW_BT",
+ "CONNSYS_ADIE_CTL_FW_WIFI",
+};
+
+const static char* g_spi_system_name[SYS_SPI_MAX] = {
+ "SYS_SPI_WF1",
+ "SYS_SPI_WF",
+ "SYS_SPI_BT",
+ "SYS_SPI_FM",
+ "SYS_SPI_GPS",
+ "SYS_SPI_TOP",
+ "SYS_SPI_WF2",
+ "SYS_SPI_WF3",
+};
+
+#define ADIE_CONFIG_NUM 2
+
+// E1 WF/GPS/FM on(default)
+const static struct a_die_reg_config adie_e1_default[ADIE_CONFIG_NUM] =
+{
+ {ATOP_RG_TOP_XTAL_01, 0xc180, 0xc180},
+ {ATOP_RG_TOP_XTAL_02, 0xf0ff0080, 0xd0550080},
+};
+
+const static struct a_die_reg_config adie_e1_bt_only[ADIE_CONFIG_NUM] =
+{
+ {ATOP_RG_TOP_XTAL_01, 0xc180, 0xc100},
+ {ATOP_RG_TOP_XTAL_02, 0xf0ff0080, 0xf0ff0000},
+};
+
+const static struct a_die_reg_config adie_e2_default[ADIE_CONFIG_NUM] =
+{
+ {ATOP_RG_TOP_XTAL_01, 0xc180, 0xc180},
+ {ATOP_RG_TOP_XTAL_02, 0xf0ff0080, 0x50550080},
+};
+
+const static struct a_die_reg_config adie_e2_bt_only[ADIE_CONFIG_NUM] =
+{
+ {ATOP_RG_TOP_XTAL_01, 0xc180, 0x100},
+ {ATOP_RG_TOP_XTAL_02, 0xf0ff0080, 0x70ff0000},
+};
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+static int consys_spi_read_nolock(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data);
+static int consys_spi_write_nolock(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data);
+static void consys_spi_write_offset_range_nolock(
+ enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int value,
+ unsigned int reg_offset, unsigned int value_offset, unsigned int size);
+static int connsys_a_die_thermal_cal(int efuse_valid, unsigned int efuse);
+
+unsigned int consys_emi_set_remapping_reg(
+ phys_addr_t con_emi_base_addr,
+ phys_addr_t md_shared_emi_base_addr)
+{
+ /* EMI Registers remapping */
+ CONSYS_REG_WRITE_OFFSET_RANGE(CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_MCU_EMI_BASE_ADDR_OFFSET,
+ con_emi_base_addr, 0, 16, 20);
+
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_WF_PERI_BASE_ADDR_OFFSET,
+ 0x01000, 0xFFFFF);
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_BT_PERI_BASE_ADDR_OFFSET,
+ 0x01000, 0xFFFFF);
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_GPS_PERI_BASE_ADDR_OFFSET,
+ 0x01000, 0xFFFFF);
+
+ if (md_shared_emi_base_addr) {
+ CONSYS_REG_WRITE_OFFSET_RANGE(
+ CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_MD_SHARE_EMI_BASE_ADDR_OFFSET,
+ md_shared_emi_base_addr, 0, 16, 20);
+ }
+ pr_info("connsys_emi_base=[0x%llx] mcif_emi_base=[0x%llx] remap cr: connsys=[0x%08x] mcif=[0x%08x]\n",
+ con_emi_base_addr, md_shared_emi_base_addr,
+ CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_MCU_EMI_BASE_ADDR_OFFSET),
+ CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN2AP_REMAP_MD_SHARE_EMI_BASE_ADDR_OFFSET));
+ return 0;
+}
+
+int consys_conninfra_on_power_ctrl(unsigned int enable)
+{
+ int check;
+ if (enable) {
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ /* Turn on SPM clock (apply this for SPM's CONNSYS power control related CR accessing)
+ * address: 0x1000_6000[0]
+ * 0x1000_6000[31:16]
+ * Data: [0]=1'b1
+ * [31:16]=16'h0b16 (key)
+ * Action: write
+ */
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_SPM_BASE_ADDR + SPM_POWERON_CONFIG_EN, 0x0b160001, 0xffff0001);
+#endif
+
+ /* Turn on ap2conn host_ck CG (ECO)
+ * Address: INFRA_AP2MD_GALS_CTL[0] (0x1020E504[0])
+ * Value: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(CON_REG_INFRACFG_BASE_ADDR + INFRA_AP2MD_GALS_CTL, 0x1);
+
+#if MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE
+ check = consys_platform_spm_conn_ctrl(enable);
+ if (check) {
+ pr_err("Turn on oonn_infra power fail.\n");
+ return -1;
+ }
+#else
+ pr_info("Turn on conn_infra power by POS steps\n");
+ /* Assert "conn_infra_on" primary part power on, set "connsys_on_domain_pwr_on"=1
+ * Address: 0x1000_6304[2]
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x4);
+
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ /* Check "conn_infra_on" primary part power status, check "connsys_on_domain_pwr_ack"=1
+ * (polling "10 times" and each polling interval is "0.5ms")
+ * Address: 0x1000_616C[1]
+ * Data: 1'b1
+ * Action: polling
+ */
+ check = 0;
+ CONSYS_REG_BIT_POLLING(CON_REG_SPM_BASE_ADDR + SPM_PWR_STATUS, 1, 1, 500, 10, check);
+ if (check != 0)
+ pr_err("Check conn_infra_on primary power fail. 0x1000_616C is 0x%08x. Expect [1] as 1.\n",
+ CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PWR_STATUS));
+#endif
+
+ /* Assert "conn_infra_on" secondary part power on, set "connsys_on_domain_pwr_on_s"=1
+ * Address: 0x1000_6304[3]
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x8);
+
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ /* Check "conn_infra_on" secondary part power status,
+ * check "connsys_on_domain_pwr_ack_s"=1
+ * (polling "10 times" and each polling interval is "0.5ms")
+ * Address: 0x1000_6170[1]
+ * Data: 1'b1
+ * Action: polling
+ */
+ check = 0;
+ CONSYS_REG_BIT_POLLING(CON_REG_SPM_BASE_ADDR + SPM_PWR_STATUS_2ND, 1, 1, 500, 10, check);
+ if (check != 0)
+ pr_err("Check conn_infra_on secondary power fail. 0x1000_6170 is 0x%08x. Expect [1] as 1.\n",
+ CONSYS_REG_READ(CON_REG_SPM_BASE_ADDR + SPM_PWR_STATUS_2ND));
+#endif
+
+ /* Turn on AP-to-CONNSYS bus clock, set "conn_clk_dis"=0
+ * (apply this for bus clock toggling)
+ * Address: 0x1000_6304[4]
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x10);
+
+ /* Wait 1 us */
+ udelay(1);
+
+ /* De-assert "conn_infra_on" isolation, set "connsys_iso_en"=0
+ * Address: 0x1000_6304[1]
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x2);
+
+ /* De-assert CONNSYS S/W reset (TOP RGU CR),
+ * set "ap_sw_rst_b"=1
+ * Address: WDT_SWSYSRST[9] (0x1000_7018[9])
+ * WDT_SWSYSRST[31:24] (0x1000_7018[31:24])
+ * Data: [9]=1'b0
+ * [31:24]=8'h88 (key)
+ * Action: Write
+ */
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_TOP_RGU_ADDR + TOP_RGU_WDT_SWSYSRST,0x88000000, 0xff000200);
+
+ /* De-assert CONNSYS S/W reset (SPM CR), set "ap_sw_rst_b"=1
+ * Address: CONN_PWR_CON[0] (0x1000_6304[0])
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x1);
+
+ /* Wait 0.5ms */
+ udelay(500);
+
+ /* Disable AXI bus sleep protect */
+ /* Turn off AXI RX bus sleep protect (AP2CONN AHB Bus protect)
+ * (apply this for INFRA AHB bus accessing when CONNSYS had been turned on)
+ * Address: 0x1000_1718[31:0] (INFRA_TOPAXI_PROTECTEN2_CLR)
+ * Data: 0x0000_0002
+ * Action: write
+ */
+ CONSYS_REG_WRITE(
+ CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN2_CLR_OFFSET,
+ 0x00000002);
+
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ /* Check AHB RX bus sleep protect turn off
+ * (polling "10 times" and each polling interval is "0.5ms")
+ * Address: 0x1000_1724[2] (INFRA_TOPAXI_PROTECTEN2_STA1[2])
+ * Data: 1'b0
+ * Action: polling
+ */
+ check = 0;
+ CONSYS_REG_BIT_POLLING(
+ CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET,
+ 2, 0, 10, 500, check);
+ if (check != 0)
+ pr_err("Polling AHB RX bus sleep protect turn off fail. status=0x%08x\n",
+ CONSYS_REG_READ(CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET));
+#endif
+
+ /* Turn off AXI Rx bus sleep protect (CONN2AP AXI Rx Bus protect)
+ * (disable sleep protection when CONNSYS had been turned on)
+ * Note : Should turn off AHB Rx sleep protection first.
+ */
+ CONSYS_REG_WRITE(
+ CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_CLR_OFFSET,
+ 0x00004000);
+#if 0 /* POS update 20190819: Skip check */
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ /* Check AXI Rx bus sleep protect turn off
+ * (polling "10 times" and each polling interval is "0.5ms")
+ * Address: 0x1000_1228[14] (INFRA_TOPAXI_PROTECTEN_STA1[14])
+ * Data: 1'b0
+ * Action: polling
+ */
+ CONSYS_REG_BIT_POLLING(
+ CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET,
+ 14, 0, 10, 50, check);
+ if (check != 0)
+ pr_err("Polling AXI bus sleep protect turn off fail. Status=0x%08x\n",
+ CONSYS_REG_READ(CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET));
+#endif
+#endif
+ /* Turn off AXI TX bus sleep protect (AP2CONN AXI Bus protect)
+ * (apply this for INFRA AXI bus accessing when CONNSYS had been turned on)
+ */
+ CONSYS_REG_WRITE(
+ CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_CLR_OFFSET,
+ 0x00002000);
+
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ /* Check AXI TX bus sleep protect turn off
+ * (polling "10 times" and each polling interval is "0.5ms")
+ * Address: 0x1000_1228[13] (INFRA_TOPAXI_PROTECTEN_STA1[13])
+ * Data: 1'b0
+ * Action: polling
+ */
+ CONSYS_REG_BIT_POLLING(
+ CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET,
+ 13, 0, 10, 500, check);
+ if (check != 0)
+ pr_err("polling AHB TX bus sleep protect turn off fail. Status=0x%08x\n",
+ CONSYS_REG_READ(CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET));
+#endif
+#endif /* MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE */
+ } else {
+
+ /* Enable AXI bus sleep protect */
+#if MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE
+ pr_info("Turn off conn_infra power by SPM API\n");
+ check = consys_platform_spm_conn_ctrl(enable);
+ if (check) {
+ pr_err("Turn off conn_infra power fail, ret=%d\n", check);
+ return -1;
+ }
+#else
+ /* Turn on AXI TX bus sleep protect (AP2CONN AXI Bus protect)
+ * (apply this for INFRA AXI bus protection to prevent bus hang when
+ * CONNSYS had been turned off)
+ * Address: 0x1000_12a0[31:0]
+ * Data: 0x0000_2000
+ * Action: write
+ */
+ CONSYS_REG_WRITE(
+ CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_SET_OFFSET,
+ 0x00002000);
+
+ /* check AHB TX bus sleep protect turn on (polling "10 times")
+ * Address: 0x1000_1228[13]
+ * Data: 1'b1
+ * Action: polling
+ */
+ CONSYS_REG_BIT_POLLING(
+ CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET,
+ 13, 1, 0, 500, check);
+ if (check)
+ pr_err("Polling AHB TX bus sleep protect turn on fail.\n");
+
+ /* Turn on AXI Rx bus sleep protect (CONN2AP AXI RX Bus protect)
+ * (apply this for INFRA AXI bus protection to prevent bus hang when
+ * CONNSYS had been turned off)
+ * Note:
+ * Should turn on AXI Rx sleep protection after
+ * AXI Tx sleep protection has been turn on.
+ * Address: 0x1000_12A0[31:0]
+ * Data: 0x0000_4000
+ * Action: write
+ */
+ CONSYS_REG_WRITE(
+ CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_SET_OFFSET,
+ 0x00004000);
+
+ /* check AXI Rx bus sleep protect turn on
+ * (polling "100 times", polling interval is 1ms)
+ * Address: 0x1000_1228[14]
+ * Data: 1'b1
+ * Action: polling
+ */
+ CONSYS_REG_BIT_POLLING(
+ CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN_STA1_OFFSET,
+ 14, 1, 10, 1000, check);
+ if (check)
+ pr_err("Polling AXI Rx bus sleep protect turn on fail.\n");
+
+ /* Turn on AXI RX bus sleep protect (AP2CONN AXI Bus protect)
+ * (apply this for INFRA AXI bus protection to prevent bus hang when
+ * CONNSYS had been turned off)
+ * Address: 0x1000_1714[31:0] (INFRA_TOPAXI_PROTECTEN2_SET)
+ * Data: 0x0000_0002
+ * Action: write
+ */
+ CONSYS_REG_WRITE(
+ CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN2_SET_OFFSET,
+ 0x00000002);
+ /* check AHB RX bus sleep protect turn on (polling "10 times")
+ * Address: 0x1000_1724[2] (INFRA_TOPAXI_PROTECTEN2_STA1[2])
+ * Value: 1'b1
+ * Action: polling
+ */
+ CONSYS_REG_BIT_POLLING(
+ CON_REG_INFRACFG_AO_ADDR + INFRA_TOPAXI_PROTECTEN2_STA1_OFFSET,
+ 2, 1, 10, 0, check);
+ if (check)
+ pr_err("Polling AHB RX bus sleep protect turn on fail.\n");
+
+ /* Assert "conn_infra_on" isolation, set "connsys_iso_en"=1
+ * Address: CONN_PWR_CON[1] (0x1000_6304[1])
+ * Value: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x2);
+
+ /* Assert CONNSYS S/W reset (SPM CR), set "ap_sw_rst_b"=0
+ * Address: CONN_PWR_CON[0] (0x1000_6304[0])
+ * Value: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x1);
+
+ /* Assert CONNSYS S/W reset(TOP RGU CR), set "ap_sw_rst_b"=0
+ * Address: WDT_SWSYSRST[9] (0x1000_7018[9])
+ * WDT_SWSYSRST[31:24] (0x1000_7018[31:24])
+ * Value: [9]=1'b1
+ * [31:24]=8'h88 (key)
+ * Action: write
+ * Note: this CR value for reset control is active high (0: not reset, 1: reset)
+ */
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_TOP_RGU_ADDR + TOP_RGU_WDT_SWSYSRST,
+ 0x88000200,
+ 0xff000200);
+
+ /* Turn off AP-to-CONNSYS bus clock, set "conn_clk_dis"=1
+ * (apply this for bus clock gating)
+ * Address: CONN_PWR_CON[4] (0x1000_6304[4])
+ * Value: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x10);
+
+ /* wait 1us (?) */
+ udelay(1);
+
+ /* De-assert "conn_infra_on" primary part power on,
+ * set "connsys_on_domain_pwr_on"=0
+ * Address: CONN_PWR_CON[2] (0x1000_6304[2])
+ * Value: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x4);
+
+ /* De-assert "conn_infra_on" secondary part power on,
+ * set "connsys_on_domain_pwr_on_s"=0
+ * Address: CONN_PWR_CON[3] (0x1000_6304[3])
+ * Value: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CON_REG_SPM_BASE_ADDR + SPM_CONN_PWR_CON, 0x8);
+#endif /* MTK_CONNINFRA_CLOCK_BUFFER_API_AVAILABLE */
+
+ /* Turn off ap2conn host_ck CG (ECO)
+ * Address: INFRA_AP2MD_GALS_CTL[0] (0x1020E504[0])
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CON_REG_INFRACFG_BASE_ADDR + INFRA_AP2MD_GALS_CTL, 0x1);
+ }
+ return 0;
+}
+
+int consys_conninfra_wakeup(void)
+{
+ int check, r1, r2;
+ unsigned int retry = 10;
+ unsigned int consys_hw_ver = 0;
+ int polling_fail_retry = 2;
+ unsigned long polling_fail_delay = 20000; /* 20ms */
+
+ /* Wake up conn_infra
+ * Address: CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP (0x180601a0)
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_REG_WRITE(
+ CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP,
+ 0x1);
+
+ /* Check ap2conn slpprot_rdy
+ * (polling "10 times" for specific project code and each polling interval is "1ms")
+ * Address: CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_ACK (0x1806_0184[5])
+ * Data: 1'b0
+ * Action: polling
+ */
+ while (polling_fail_retry > 0) {
+ check = 0;
+ CONSYS_REG_BIT_POLLING(
+ CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL, 5, 0, 10, 1000, check);
+
+ if (check) {
+ pr_err("[%s] Check ap2conn slpprot_rdy fail. value=0x%x WAKEUP_TOP=[0x%x]\n",
+ __func__,
+ CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL),
+ CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP));
+ }
+
+ if (consys_reg_mng_reg_readable() == 0) {
+ check = consys_reg_mng_is_bus_hang();
+ r1 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_3);
+ r2 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP);
+ pr_info("[%s] check=[%d] r1=[0x%x] r2=[0x%x]", __func__, check, r1, r2);
+ consys_reg_mng_dump_cpupcr(CONN_DUMP_CPUPCR_TYPE_ALL, 10, 200);
+ if (check > 0) {
+ return -1;
+ }
+ check = -1;
+ }
+
+ if (check == 0)
+ break;
+
+ /* delay 20 ms */
+ usleep_range(polling_fail_delay - 200, polling_fail_delay + 200);
+ polling_fail_retry--;
+ }
+
+ if (check != 0) {
+ pr_err("[%s] wakeup fail retry %d", __func__, polling_fail_retry);
+ return -1;
+ }
+
+ /* Check CONNSYS version ID
+ * (polling "10 times" for specific project code and each polling interval is "1ms")
+ * Address: CONN_HW_VER (0x1800_1000[31:0])
+ * Data: 32'h2001_0000
+ * Action: polling
+ */
+ check = 0;
+ while (retry-- > 0) {
+ consys_hw_ver = CONSYS_REG_READ(
+ CON_REG_INFRA_CFG_ADDR +
+ CONN_HW_VER_OFFSET);
+ if (consys_hw_ver == CONN_HW_VER) {
+ check = 0;
+ pr_info("[%s] Polling chip id success (0x%x)\n", __func__, consys_hw_ver);
+ break;
+ }
+ check = -1;
+ }
+ if (check != 0)
+ pr_err("[%s] Polling chip id fail (0x%x)\n", __func__, consys_hw_ver);
+
+ return check;
+}
+
+int consys_conninfra_sleep(void)
+{
+ /* Release conn_infra force on
+ * Address: CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP (0x180601a0)
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_REG_WRITE(
+ CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP,
+ 0x0);
+
+ return 0;
+}
+
+void consys_set_if_pinmux(unsigned int enable)
+{
+#ifndef CONFIG_FPGA_EARLY_PORTING
+ if (enable) {
+ /* Set pinmux for the interface between D-die and A-die
+ * (CONN_HRST_B / CONN_TOP_CLK / CONN_TOP_DATA / CONN_WB_PTA /
+ * CONN_BT_CLK / CONN_BT_DATA / CONN_WF_CTRL0 / CONN_WF_CTRL1 /
+ * CONN_WF_CTRL2 / CONN_WF_CTRL3 / CONN_WF_CTRL4)
+ */
+ /* GPIO 172: 0x1000_5450[18:16] */
+ /* GPIO 173: 0x1000_5450[22:20] */
+ /* GPIO 174: 0x1000_5450[26:24] */
+ /* GPIO 175: 0x1000_5450[30:28] */
+ CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE21, 0x11110000, 0xffff0000);
+
+ /* GPIO 176: 0x1000_5460[2:0] */
+ /* GPIO 177: 0x1000_5460[6:4] */
+ /* GPIO 178: 0x1000_5460[10:8] */
+ /* GPIO 179: 0x1000_5460[14:12] */
+ /* GPIO 180: 0x1000_5460[18:16] */
+ /* GPIO 181: 0x1000_5460[22:20] */
+ /* GPIO 182: 0x1000_5460[26:24] */
+ CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE22, 0x01111111, 0x0fffffff);
+
+ /* Set pinmux driving to 2mA
+ * Address:
+ * 0x11EA_0000[5:3]/0x11EA_0000[8:6]/0x11EA_0000[11:9]
+ * 0x11EA_0000[14:12]/0x11EA_0000[17:15]
+ * Data: 3'b000
+ * Action: write
+ * Note: IOCFG_RT
+ */
+ CONSYS_REG_WRITE_MASK(IOCFG_RT_ADDR + IOCFG_RT_DRV_CFG0, 0x0, 0x3fff8);
+
+ /* Set CONN_TOP_CLK/CONN_TOP_DATA/CONN_BT_CLK/CONN_BT_DATA driving to 4mA
+ * (CONN_TOP_DATA driving config is the same position with
+ * CONN_WF_CTRL0/CONN_WF_CTRL1/CONN_WF_CTRL2/CONN_WF_CTRL3/CONN_WF_CTRL4)
+ * Address:
+ * CONN_TOP_CLK 0x11EA_0000[17:15] = 3b'001
+ * CONN_TOP_DATA 0x11EA_0000[5:3] = 3b'001
+ * CONN_BT_CLK 0x11EA_0000[8:6] = 3b'001
+ * CONN_BT_DATA 0x11EA_0000[11:9] = 3b'001
+ * Action: write
+ */
+ CONSYS_REG_WRITE_MASK(IOCFG_RT_ADDR + IOCFG_RT_DRV_CFG0, 0x8248, 0x38ff8);
+
+ /* Set pinmux PUPD setting
+ * Clear CONN_TOP_DATA/CONN_BT_DATA PD setting
+ * Address: 0x11EA_0058[14][11]
+ * Data: 2'b11
+ * Action: write
+ * Note: IOCFG_RT
+ */
+ CONSYS_REG_WRITE_MASK(IOCFG_RT_ADDR + IOCFG_RT_PD_CFG0_CLR, 0x4800, 0x4800);
+
+ /* Set pinmux PUPD
+ * Setting CONN_TOP_DATA/CONN_BT_DATA as PU
+ * Address: 0x11EA_0074[14][11]
+ * Data: 2'b11
+ * Action: write
+ * Note: IOCFG_RT
+ */
+ CONSYS_REG_WRITE_MASK(IOCFG_RT_ADDR + IOCFG_RT_PU_CFG0_SET, 0x4800, 0x4800);
+
+ /* If TCXO mode, set GPIO155 pinmux for TCXO mode (AUX4)
+ * (CONN_TCXOENA_REQ)
+ * Address: 0x1000_5430[14:12]
+ * Data: 3'b100
+ * Action: write
+ */
+ if (consys_co_clock_type() == CONNSYS_CLOCK_SCHEMATIC_26M_EXTCXO) {
+ /* TODO: need customization for TCXO GPIO */
+ CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE19, 0x4000, 0x7000);
+ }
+ } else {
+ /* Set pinmux for the interface between D-die and A-die (Aux0)
+ * Address:
+ * 0x1000_5450[26:24]/0x1000_5450[18:16]/0x1000_5450[22:20]
+ * 0x1000_5450[30:28]/0x1000_5460[2:0]/0x1000_5460[6:4]
+ * 0x1000_5460[10:8]/0x1000_5460[14:12]/0x1000_5460[18:16]
+ * 0x1000_5460[22:20]/0x1000_5460[26:24]
+ * Data: 3'b000
+ * Action: write
+ */
+ CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE21, 0x0, 0xffff0000);
+ CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE22, 0x0, 0x0fffffff);
+
+ /* Set pinmux PUPD setting
+ * Clear CONN_TOP_DATA/CONN_BT_DATA PU setting
+ * Address: 0x11EA_0078[14][11]
+ * Data: 2'b11
+ * Action: write
+ */
+ CONSYS_REG_WRITE_MASK(IOCFG_RT_ADDR + IOCFG_RT_PU_CFG0_CLR, 0x4800, 0x4800);
+
+ /* Set pinmux PUPD setting
+ * CONN_TOP_DATA/CONN_BT_DATA as PD
+ * Address: 0x11EA_0054[14][11]
+ * Data: 2'b11
+ *Action: write
+ */
+ CONSYS_REG_WRITE_MASK(IOCFG_RT_ADDR + IOCFG_RT_PD_CFG0_SET, 0x4800, 0x4800);
+
+ /* If TCXO mode, set GPIO155 pinmux to GPIO mode
+ * Address: 0x1000_5430[14:12]
+ * Data: 3'b000
+ * Action: write
+ */
+ if (consys_co_clock_type() == CONNSYS_CLOCK_SCHEMATIC_26M_EXTCXO) {
+ CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE19, 0x0, 0x7000);
+ }
+ }
+#else
+ pr_info("[%s] not for FPGA\n", __func__);
+#endif
+}
+
+int consys_polling_chipid(void)
+{
+ unsigned int retry = 11;
+ unsigned int consys_hw_ver = 0;
+ unsigned int consys_configuration_id = 0;
+ int ret = -1;
+
+ while (--retry > 0) {
+ consys_hw_ver = CONSYS_REG_READ(
+ CON_REG_INFRA_CFG_ADDR +
+ CONN_HW_VER_OFFSET);
+ if (consys_hw_ver == CONN_HW_VER) {
+ consys_configuration_id = CONSYS_REG_READ(
+ CON_REG_INFRA_CFG_ADDR + CONN_CFG_ID_OFFSET);
+ pr_info("Consys HW version id(0x%x) cfg_id=(0x%x)\n",
+ consys_hw_ver, consys_configuration_id);
+ ret = 0;
+ break;
+ }
+ msleep(20);
+ }
+
+ if (retry == 0) {
+ pr_err("Read CONSYS version id fail. Expect 0x%x but get 0x%x\n",
+ consys_hw_ver, CONN_HW_VER, consys_hw_ver);
+ return -1;
+ }
+
+ /* Disable conn_infra deadfeed function(workaround)
+ * Address: CONN_HOST_CSR_TOP_CSR_DEADFEED_EN_CR_AP2CONN_DEADFEED_EN (0x1806_0124[0])
+ * Data: 1'b0
+ * Action: write
+ * Note: workaround for deadfeed CDC issue
+ */
+ CONSYS_CLR_BIT(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CSR_DEADFEED_EN_CR, 0x1);
+
+#ifdef CONFIG_FPGA_EARLY_PORTING
+ /* For FPGA workaround */
+ CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + 0x0c04,
+ ((0x1 << 1) | (0x1 << 9) | (0x1 << 17) | (0x1 << 25)));
+ pr_info("Workaround for FPGA: Check %x\n", CON_REG_INFRA_CFG_ADDR + 0x0c04);
+#endif
+
+ return ret;
+}
+
+int connsys_d_die_cfg(void)
+{
+ /* Read D-die Efuse
+ * Address: AP2CONN_EFUSE_DATA (0x1800_1818)
+ * Data:
+ * Action: read
+ */
+ CONSYS_REG_WRITE(
+ CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_D_DIE_EFUSE,
+ CONSYS_REG_READ(CON_REG_INFRA_CFG_ADDR + AP2CONN_EFUSE_DATA));
+
+ /* conn_infra sysram hw control setting -> disable hw power down
+ * Address: CONN_INFRA_RGU_SYSRAM_HWCTL_PDN_SYSRAM_HWCTL_PDN (0x1800_0038)
+ * Data: 32'h0
+ * Action: write
+ */
+ CONSYS_REG_WRITE(CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_SYSRAM_HWCTL_PDN, 0x0);
+
+ /* conn_infra sysram hw control setting -> enable hw sleep
+ * Address: CONN_INFRA_RGU_SYSRAM_HWCTL_SLP_SYSRAM_HWCTL_SLP (0x1800_003C)
+ * Data: 32'h0000_00FF
+ * Action: write
+ */
+ CONSYS_REG_WRITE(CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_SYSRAM_HWCTL_SLP, 0x000000ff);
+
+ /* co-ext memory hw control setting -> disable hw power down
+ * Address: CONN_INFRA_RGU_CO_EXT_MEM_HWCTL_PDN_CO_EXT_MEM_HWCTL_PDN (0x1800_0050)
+ * Data: 32'h0
+ * Action: write
+ */
+ CONSYS_REG_WRITE(CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_CO_EXT_MEM_HWCTL_PDN, 0x0);
+
+ /* co-ext memory hw control setting -> enable hw sleep
+ * Address: CONN_INFRA_RGU_CO_EXT_MEM_HWCTL_SLP_CO_EXT_MEM_HWCTL_SLP (0x1800_0054)
+ * Data: 32'h0000_0001
+ * Action: write
+ */
+ CONSYS_REG_WRITE(CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_CO_EXT_MEM_HWCTL_SLP, 0x1);
+
+ return 0;
+}
+
+int connsys_spi_master_cfg(unsigned int next_status)
+{
+ unsigned int bt_only = 0;
+
+ if ((next_status & (~(0x1 << CONNDRV_TYPE_BT))) == 0)
+ bt_only = 1;
+
+ /* CONN_WT_SLP_CTL_REG_WB_WF_CK_ADDR_ADDR(0x070) = 0x0AF40A04
+ * CONN_WT_SLP_CTL_REG_WB_WF_WAKE_ADDR_ADDR(0x74) = 0x00A00090
+ * CONN_WT_SLP_CTL_REG_WB_WF_ZPS_ADDR_ADDR(0x78) = 0x009c008c
+ * CONN_WT_SLP_CTL_REG_WB_BT_CK_ADDR_ADDR(0x7c[11:0]) = 0xa08
+ * CONN_WT_SLP_CTL_REG_WB_BT_WAKE_ADDR_ADDR(0x80[11:0]) = 0x094
+ * CONN_WT_SLP_CTL_REG_WB_TOP_CK_ADDR_ADDR(0x84[11:0]) = 0xA2c
+ * CONN_WT_SLP_CTL_REG_WB_GPS_CK_ADDR_ADDR(0x88) = 0x0AFC0A0C
+ * CONN_WT_SLP_CTL_REG_WB_WF_B0_CMD_ADDR_ADDR(0x8c[11:0]) = 0x0F0
+ * CONN_WT_SLP_CTL_REG_WB_WF_B1_CMD_ADDR_ADDR(0x90[11:0]) = 0x0F4
+ * CONN_WT_SLP_CTL_REG_WB_GPS_RFBUF_ADDR(0x18005094[11:0]) = 0x0FC
+ * CONN_WT_SLP_CTL_REG_WB_GPS_L5_EN_ADDR(0x18005098[11:0]) = 0x0F8
+ */
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_WF_CK_ADDR, 0x0AF40A04);
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_WF_WAKE_ADDR, 0x00A00090);
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_WF_ZPS_ADDR, 0x009C008C);
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BT_CK_ADDR,
+ 0xa08, 0xfff);
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BT_WAKE_ADDR,
+ 0x094, 0xfff);
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_TOP_CK_ADDR,
+ 0xa2c, 0xfff);
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_GPS_CK_ADDR,
+ 0x0AFC0A0C);
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_WF_B0_CMD_ADDR,
+ 0x0f0, 0xfff);
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_WF_B1_CMD_ADDR,
+ 0x0f4, 0xfff);
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_GPS_RFBUF_ADDR,
+ 0x0FC, 0xfff);
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_GPS_L5_EN_ADDR,
+ 0x0F8, 0xfff);
+
+ /* CONN_WT_SLP_CTL_REG_WB_SLP_CTL_CMD_LENGTH(0x004[4:0]) = 0x8
+ * CONN_WT_SLP_CTL_REG_WB_BG_ADDR1_WB_BG_ADDR1(0x10[15:0]) = 0xA03C
+ * CONN_WT_SLP_CTL_REG_WB_BG_ADDR2_WB_BG_ADDR2(0x14[15:0]) = 0xA03C
+ * CONN_WT_SLP_CTL_REG_WB_BG_ADDR3_WB_BG_ADDR3(0x18[15:0]) = 0xAA18
+ * CONN_WT_SLP_CTL_REG_WB_BG_ADDR4_WB_BG_ADDR4(0x1c[15:0]) = 0xAA18
+ * CONN_WT_SLP_CTL_REG_WB_BG_ADDR5_WB_BG_ADDR5(0x20[15:0]) = 0xA0C8
+ * CONN_WT_SLP_CTL_REG_WB_BG_ADDR6_WB_BG_ADDR6(0x24[15:0]) = 0xAA00
+ * CONN_WT_SLP_CTL_REG_WB_BG_ADDR7_WB_BG_ADDR7(0x28[15:0]) = 0xA0B4
+ * CONN_WT_SLP_CTL_REG_WB_BG_ADDR8_WB_BG_ADDR8(0x2c[15:0]) = 0xA34C
+ * CONN_WT_SLP_CTL_REG_WB_BG_ON1_WB_BG_ON1(0x30) = 0x00000000
+ * CONN_WT_SLP_CTL_REG_WB_BG_ON2_WB_BG_ON2(0x34) = 0x00000000
+ * if (BT_only) {
+ * CONN_WT_SLP_CTL_REG_WB_BG_ON3_WB_BG_ON3(0x38) = 0x74E03F75
+ * CONN_WT_SLP_CTL_REG_WB_BG_ON4_WB_BG_ON4(0x3c) = 0x76E83F75
+ * } else {
+ * CONN_WT_SLP_CTL_REG_WB_BG_ON3_WB_BG_ON3(0x38) = 0x74E0FFF5
+ * CONN_WT_SLP_CTL_REG_WB_BG_ON4_WB_BG_ON4(0x3c) = 0x76E8FFF5
+ * }
+ * CONN_WT_SLP_CTL_REG_WB_BG_ON5_WB_BG_ON5(0x40) = 0x00000000
+ * CONN_WT_SLP_CTL_REG_WB_BG_ON6_WB_BG_ON6(0x44) = 0xFFFFFFFF
+ * CONN_WT_SLP_CTL_REG_WB_BG_ON7_WB_BG_ON7(0x48) = 0x00000019
+ * CONN_WT_SLP_CTL_REG_WB_BG_ON8_WB_BG_ON8(0x4c) = 0x00010400
+ * CONN_WT_SLP_CTL_REG_WB_BG_OFF1_WB_BG_OFF1(0x50) = 0x57400000
+ * CONN_WT_SLP_CTL_REG_WB_BG_OFF2_WB_BG_OFF2(0x54) = 0x57400000
+ * if (BT only) {
+ * CONN_WT_SLP_CTL_REG_WB_BG_OFF3_WB_BG_OFF3(0x58) = 0x44E03F75
+ * CONN_WT_SLP_CTL_REG_WB_BG_OFF4_WB_BG_OFF4(0x5c) = 0x44E03F75
+ * } else {
+ * CONN_WT_SLP_CTL_REG_WB_BG_OFF3_WB_BG_OFF3(0x58) = 0x44E0FFF5
+ * CONN_WT_SLP_CTL_REG_WB_BG_OFF4_WB_BG_OFF4(0x5c) = 0x44E0FFF5
+ * }
+ * CONN_WT_SLP_CTL_REG_WB_BG_OFF5_WB_BG_OFF5(0x60) = 0x00000001
+ * CONN_WT_SLP_CTL_REG_WB_BG_OFF6_WB_BG_OFF6(0x64) = 0x00000001
+ * CONN_WT_SLP_CTL_REG_WB_RG_OFF7_WB_BG_OFF7(0x68) = 0x00040019
+ * CONN_WT_SLP_CTL_REG_WB_RG_OFF8_WB_BG_OFF8(0x6c) = 0x00410440
+ */
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_SLP_CTL,
+ 0x8, 0x1f);
+
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR1,
+ 0xa03c, 0xffff);
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR2,
+ 0xa03c, 0xffff);
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR3,
+ 0xaa18, 0xffff);
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR4,
+ 0xaa18, 0xffff);
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR5,
+ 0xa0c8, 0xffff);
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR6,
+ 0xaa00, 0xffff);
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR7,
+ 0xa0b4, 0xffff);
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ADDR8,
+ 0xa34c, 0xffff);
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON1, 0x00000000);
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON2, 0x00000000);
+ if (bt_only) {
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON3, 0x74E03F75);
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON4, 0x76E83F75);
+ } else {
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON3, 0x74E0fff5);
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON4, 0x76E8FFF5);
+ }
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON5, 0x00000000);
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON6, 0xFFFFFFFF);
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON7, 0x00000019);
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_ON8, 0x00010400);
+
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF1, 0x57400000);
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF2, 0x57400000);
+ if (bt_only) {
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF3, 0x44E03F75);
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF4, 0x44E03F75);
+ } else {
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF3, 0x44e0fff5);
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF4, 0x44e0fff5);
+ }
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF5, 0x00000001);
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF6, 0x00000000);
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF7, 0x00040019);
+ CONSYS_REG_WRITE(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WT_SLP_CTL_REG_WB_BG_OFF8, 0x00410440);
+
+ return 0;
+}
+
+//#ifndef CONFIG_FPGA_EARLY_PORTING
+/*****************************************************************************
+* FUNCTION
+* connsys_a_die_efuse_read
+* DESCRIPTION
+* Read a-die efuse
+* PARAMETERS
+* efuse_addr: read address
+* RETURNS
+* int
+* 0: fail, efuse is invalid
+* 1: success, efuse is valid
+*****************************************************************************/
+static int connsys_a_die_efuse_read(unsigned int efuse_addr)
+{
+ int ret = 0;
+ int retry = 0;
+ unsigned int efuse0 = 0, efuse1 = 0, efuse2 = 0, efuse3 = 0;
+ int ret0, ret1, ret2, ret3;
+
+ /* Get semaphore before read */
+ if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) {
+ pr_err("[EFUSE READ] Require semaphore fail\n");
+ return 0;
+ }
+
+ /* Efuse control clear, clear Status /trigger
+ * Address: ATOP EFUSE_CTRL_write_efsrom_kick_and_read_kick_busy_flag (0x108[30])
+ * Data: 1'b0
+ * Action: TOPSPI_WR
+ */
+ consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret);
+ ret &= ~(0x1 << 30);
+ consys_spi_write_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, ret);
+
+ /* Efuse Read 1st 16byte
+ * Address:
+ * ATOP EFUSE_CTRL_efsrom_mode (0x108[7:6]) = 2'b00
+ * ATOP EFUSE_CTRL_efsrom_ain (0x108[25:16]) = efuse_addr (0)
+ * ATOP EFUSE_CTRL_write_efsrom_kick_and_read_kick_busy_flag (0x108[30]) = 1'b1
+ * Action: TOPSPI_WR
+ */
+ consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret);
+ ret &= ~(0x43ff00c0);
+ ret |= (0x1 << 30);
+ ret |= ((efuse_addr << 16) & 0x1ff0000);
+ consys_spi_write_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, ret);
+
+ /* Polling EFUSE busy = low
+ * (each polling interval is "30us" and polling timeout is 2ms)
+ * Address:
+ * ATOP EFUSE_CTRL_write_efsrom_kick_and_read_kick_busy_flag (0x108[30]) = 1'b0
+ * Action: TOPSPI_Polling
+ */
+ consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret);
+ while ((ret & (0x1 << 30)) != 0 && retry < 70) {
+ retry++;
+ udelay(30);
+ consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret);
+ }
+ if ((ret & (0x1 << 30)) != 0) {
+ pr_info("[%s] EFUSE busy, retry failed(%d)\n", __func__, retry);
+ }
+
+ /* Check efuse_valid & return
+ * Address: ATOP EFUSE_CTRL_csri_efsrom_dout_vld_sync_1_ (0x108[29])
+ * Action: TOPSPI_RD
+ */
+ /* if (efuse_valid == 1'b1)
+ * Read Efuse Data to global var
+ */
+ consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_CTRL, &ret);
+ if (((ret & (0x1 << 29)) >> 29) == 1) {
+ ret0 = consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_RDATA0, &efuse0);
+
+ CONSYS_REG_WRITE(
+ CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_0,
+ efuse0);
+
+ ret1 = consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_RDATA1, &efuse1);
+ CONSYS_REG_WRITE(
+ CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_1,
+ efuse1);
+ /* Sub-task: thermal cal */
+ connsys_a_die_thermal_cal(1, efuse1);
+
+ ret2 = consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_RDATA2, &efuse2);
+ CONSYS_REG_WRITE(
+ CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_2,
+ efuse2);
+
+ ret3 = consys_spi_read_nolock(SYS_SPI_TOP, ATOP_EFUSE_RDATA3, &efuse3);
+ CONSYS_REG_WRITE(
+ CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_EFUSE_DATA_3,
+ efuse3);
+
+ pr_info("efuse = [0x%08x, 0x%08x, 0x%08x, 0x%08x]", efuse0, efuse1, efuse2, efuse3);
+ if (ret0 || ret1 || ret2 || ret3)
+ pr_err("efuse read error: [%d, %d, %d, %d]", ret0, ret1, ret2, ret3);
+ ret = 1;
+ } else {
+ connsys_a_die_thermal_cal(0, 0);
+ pr_err("EFUSE is invalid\n");
+ ret = 0;
+ }
+
+ consys_sema_release(CONN_SEMA_RFSPI_INDEX);
+ return ret;
+}
+
+static int connsys_a_die_thermal_cal(int efuse_valid, unsigned int efuse)
+{
+ struct consys_plat_thermal_data input;
+ memset(&input, 0, sizeof(struct consys_plat_thermal_data));
+
+ if (efuse_valid) {
+ if (efuse & (0x1 << 7)) {
+ consys_spi_write_offset_range_nolock(
+ SYS_SPI_TOP, ATOP_RG_TOP_THADC_BG, efuse, 12, 3, 4);
+ consys_spi_write_offset_range_nolock(
+ SYS_SPI_TOP, ATOP_RG_TOP_THADC, efuse, 23, 0, 3);
+ }
+ if(efuse & (0x1 << 15)) {
+ consys_spi_write_offset_range_nolock(
+ SYS_SPI_TOP, ATOP_RG_TOP_THADC, efuse, 26, 13, 2);
+ input.slop_molecule = (efuse & 0x1f00) >> 8;
+ pr_info("slop_molecule=[%d]", input.slop_molecule);
+ }
+ if (efuse & (0x1 << 23)) {
+ /* [22:16] */
+ input.thermal_b = (efuse & 0x7f0000) >> 16;
+ pr_info("thermal_b =[%d]", input.thermal_b);
+ }
+ if (efuse & (0x1 << 31)) {
+ input.offset = (efuse & 0x7f000000) >> 24;
+ pr_info("offset=[%d]", input.offset);
+ }
+ }
+ update_thermal_data(&input);
+ return 0;
+}
+//#endif
+
+int connsys_a_die_cfg(void)
+{
+ int efuse_valid;
+ bool adie_26m = true;
+ unsigned int adie_id = 0;
+
+ if (consys_co_clock_type() == CONNSYS_CLOCK_SCHEMATIC_52M_COTMS) {
+ pr_info("A-die clock 52M\n");
+ adie_26m = false;
+ }
+ /* First time to setup conninfra sysram, clean it. */
+ memset_io(
+ (volatile void*)CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_OFFSET,
+ 0x0,
+ CONN_INFRA_SYSRAM_SW_CR_SIZE);
+
+
+ /* if(A-die XTAL = 26MHz ) {
+ * CONN_WF_CTRL2 swtich to GPIO mode, GPIO output value
+ * before patch download swtich back to CONN mode.
+ * }
+ */
+ /* Address:
+ * 0x1000_5054 = 32'h0010_0000
+ * 0x1000_5154 = 32'h0010_0000
+ * 0x1000_5460[18:16] = 3'b000
+ * Actin: write
+ * Note: MT6635 strap pinmux, set CONN_WF_CTRL2 as GPIO
+ */
+ if (adie_26m) {
+ CONSYS_REG_WRITE(GPIO_BASE_ADDR + GPIO_DIR5_SET, 0x00100000);
+ CONSYS_REG_WRITE(GPIO_BASE_ADDR + GPIO_DOUT5_SET, 0x00100000);
+ CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE22, 0x0, 0x70000);
+ }
+ /* sub-task: a-die cfg */
+ /* De-assert A-die reset
+ * Address: CONN_INFRA_CFG_ADIE_CTL_ADIE_RSTB (0x18001900[0])
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_ADIE_CTL, 0x1);
+
+ /* Read MT6635 ID
+ * Address: ATOP CHIP_ID
+ * 0x02C[31:16]: hw_code
+ * 0x02C[15:0]: hw_ver
+ * Data:
+ * MT6635 E1 : read 0x02C = 0x66358A00
+ * MT6635 E2 : read 0x02C = 0x66358A10
+ * MT6635 E3 : read 0x02C = 0x66358A11
+ * Action: TOPSPI_RD
+ */
+ consys_spi_read(SYS_SPI_TOP, ATOP_CHIP_ID, &adie_id);
+ conn_hw_env.adie_hw_version = adie_id;
+ conn_hw_env.is_rc_mode = consys_is_rc_mode_enable();
+ pr_info("A-die CHIP_ID=0x%08x rc=%d\n", adie_id, conn_hw_env.is_rc_mode);
+
+ CONSYS_REG_WRITE(
+ CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_CHIP_ID,
+ adie_id);
+
+ /* Patch to FW from 7761(WF0_WRI_SX_CAL_MAP/WF1_WRI_SX_CAL_MAP)
+ * Address: ATOP WRI_CTR2 (0x064)
+ * Data: 32'h00007700
+ * Action: TOPSPI_WR
+ */
+ consys_spi_write(SYS_SPI_TOP, ATOP_WRI_CTR2, 0x00007700);
+
+ /* Set WF low power cmd as DBDC mode & legacy interface
+ * Address: ATOP SMCTK11 (0x0BC)
+ * Data: 32'h00000021
+ * Action: TOPSPI_WR
+ */
+ consys_spi_write(SYS_SPI_TOP, ATOP_SMCTK11, 0x00000021);
+
+ /* Update spi fm read extra bit setting
+ * Address:
+ * CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_EN (0x1800400C[15])
+ * CONN_RF_SPI_MST_REG_FM_CTRL_FM_RD_EXT_CNT (0x1800400C[7:0])
+ * Data:
+ * 0x1800400C[15] = 1'b0
+ * 0x1800400C[7:0] = 8'h0
+ * Action: write
+ */
+ CONSYS_REG_WRITE_MASK(
+ CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_FM_CTRL, 0x0, 0x80ff);
+
+ /* Update Thermal addr for 6635
+ * Address: CONN_TOP_THERM_CTL_THERM_AADDR (0x18002018)
+ * Data: 32'h50305A00
+ * Action: write
+ */
+ CONSYS_REG_WRITE(CONN_TOP_THERM_CTL_ADDR + CONN_TOP_THERM_CTL_THERM_AADDR, 0x50305A00);
+
+ /* Sub-task: read a-die efuse */
+ efuse_valid = connsys_a_die_efuse_read(0);
+
+ /* Set WF_PAD to HighZ
+ * Address: ATOP RG_ENCAL_WBTAC_IF_SW (0x070)
+ * Data: 32'h80000000
+ * Action: TOPSPI_WR
+ */
+ consys_spi_write(SYS_SPI_TOP, ATOP_RG_ENCAL_WBTAC_IF_SW, 0x80000000);
+
+ /* Disable CAL LDO
+ * Address: ATOP RG_WF0_TOP_01 (0x380)
+ * Data: 32'h000E8002
+ * Action: TOPSPI_WR
+ * Note: AC mode
+ */
+ consys_spi_write(SYS_SPI_TOP, ATOP_RG_WF0_TOP_01, 0x000e8002);
+
+ /* Disable CAL LDO
+ * Address: ATOP RG_WF1_TOP_01 (0x390)
+ * Data: 32'h000E8002
+ * Action: TOPSPI_WR
+ * Note: AC mode
+ */
+ consys_spi_write(SYS_SPI_TOP, ATOP_RG_WF1_TOP_01, 0x000e8002);
+
+ /* Increase XOBUF supply-V
+ * Address: ATOP RG_TOP_XTAL_01 (0xA18)
+ * Data: 32'hF6E8FFF5
+ * Action: TOPSPI_WR
+ */
+ consys_spi_write(SYS_SPI_TOP, ATOP_RG_TOP_XTAL_01, 0xF6E8FFF5);
+
+ /* Increase XOBUF supply-R for MT6635 E1
+ * Address: ATOP RG_TOP_XTAL_02 (0xA1C)
+ * Data:
+ * if(MT6635 E1) //rf_hw_ver = 0x8a00
+ * 32'hD5555FFF
+ * else
+ * 32'h0x55555FFF
+ * Action: TOPSPI_WR
+ */
+ if (adie_id == 0x66358a00) {
+ consys_spi_write(SYS_SPI_TOP, ATOP_RG_TOP_XTAL_02, 0xD5555FFF);
+ } else {
+ consys_spi_write(SYS_SPI_TOP, ATOP_RG_TOP_XTAL_02, 0x55555FFF);
+ }
+
+ /* Initial IR value for WF0 THADC
+ * Address: ATOP RG_WF0_BG (0x384)
+ * Data: 0x00002008
+ * Action: TOPSPI_WR
+ */
+ consys_spi_write(SYS_SPI_TOP, ATOP_RG_WF0_BG, 0x2008);
+
+ /* Initial IR value for WF1 THADC
+ * Address: ATOP RG_WF1_BG (0x394)
+ * Data: 0x00002008
+ * Action: TOPSPI_WR
+ */
+ consys_spi_write(SYS_SPI_TOP, ATOP_RG_WF1_BG, 0x2008);
+
+ /* if(A-die XTAL = 26MHz ) {
+ * CONN_WF_CTRL2 swtich to CONN mode
+ * }
+ */
+ /* Adress: 0x1000_5460[18:16] = 3'b001
+ * Action: write
+ * Note: MT6635 strap pinmux, set CONN_WF_CTRL2 as conn mode
+ */
+ if (adie_26m) {
+ CONSYS_REG_WRITE_MASK(GPIO_BASE_ADDR + GPIO_MODE22, 0x10000, 0x70000);
+ }
+ return 0;
+}
+
+int connsys_afe_wbg_cal(void)
+{
+ /* Default value update; 1: AFE WBG CR (if needed)
+ * note that this CR must be backuped and restored by command batch engine
+ * Address:
+ * CONN_AFE_CTL_RG_WBG_AFE_01(0x18003010) = 32'h00000000
+ * CONN_AFE_CTL_RG_WBG_RCK_01(0x18003018) = 32'h144B0160
+ * CONN_AFE_CTL_RG_WBG_GL1_01(0x18003040) = 32'h10990C13
+ * CONN_AFE_CTL_RG_WBG_GL5_01(0x18003100) = 32'h10990C13
+ * CONN_AFE_CTL_RG_WBG_BT_TX_03 (0x18003058) = 32'hCD258051
+ * CONN_AFE_CTL_RG_WBG_WF0_TX_03 (0x18003078) = 32'hC5258251
+ * CONN_AFE_CTL_RG_WBG_WF1_TX_03 (0x18003094) = 32'hC5258251
+ */
+ CONSYS_REG_WRITE(
+ CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_AFE_01,
+ 0x0);
+ CONSYS_REG_WRITE(
+ CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_RCK_01,
+ 0x144B0160);
+ CONSYS_REG_WRITE(
+ CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_GL1_01,
+ 0x10990C13);
+ CONSYS_REG_WRITE(
+ CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_GL5_01,
+ 0x10990C13);
+ CONSYS_REG_WRITE(
+ CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_BT_TX_03,
+ 0xCD258051);
+ CONSYS_REG_WRITE(
+ CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_WF0_TX_03,
+ 0xC5258251);
+ CONSYS_REG_WRITE(
+ CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_WBG_WF1_TX_03,
+ 0xC5258251);
+
+ /* AFE WBG CAL SEQ1 (RC calibration) */
+ /* AFE WBG RC calibration, set "AFE RG_WBG_EN_RCK" = 1
+ * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_RCK (0x18003000[0])
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, 0x1);
+ udelay(60);
+ /* AFE WBG RC calibration */
+ /* AFE WBG RC calibration, set "AFE RG_WBG_EN_RCK" = 0
+ * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_RCK (0x18003000[0])
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, 0x1);
+
+ /* AFE WBG CAL SEQ2 (TX calibration) */
+ /* AFE WBG TX calibration, set "AFE RG_WBG_EN_BPLL_UP" = 1
+ * Address: CONN_AFE_CTL_RG_DIG_EN_03_RG_WBG_EN_BPLL_UP (0x18003008[21])
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 21));
+ udelay(30);
+ /* AFE WBG TX calibration, set "AFE RG_WBG_EN_WPLL_UP" = 1
+ * Address: CONN_AFE_CTL_RG_DIG_EN_03_RG_WBG_EN_WPLL_UP (0x18003008[20])
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 20));
+ udelay(60);
+ /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_BT" = 1
+ * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_BT (0x18003000[21])
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 21));
+ /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF0" = 1
+ * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF0 (0x18003000[20])
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 20));
+ /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF1" = 1
+ * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF1 (0x18003000[19])
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 19));
+ /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF2" = 1
+ * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF2 (0x18003000[18])
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 18));
+ /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF3" = 1
+ * Addres: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF3 (0x18003000[17])
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 17));
+ udelay(800);
+ /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_BT" = 0
+ * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_BT (0x18003000[21])
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 21));
+ /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF0" = 0
+ * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF0 (0x18003000[20])
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 20));
+ /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF1" = 0
+ * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF1 (0x18003000[19])
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 19));
+ /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF2" = 0
+ * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF2 (0x18003000[18])
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 18));
+ /* AFE WBG TX calibration, set "AFE RG_WBG_EN_TXCAL_WF3" = 0
+ * Address: CONN_AFE_CTL_RG_DIG_EN_01_RG_WBG_EN_TXCAL_WF3 (0x18003000[17])
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_01, (0x1 << 17));
+ /* AFE WBG TX calibration, set "AFE RG_WBG_EN_BPLL_UP" = 0
+ * Address: CONN_AFE_CTL_RG_DIG_EN_03_RG_WBG_EN_BPLL_UP (0x18003008[21])
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 21));
+ /* AFE WBG TX calibration, set "AFE RG_WBG_EN_WPLL_UP" = 0
+ * Address:i CONN_AFE_CTL_RG_DIG_EN_03_RG_WBG_EN_WPLL_UP (0x18003008[20])
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_03, (0x1 << 20));
+
+ /* Initial BT path if WF is in cal(need set this CR after WBG cal)
+ * Address: ATOP RG_ENCAL_WBTAC_IF_SW (0x070)
+ * Data: 32'h00000005
+ * Action: write
+ */
+ consys_spi_write(SYS_SPI_TOP, ATOP_RG_ENCAL_WBTAC_IF_SW, 0x5);
+ return 0;
+}
+
+int connsys_subsys_pll_initial(void)
+{
+ /* Check with DE, only 26M on mobile phone */
+
+ CONSYS_REG_WRITE_MASK(
+ CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_PLL_STB_TIME,
+ 0x314521, 0x7fff7fff);
+ CONSYS_REG_WRITE_MASK(
+ CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_02,
+ 0x4f, 0xcf);
+#if 0
+ switch (xtal_freq) {
+ case 0: /* SYS_XTAL_40000K */
+ CONSYS_REG_WRITE_MASK(
+ CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_PLL_STB_TIME,
+ 0x4bc7e4, 0x7fff7fff);
+ CONSYS_REG_WRITE_MASK(
+ CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_02,
+ 0x4e, 0xcf);
+ break;
+ case 1: /* SYS_XTAL_26000K */
+ CONSYS_REG_WRITE_MASK(
+ CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_PLL_STB_TIME,
+ 0x314521, 0x7fff7fff);
+ CONSYS_REG_WRITE_MASK(
+ CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_02,
+ 0x4f, 0xcf);
+ break;
+ case 2: /* SYS_XTAL_25000K */
+ CONSYS_REG_WRITE_MASK(
+ CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_PLL_STB_TIME,
+ 0x2f64ef, 0x7fff7fff);
+ CONSYS_REG_WRITE_MASK(
+ CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_02,
+ 0xcf, 0xcf);
+ break;
+ case 3: /* SYS_XTAL_24000K */
+ CONSYS_REG_WRITE_MASK(
+ CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_PLL_STB_TIME,
+ 0x2d74bc, 0x7fff7fff);
+ CONSYS_REG_WRITE_MASK(
+ CONN_AFE_CTL_BASE_ADDR + CONN_AFE_CTL_RG_DIG_EN_02,
+ 0x4e, 0xcf);
+ break;
+ }
+#endif
+ return 0;
+}
+
+// Special setting for BT low power
+static int connsys_bt_low_power_setting(bool bt_only)
+{
+ int hw_version;
+ const struct a_die_reg_config* config = NULL;
+ unsigned int ret, i;
+
+ hw_version = CONSYS_REG_READ(
+ CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_CHIP_ID);
+
+ if (bt_only) {
+ /* E1 */
+ if (hw_version == 0x66358A00) {
+ config = adie_e1_bt_only;
+ } else if (hw_version == 0x66358A10 || hw_version == 0x66358A11) {
+ config = adie_e2_bt_only;
+ } else
+ pr_err("[%s] wrong adie version (0x%08x)\n", __func__, hw_version);
+ } else {
+ if (hw_version == 0x66358A00) {
+ config = adie_e1_default;
+ } else if (hw_version == 0x66358A10 || hw_version == 0x66358A11) {
+ config = adie_e2_default;
+ } else
+ pr_err("[%s] wrong adie version (0x%08x)\n", __func__, hw_version);
+ }
+
+ if (config == NULL)
+ return -1;
+
+ consys_adie_top_ck_en_on(CONNSYS_ADIE_CTL_HOST_CONNINFRA);
+
+ /* Get semaphore before read */
+ if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) {
+ pr_err("[EFUSE READ] Require semaphore fail\n");
+ consys_adie_top_ck_en_off(CONNSYS_ADIE_CTL_HOST_CONNINFRA);
+ return -1;
+ }
+
+ for (i = 0; i < ADIE_CONFIG_NUM; i++) {
+ consys_spi_read_nolock(SYS_SPI_TOP, config[i].reg, &ret);
+ ret &= (~config[i].mask);
+ ret |= config[i].config;
+ consys_spi_write_nolock(SYS_SPI_TOP, config[i].reg, ret);
+ }
+
+ consys_sema_release(CONN_SEMA_RFSPI_INDEX);
+
+ consys_adie_top_ck_en_off(CONNSYS_ADIE_CTL_HOST_CONNINFRA);
+
+ return 0;
+}
+
+void connsys_debug_select_config(void)
+{
+#if 0
+ /* select conn_infra_cfg debug_sel to low pwoer related
+ * Address: 0x18001B00[2:0]
+ * Data: 3'b000
+ * Action: write
+ */
+ CONSYS_REG_WRITE_MASK(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_DBG_MUX_SEL,
+ 0x0, 0x7);
+#else
+ /* select conn_infra_cfg debug_sel to BPLL/WPLL status
+ * Address: 0x18001B00[2:0]
+ * Data: 3’b001
+ * Action: write
+ */
+ CONSYS_REG_WRITE_MASK(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_DBG_MUX_SEL,
+ 0x1, 0x7);
+ {
+ void __iomem *vir_addr = NULL;
+ vir_addr = ioremap_nocache(0x18006000, 0x1000);
+ if (vir_addr) {
+ /* wpll_rdy/bpll_rdy status dump
+ * 1.???Set 0x1800_604C = 0xFFFF_FFFF
+ * 2.???Set 0c1800_6058[1] = 0x1
+ * 3.???Set 0x1800_603C = 0x0000_0100
+ * 4.???Set 0x1800_601C = 0x0302_0100
+ * 5.???Set 0x1800_6020 = 0x0706_0504
+ * 6.???Set 0x1800_6024 = 0x0b0a_0908
+ * 7.???Set 0x1800_6028 = 0x0f0e_0d0c
+ * 8.???Set 0x1800_602C = 0x1312_1110
+ * 9.???Set 0x1800_6030 = 0x1716_1514
+ * 10.??Set 0x1800_6034 = 0x1b1a_1918
+ * 11.??Set 0x1800_6038 = 0x1f1e_1d1c
+ */
+ CONSYS_REG_WRITE(vir_addr + 0x004c, 0xffffffff);
+ CONSYS_SET_BIT(vir_addr + 0x0058, 0x1);
+ CONSYS_REG_WRITE(vir_addr + 0x3c, 0x00000100);
+ CONSYS_REG_WRITE(vir_addr + 0x1c, 0x03020100);
+ CONSYS_REG_WRITE(vir_addr + 0x20, 0x07060504);
+ CONSYS_REG_WRITE(vir_addr + 0x24, 0x0b0a0908);
+ CONSYS_REG_WRITE(vir_addr + 0x28, 0x0f0e0d0c);
+ CONSYS_REG_WRITE(vir_addr + 0x2c, 0x13121110);
+ CONSYS_REG_WRITE(vir_addr + 0x30, 0x17161514);
+ CONSYS_REG_WRITE(vir_addr + 0x34, 0x1b1a1918);
+ CONSYS_REG_WRITE(vir_addr + 0x38, 0x1f1e1d1c);
+ iounmap(vir_addr);
+ } else {
+ pr_err("remap 0x1800_6000 fail\n");
+ }
+ }
+#endif
+
+}
+
+
+int connsys_low_power_setting(unsigned int curr_status, unsigned int next_status)
+{
+ bool bt_only = false;
+
+ if ((next_status & (~(0x1 << CONNDRV_TYPE_BT))) == 0)
+ bt_only = true;
+
+ pr_info("[%s] current_status=%d bt_only = %d\n", __func__, curr_status, bt_only);
+
+ /* First subsys on */
+ if (curr_status == 0) {
+ /* Enable AP2CONN GALS Slave sleep protect en with conn_infra on2off/off2on & wfdma2conn
+ * sleep protect en
+ * Address: CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_WFDMA2CONN_SLP_PROT_AP2CONN_EN_ENABLE
+ * CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_CONN_INFRA_ON2OFF_SLP_PROT_AP2CONN_EN_ENABLE
+ * CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL_CONN_INFRA_OFF2ON_SLP_PROT_AP2CONN_EN_ENABLE (0x1806_0184[11:9])
+ * Data: 3'b111
+ * Action: write
+ */
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_SLP_PROT_CTRL,
+ 0xe00, 0xe00);
+
+ /* Unmask on2off/off2on slpprot_rdy enable checker @conn_infra off power off=> check slpprot_rdy = 1'b1 and go to sleep
+ * Address: CONN_INFRA_CFG_PWRCTRL0_CONN_INFRA_CFG_SLP_RDY_MASK (0x18001860[15:12])
+ * Data: 4'h0
+ * Action: write
+ */
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_PWRCTRL0,
+ 0x1000, 0xf000);
+
+ /* conn_infra low power setting */
+ if (!consys_is_rc_mode_enable()) {
+ /* Default mode (non-RC) */
+ /* Disable conn_top rc osc_ctrl_top
+ * Address: CONN_INFRA_CFG_RC_CTL_0_CONN_INFRA_OSC_RC_EN (0x18001834[7])
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0, (0x1 << 7));
+ /* Legacy OSC control stable time
+ * Address:
+ * CONN_INFRA_CFG_OSC_CTL_0_XO_VCORE_RDY_STABLE_TIME (0x18001800[7:0]) = 8'd6
+ * CONN_INFRA_CFG_OSC_CTL_0_XO_INI_STABLE_TIME (0x18001800[15:8]) = 8'd7
+ * CONN_INFRA_CFG_OSC_CTL_0_XO_BG_STABLE_TIME (0x18001800[23:16]) = 8'd8
+ * Action: write
+ */
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_OSC_CTL_0, 0x080706, 0xffffff);
+ /* Legacy OSC control unmask conn_srcclkena_ack
+ * Address: CONN_INFRA_CFG_OSC_CTL_1_ACK_FOR_XO_STATE_MASK (0x18001804[16])
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_OSC_CTL_1, (0x1 << 16));
+ } else {
+ /* RC mode */
+ /* GPS RC OSC control stable time
+ * Address:
+ * CONN_INFRA_CFG_RC_CTL_1_GPS_XO_VCORE_RDY_STABLE_TIME_0 (0x1800183C[7:0]) = 8'd6
+ * CONN_INFRA_CFG_RC_CTL_1_GPS_XO_INI_STABLE_TIME_0 (0x1800183C[15:8]) = 8'd7
+ * CONN_INFRA_CFG_RC_CTL_1_GPS_XO_BG_STABLE_TIME_0 (0x1800183C[23:16]) = 8'd8
+ * CONN_INFRA_CFG_RC_CTL_1_GPS_XO_VCORE_OFF_STABLE_TIME_0 (0x1800183C[31:24]) = 8'd2
+ * Action: write
+ */
+ CONSYS_REG_WRITE(
+ CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_1_GPS,
+ 0x02080706);
+
+ /* GPS RC OSC control unmask conn_srcclkena_ack
+ * Address: CONN_INFRA_CFG_RC_CTL_0_GPS_ACK_FOR_XO_STATE_MASK_0 (0x18001838[15])
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0_GPS, (0x1 << 15));
+
+ /* BT RC OSC control stable time
+ * Address:
+ * CONN_INFRA_CFG_RC_CTL_1_BT_XO_VCORE_RDY_STABLE_TIME_1 (0x18001844[7:0]) = 8'd6
+ * CONN_INFRA_CFG_RC_CTL_1_BT_XO_INI_STABLE_TIME_1 (0x18001844[15:8]) = 8'd7
+ * CONN_INFRA_CFG_RC_CTL_1_BT_XO_BG_STABLE_TIME_1 (0x18001844[23:16]) = 8'd8
+ * CONN_INFRA_CFG_RC_CTL_1_BT_XO_VCORE_OFF_STABLE_TIME_1 (0x18001844[31:24]) = 8'd2
+ * Action: write
+ */
+ CONSYS_REG_WRITE(
+ CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_1_BT,
+ 0x02080706);
+
+ /* BT RC OSC control unmask conn_srcclkena_ack
+ * Address: CONN_INFRA_CFG_RC_CTL_0_BT_ACK_FOR_XO_STATE_MASK_1 (0x18001840[15])
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0_BT, (0x1 << 15));
+
+ /* WF RC OSC control stable time
+ * Address:
+ * CONN_INFRA_CFG_RC_CTL_1_WF_XO_VCORE_RDY_STABLE_TIME_2 (0x1800184C[7:0]) = 8'd6
+ * CONN_INFRA_CFG_RC_CTL_1_WF_XO_INI_STABLE_TIME_2 (0x1800184C[15:8]) = 8'd7
+ * CONN_INFRA_CFG_RC_CTL_1_WF_XO_BG_STABLE_TIME_2 (0x1800184C[23:16]) = 8'd8
+ * CONN_INFRA_CFG_RC_CTL_1_WF_XO_VCORE_OFF_STABLE_TIME_2 (0x1800184C[31:24])= 8'd2
+ * Action: write
+ */
+ CONSYS_REG_WRITE(
+ CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_1_WF,
+ 0x02080706);
+
+ /* WF RC OSC control unmask conn_srcclkena_ack
+ * Address: CONN_INFRA_CFG_RC_CTL_0_WF_ACK_FOR_XO_STATE_MASK_2 (0x18001848[15])
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0_WF, (0x1 << 15));
+
+ /* TOP RC OSC control stable time
+ * Address:
+ * CONN_INFRA_CFG_RC_CTL_1_TOP_XO_VCORE_RDY_STABLE_TIME_3 (0x18001854[7:0]) = 8'd6
+ * CONN_INFRA_CFG_RC_CTL_1_TOP_XO_INI_STABLE_TIME_3 (0x18001854[15:8]) = 8'd7
+ * CONN_INFRA_CFG_RC_CTL_1_TOP_XO_BG_STABLE_TIME_3 (0x18001854[23:16]) = 8'd8
+ * CONN_INFRA_CFG_RC_CTL_1_TOP_XO_VCORE_OFF_STABLE_TIME_3 (0x18001854[31:24]) = 8'd2
+ * Action: write
+ */
+ CONSYS_REG_WRITE(
+ CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_1_TOP,
+ 0x02080706);
+
+ /* TOP RC OSC control unmask conn_srcclkena_ack
+ * Address: CONN_INFRA_CFG_RC_CTL_0_TOP_ACK_FOR_XO_STATE_MASK_3 (0x18001850[15])
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(
+ CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0_TOP,
+ (0x1 << 15));
+
+ /* Enable conn_top rc osc_ctrl_gps
+ * Address: CONN_INFRA_CFG_RC_CTL_0_GPSSYS_OSC_RC_EN (0x18001834[4])
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(
+ CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0,
+ (0x1 << 4));
+
+ /* Enable conn_top rc osc_ctrl_bt
+ * Address: CONN_INFRA_CFG_RC_CTL_0_BTSYS_OSC_RC_EN (0x18001834[5])
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(
+ CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0,
+ (0x1 << 5));
+
+ /* Enable conn_top rc osc_ctrl_wf
+ * Address: CONN_INFRA_CFG_RC_CTL_0_WFSYS_OSC_RC_EN (0x18001834[6])
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(
+ CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0,
+ (0x1 << 6));
+
+ /* set conn_srcclkena control by conn_infra_emi_ctl
+ * Address: CONN_INFRA_CFG_EMI_CTL_0_CONN_EMI_RC_EN (0x18001C00[0])
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(
+ CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_EMI_CTL_0, 0x1);
+
+ /* Disable legacy osc control
+ * Address: CONN_INFRA_CFG_RC_CTL_0_OSC_LEGACY_EN (0x18001834[0])
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(
+ CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_RC_CTL_0,
+ 0x1);
+ }
+ /* conn2ap sleep protect release bypass ddr_en_ack check
+ * Address: CONN_INFRA_CFG_EMI_CTL_0_EMI_SLPPROT_BP_DDR_EN (0x18001C00[18])
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_EMI_CTL_0, 0x40000);
+
+ /* Enable ddr_en timeout, timeout value = 1023 T (Bus clock)
+ * Address: CONN_INFRA_CFG_EMI_CTL_0_DDR_CNT_LIMIT (0x18001C00[14:4])
+ * Data: 11'd1023
+ * Action: write
+ */
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_EMI_CTL_0,
+ 0x3ff0, 0x7ff0);
+
+ /* A-die clock buffer setting for BT only and others mode */
+ connsys_bt_low_power_setting(bt_only);
+
+ /* Enable conn_infra_clkgen BPLL source (hw workaround)
+ * Address: CONN_INFRA_CFG_CKGEN_BUS_RFSPI_DIV_EN (0x1800_1A00[28])
+ * Data: 1'b1
+ * Action: write
+ */
+ CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_CKGEN_BUS, (0x1 << 28));
+
+ /* Bus light security
+ * Address:
+ * CONN_INFRA_CFG_LIGHT_SECURITY_CTRL_R_CONN_INFRA_BT_PAIR1_EN
+ * CONN_INFRA_CFG_LIGHT_SECURITY_CTRL_R_CONN_INFRA_BT_PAIR0_EN
+ * CONN_INFRA_CFG_LIGHT_SECURITY_CTRL_R_CONN_INFRA_WF_PAIR1_EN
+ * CONN_INFRA_CFG_LIGHT_SECURITY_CTRL_R_CONN_INFRA_WF_PAIR0_EN
+ * 0x1800_10F0[4][3][1][0] = 6'h1B
+ * Action: write
+ */
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_LIGHT_SECURITY_CTRL,
+ ((0x1 << 4) | (0x1 << 3) | (0x1 << 1) | 0x1),
+ ((0x1 << 4) | (0x1 << 3) | (0x1 << 1) | 0x1));
+
+ /* if(BT on or GPS on)
+ * Conn_infrapower on bgfsys on (woraround)
+ * Address:
+ * 0x18000008[31:16] = 16'h4254 (key)
+ * CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_CTL[7] (0x18000008[7]) = 1'b1
+ * Action: write
+ */
+ /* Check with DE, write 1 -> 1 is ok */
+ if ((next_status & ((0x1 << CONNDRV_TYPE_BT) | (0x1 << CONNDRV_TYPE_GPS))) != 0) {
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_CTL,
+ ((0x42540000) | (0x1 << 7)), 0xffff0080);
+ }
+
+ consys_config_setup();
+ connsys_debug_select_config();
+ /*
+ * set 0x1800_0090 = 4'h6
+ */
+ CONSYS_REG_WRITE(CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_DEBUG_SEL, 0x6);
+
+ /******************************************************/
+ /* power ctrl : 0x1800_1860[9] = 1'b1 */
+ /******************************************************/
+ CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_PWRCTRL0, 0x200);
+
+ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+ /* !!!!!!!!!!!!!!!!!!!!!! CANNOT add code after HERE!!!!!!!!!!!!!!!!!!!!!!!!!! */
+ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+ /* Disable conn_infra bus clock sw control ==> conn_infra bus clock hw control
+ * Address: CONN_INFRA_CFG_CKGEN_BUS_HCLK_CKSEL_SWCTL (0x1800_1A00[23])
+ * Data: 1'b0
+ * Action: write
+ */
+ CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_CKGEN_BUS, (0x1 << 23));
+
+ /* Conn_infra HW_CONTROL => conn_infra enter dsleep mode
+ * Address: CONN_INFRA_CFG_PWRCTRL0_HW_CONTROL (0x1800_1860[0])
+ * Data: 1'b1
+ * Action: write
+ * Note: enable conn_infra off domain as HW control
+ */
+ CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_PWRCTRL0, 0x1);
+ } else {
+ /* for subsys on/off, only update BT low power setting */
+ connsys_bt_low_power_setting(bt_only);
+
+ /* Workaround */
+ if ((next_status & ((0x1 << CONNDRV_TYPE_BT) | (0x1 << CONNDRV_TYPE_GPS))) != 0) {
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_CTL,
+ ((0x42540000) | (0x1 << 7)), 0xffff0080);
+ } else {
+ CONSYS_REG_WRITE_MASK(
+ CON_REG_INFRA_RGU_ADDR + CONN_INFRA_RGU_BGFSYS_ON_TOP_PWR_CTL,
+ 0x42540000, 0xffff0080);
+ }
+
+ consys_config_setup();
+ connsys_debug_select_config();
+ }
+ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+ /* !!!!!!!!!!!!!!!!!!!!!!!!CANNOT add code HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+ return 0;
+}
+
+static int consys_sema_acquire(enum conn_semaphore_type index)
+{
+ if (CONSYS_REG_READ_BIT(
+ CONN_REG_SEMAPHORE_ADDR + CONN_SEMAPHORE_M2_OWN_STA + index*4, 0x1) == 0x1) {
+ return CONN_SEMA_GET_SUCCESS;
+ } else {
+ return CONN_SEMA_GET_FAIL;
+ }
+}
+
+int consys_sema_acquire_timeout(enum conn_semaphore_type index, unsigned int usec)
+{
+ int i, check, r1, r2;
+
+ /* debug for bus hang */
+ if (consys_reg_mng_reg_readable() == 0) {
+ check = consys_reg_mng_is_bus_hang();
+ if (check > 0) {
+ r1 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_DBG_DUMMY_3);
+ r2 = CONSYS_REG_READ(CON_REG_HOST_CSR_ADDR + CONN_HOST_CSR_TOP_CONN_INFRA_WAKEPU_TOP_CONN_INFRA_WAKEPU_TOP);
+ pr_info("[%s] check=[%d] r1=[0x%x] r2=[0x%x]", __func__, check, r1, r2);
+ consys_reg_mng_dump_bus_status();
+ consys_reg_mng_dump_cpupcr(CONN_DUMP_CPUPCR_TYPE_ALL, 10, 200);
+ return CONN_SEMA_GET_FAIL;
+ }
+ }
+
+ for (i = 0; i < usec; i++) {
+ if (consys_sema_acquire(index) == CONN_SEMA_GET_SUCCESS) {
+ return CONN_SEMA_GET_SUCCESS;
+ }
+ udelay(1);
+ }
+
+ pr_err("Get semaphore 0x%x timeout, dump status:\n", index);
+ pr_err("M0:[0x%x] M1:[0x%x] M2:[0x%x] M3:[0x%x]\n",
+ CONSYS_REG_READ(CONN_REG_SEMAPHORE_ADDR + CONN_SEMA_OWN_BY_M0_STA_REP),
+ CONSYS_REG_READ(CONN_REG_SEMAPHORE_ADDR + CONN_SEMA_OWN_BY_M1_STA_REP),
+ CONSYS_REG_READ(CONN_REG_SEMAPHORE_ADDR + CONN_SEMA_OWN_BY_M2_STA_REP),
+ CONSYS_REG_READ(CONN_REG_SEMAPHORE_ADDR + CONN_SEMA_OWN_BY_M3_STA_REP));
+ consys_reg_mng_dump_cpupcr(CONN_DUMP_CPUPCR_TYPE_ALL, 10, 200);
+
+ return CONN_SEMA_GET_FAIL;
+}
+
+void consys_sema_release(enum conn_semaphore_type index)
+{
+ CONSYS_REG_WRITE(
+ (CONN_REG_SEMAPHORE_ADDR + CONN_SEMAPHORE_M2_OWN_REL + index*4), 0x1);
+}
+
+struct spi_op {
+ unsigned int busy_cr;
+ unsigned int polling_bit;
+ unsigned int addr_cr;
+ unsigned int read_addr_format;
+ unsigned int write_addr_format;
+ unsigned int write_data_cr;
+ unsigned int read_data_cr;
+ unsigned int read_data_mask;
+};
+
+static const struct spi_op spi_op_array[SYS_SPI_MAX] = {
+ /* SYS_SPI_WF1 */
+ {
+ CONN_RF_SPI_MST_REG_SPI_STA, 1,
+ CONN_RF_SPI_MST_REG_SPI_WF_ADDR, 0x00001000, 0x00000000,
+ CONN_RF_SPI_MST_REG_SPI_WF_WDAT,
+ CONN_RF_SPI_MST_REG_SPI_WF_RDAT, 0xffffffff
+ },
+ /* SYS_SPI_WF */
+ {
+ CONN_RF_SPI_MST_REG_SPI_STA, 1,
+ CONN_RF_SPI_MST_REG_SPI_WF_ADDR, 0x00003000, 0x00002000,
+ CONN_RF_SPI_MST_REG_SPI_WF_WDAT,
+ CONN_RF_SPI_MST_REG_SPI_WF_RDAT, 0xffffffff
+ },
+ /* SYS_SPI_BT */
+ {
+ CONN_RF_SPI_MST_REG_SPI_STA, 2,
+ CONN_RF_SPI_MST_REG_SPI_BT_ADDR, 0x00005000, 0x00004000,
+ CONN_RF_SPI_MST_REG_SPI_BT_WDAT,
+ CONN_RF_SPI_MST_REG_SPI_BT_RDAT, 0x000000ff
+ },
+ /* SYS_SPI_FM */
+ {
+ CONN_RF_SPI_MST_REG_SPI_STA, 3,
+ CONN_RF_SPI_MST_REG_SPI_FM_ADDR, 0x00007000, 0x00006000,
+ CONN_RF_SPI_MST_REG_SPI_FM_WDAT,
+ CONN_RF_SPI_MST_REG_SPI_FM_RDAT, 0x0000ffff
+ },
+ /* SYS_SPI_GPS */
+ {
+ CONN_RF_SPI_MST_REG_SPI_STA, 4,
+ CONN_RF_SPI_MST_REG_SPI_GPS_GPS_ADDR, 0x00009000, 0x00008000,
+ CONN_RF_SPI_MST_REG_SPI_GPS_GPS_WDAT,
+ CONN_RF_SPI_MST_REG_SPI_GPS_GPS_RDAT, 0x0000ffff
+ },
+ /* SYS_SPI_TOP */
+ {
+ CONN_RF_SPI_MST_REG_SPI_STA, 5,
+ CONN_RF_SPI_MST_REG_SPI_TOP_ADDR, 0x0000b000, 0x0000a000,
+ CONN_RF_SPI_MST_REG_SPI_TOP_WDAT,
+ CONN_RF_SPI_MST_REG_SPI_TOP_RDAT, 0xffffffff
+ },
+ /* SYS_SPI_WF2 */
+ {
+ CONN_RF_SPI_MST_REG_SPI_STA, 1,
+ CONN_RF_SPI_MST_REG_SPI_WF_ADDR, 0x0000d000, 0x0000c000,
+ CONN_RF_SPI_MST_REG_SPI_WF_WDAT,
+ CONN_RF_SPI_MST_REG_SPI_WF_RDAT, 0xffffffff
+ },
+ /* SYS_SPI_WF3 */
+ {
+ CONN_RF_SPI_MST_REG_SPI_STA, 1,
+ CONN_RF_SPI_MST_REG_SPI_WF_ADDR, 0x0000f000, 0x0000e000,
+ CONN_RF_SPI_MST_REG_SPI_WF_WDAT,
+ CONN_RF_SPI_MST_REG_SPI_WF_RDAT, 0xffffffff
+ },
+};
+
+static int consys_spi_read_nolock(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data)
+{
+ /* Read action:
+ * 1. Polling busy_cr[polling_bit] should be 0
+ * 2. Write addr_cr with data being {read_addr_format | addr[11:0]}
+ * 3. Trigger SPI by writing write_data_cr as 0
+ * 4. Polling busy_cr[polling_bit] as 0
+ * 5. Read data_cr[data_mask]
+ */
+ int check = 0;
+ const struct spi_op* op = &spi_op_array[subsystem];
+
+ if (!data) {
+ pr_err("[%s] invalid data ptr\n", __func__);
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+
+ CONSYS_REG_BIT_POLLING(
+ CONN_REG_RFSPI_ADDR + op->busy_cr,
+ op->polling_bit, 0, 100, 50, check);
+ if (check != 0) {
+ pr_err("[%s][%d][STEP1] polling 0x%08x bit %d fail. Value=0x%08x\n",
+ __func__, subsystem, CONN_REG_RFSPI_ADDR + op->busy_cr,
+ op->polling_bit,
+ CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + op->busy_cr));
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+
+ CONSYS_REG_WRITE(
+ CONN_REG_RFSPI_ADDR + op->addr_cr,
+ (op->read_addr_format | addr));
+
+ CONSYS_REG_WRITE(CONN_REG_RFSPI_ADDR + op->write_data_cr, 0);
+
+ check = 0;
+ CONSYS_REG_BIT_POLLING(
+ CONN_REG_RFSPI_ADDR + op->busy_cr,
+ op->polling_bit, 0, 100, 50, check);
+ if (check != 0) {
+ pr_err("[%s][%d][STEP4] polling 0x%08x bit %d fail. Value=0x%08x\n",
+ __func__, subsystem, CONN_REG_RFSPI_ADDR + op->busy_cr,
+ op->polling_bit,
+ CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + op->busy_cr));
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+
+ check = CONSYS_REG_READ_BIT(CONN_REG_RFSPI_ADDR + op->read_data_cr, op->read_data_mask);
+ *data = check;
+
+ return 0;
+}
+
+int consys_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data)
+{
+ int ret;
+
+ /* Get semaphore before read */
+ if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) {
+ pr_err("[SPI READ] Require semaphore fail\n");
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+
+ ret = consys_spi_read_nolock(subsystem, addr, data);
+
+ consys_sema_release(CONN_SEMA_RFSPI_INDEX);
+
+ return ret;
+}
+
+static int consys_spi_write_nolock(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data)
+{
+ int check = 0;
+ const struct spi_op* op = &spi_op_array[subsystem];
+
+ /* Write action:
+ * 1. Wait busy_cr[polling_bit] as 0
+ * 2. Write addr_cr with data being {write_addr_format | addr[11:0]
+ * 3. Write write_data_cr ad data
+ * 4. Wait busy_cr[polling_bit] as 0
+ */
+ CONSYS_REG_BIT_POLLING(
+ CONN_REG_RFSPI_ADDR + op->busy_cr,
+ op->polling_bit, 0, 100, 50, check);
+ if (check != 0) {
+ pr_err("[%s][%d][STEP1] polling 0x%08x bit %d fail. Value=0x%08x\n",
+ __func__, subsystem, CONN_REG_RFSPI_ADDR + op->busy_cr,
+ op->polling_bit,
+ CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + op->busy_cr));
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+
+ CONSYS_REG_WRITE(CONN_REG_RFSPI_ADDR + op->addr_cr, (op->write_addr_format | addr));
+
+ CONSYS_REG_WRITE(CONN_REG_RFSPI_ADDR + op->write_data_cr, data);
+
+ check = 0;
+ CONSYS_REG_BIT_POLLING(
+ CONN_REG_RFSPI_ADDR + op->busy_cr,
+ op->polling_bit, 0, 100, 50, check);
+ if (check != 0) {
+ pr_err("[%s][%d][STEP4] polling 0x%08x bit %d fail. Value=0x%08x\n",
+ __func__, subsystem, CONN_REG_RFSPI_ADDR + op->busy_cr,
+ op->polling_bit,
+ CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + op->busy_cr));
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+
+ return 0;
+}
+
+
+int consys_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data)
+{
+ int ret;
+
+ /* Get semaphore before read */
+ if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) {
+ pr_err("[SPI WRITE] Require semaphore fail\n");
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+
+ ret = consys_spi_write_nolock(subsystem, addr, data);
+
+ consys_sema_release(CONN_SEMA_RFSPI_INDEX);
+ return ret;
+}
+
+int consys_spi_write_offset_range(
+ enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int value,
+ unsigned int reg_offset, unsigned int value_offset, unsigned int size)
+{
+ if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) {
+ pr_err("[SPI READ] Require semaphore fail\n");
+ return CONNINFRA_SPI_OP_FAIL;
+ }
+ consys_spi_write_offset_range_nolock(
+ subsystem, addr, value, reg_offset, value_offset, size);
+
+ consys_sema_release(CONN_SEMA_RFSPI_INDEX);
+ return 0;
+}
+
+static void consys_spi_write_offset_range_nolock(
+ enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int value,
+ unsigned int reg_offset, unsigned int value_offset, unsigned int size)
+{
+ unsigned int data = 0, data2;
+ unsigned int reg_mask;
+ int ret;
+
+ pr_info("[%s][%s] addr=0x%04x value=0x%08x reg_offset=%d value_offset=%d size=%d",
+ __func__, g_spi_system_name[subsystem], addr, value, reg_offset, value_offset, size);
+ value = (value >> value_offset);
+ value = GET_BIT_RANGE(value, size, 0);
+ value = (value << reg_offset);
+ ret = consys_spi_read_nolock(subsystem, addr, &data);
+ if (ret) {
+ pr_err("[%s][%s] Get 0x%08x error, ret=%d",
+ __func__, g_spi_system_name[subsystem], addr, ret);
+ return;
+ }
+ reg_mask = GENMASK(reg_offset + size - 1, reg_offset);
+ data2 = data & (~reg_mask);
+ data2 = (data2 | value);
+ consys_spi_write_nolock(subsystem, addr, data2);
+ pr_info("[%s][%s] Write CR:0x%08x from 0x%08x to 0x%08x",
+ __func__, g_spi_system_name[subsystem],
+ addr, data, data2);
+}
+
+
+static int consys_adie_top_ck_en_ctrl(bool on)
+{
+ int check = 0;
+
+ if (on)
+ CONSYS_SET_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_ADIE_CTL, (0x1 << 1));
+ else
+ CONSYS_CLR_BIT(CON_REG_INFRA_CFG_ADDR + CONN_INFRA_CFG_ADIE_CTL, (0x1 << 1));
+
+ CONSYS_REG_BIT_POLLING(
+ CON_REG_WT_SPL_CTL_ADDR + CONN_WTSLP_CTL_REG_WB_STA,
+ 26, 0, 100, 5, check);
+ if (check == -1) {
+ pr_err("[%s] op=%d fail\n", __func__, on);
+ }
+ return check;
+
+}
+
+int consys_adie_top_ck_en_on(enum consys_adie_ctl_type type)
+{
+ unsigned int status;
+ int ret;
+
+ if (type >= CONNSYS_ADIE_CTL_MAX) {
+ pr_err("[%s] invalid parameter(%d)\n", __func__, type);
+ return -1;
+ }
+
+ if (consys_sema_acquire_timeout(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) {
+ pr_err("[%s][%s] acquire semaphore (%d) timeout\n",
+ __func__, gAdieCtrlType[type], CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX);
+ return -1;
+ }
+
+ status = CONSYS_REG_READ(
+ CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL);
+ if ((status & CONN_INFRA_SYSRAM__A_DIE_DIG_TOP_CK_EN_MASK) == 0) {
+ ret = consys_adie_top_ck_en_ctrl(true);
+ }
+ CONSYS_SET_BIT(
+ CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL, (0x1 << type));
+
+ consys_sema_release(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX);
+ return 0;
+}
+
+int consys_adie_top_ck_en_off(enum consys_adie_ctl_type type)
+{
+ unsigned int status;
+ int ret = 0;
+
+ if (type >= CONNSYS_ADIE_CTL_MAX) {
+ pr_err("[%s] invalid parameter(%d)\n", __func__, type);
+ return -1;
+ }
+
+ if (consys_sema_acquire_timeout(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) {
+ pr_err("[%s][%s] acquire semaphoreaore (%d) timeout\n",
+ __func__, gAdieCtrlType[type], CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX);
+ return -1;
+ }
+
+ status = CONSYS_REG_READ(
+ CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL);
+ if ((status & (0x1 << type)) == 0) {
+ pr_warn("[%s][%s] already off\n", __func__, gAdieCtrlType[type]);
+ } else {
+ CONSYS_CLR_BIT(
+ CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL, (0x1 << type));
+
+ status = CONSYS_REG_READ(
+ CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_A_DIE_TOP_CK_EN_CTRL);
+ if (0 == (status & CONN_INFRA_SYSRAM__A_DIE_DIG_TOP_CK_EN_MASK)) {
+ ret = consys_adie_top_ck_en_ctrl(false);
+ }
+ }
+
+ consys_sema_release(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX);
+ return ret;
+}
+
+int consys_spi_clock_switch(enum connsys_spi_speed_type type)
+{
+#define MAX_SPI_CLOCK_SWITCH_COUNT 100
+ unsigned int status;
+ unsigned int counter = 0;
+ int ret = 0;
+
+ /* Get semaphore before read */
+ if (consys_sema_acquire_timeout(CONN_SEMA_RFSPI_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) {
+ pr_err("[SPI CLOCK SWITCH] Require semaphore fail\n");
+ return -1;
+ }
+
+ if (type == CONNSYS_SPI_SPEED_26M) {
+ CONSYS_REG_WRITE_MASK(
+ CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_SPI_CRTL,
+ 0x0, 0x5);
+ status = CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_SPI_CRTL) & 0x18;
+ while (status != 0x8 && counter < MAX_SPI_CLOCK_SWITCH_COUNT) {
+ udelay(10);
+ status = CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_SPI_CRTL) & 0x18;
+ counter++;
+ }
+ if (counter == MAX_SPI_CLOCK_SWITCH_COUNT) {
+ pr_err("[%s] switch to 26M fail\n", __func__);
+ ret = -1;
+ }
+ } else if (type == CONNSYS_SPI_SPEED_64M) {
+ CONSYS_REG_WRITE_MASK(
+ CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_SPI_CRTL, 0x5, 0x5);
+ status = CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_SPI_CRTL) & 0x18;
+ while (status != 0x10 && counter < MAX_SPI_CLOCK_SWITCH_COUNT) {
+ udelay(10);
+ status = CONSYS_REG_READ(CONN_REG_RFSPI_ADDR + CONN_RF_SPI_MST_REG_SPI_CRTL) & 0x18;
+ counter++;
+ }
+ if (counter == MAX_SPI_CLOCK_SWITCH_COUNT) {
+ pr_err("[%s] switch to 64M fail\n", __func__);
+ ret = -1;
+ }
+ } else {
+ ret = -1;
+ pr_err("[%s] wrong parameter %d\n", __func__, type);
+ }
+
+ consys_sema_release(CONN_SEMA_RFSPI_INDEX);
+
+ return ret;
+}
+
+int consys_subsys_status_update(bool on, int radio)
+{
+ if (radio < CONNDRV_TYPE_BT || radio > CONNDRV_TYPE_WIFI) {
+ pr_err("[%s] wrong parameter: %d\n", __func__, radio);
+ return -1;
+ }
+
+ if (consys_sema_acquire_timeout(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX, CONN_SEMA_TIMEOUT) == CONN_SEMA_GET_FAIL) {
+ pr_err("[%s] acquire semaphore (%d) timeout\n",
+ __func__, CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX);
+ return -1;
+ }
+
+ if (on) {
+ CONSYS_SET_BIT(
+ CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_RADIO_STATUS,
+ (0x1 << radio));
+ } else {
+ CONSYS_CLR_BIT(
+ CONN_INFRA_SYSRAM_BASE_ADDR + CONN_INFRA_SYSRAM_SW_CR_RADIO_STATUS,
+ (0x1 << radio));
+ }
+
+ consys_sema_release(CONN_SEMA_CONN_INFRA_COMMON_SYSRAM_INDEX);
+ return 0;
+}
+
+
+bool consys_is_rc_mode_enable(void)
+{
+ int ret;
+
+ ret = CONSYS_REG_READ_BIT(CON_REG_SPM_BASE_ADDR + SPM_RC_CENTRAL_CFG1, 0x1);
+
+ return ret;
+}
+
+void consys_config_setup(void)
+{
+ /* To access CR in conninfra off domain, Conninfra should be on state */
+ /* Enable conn_infra bus hang detect function
+ * Address: 0x1800_F000
+ * Data: 32'h32C8_001C
+ * Action: write
+ */
+ CONSYS_REG_WRITE(CONN_DEBUG_CTRL_ADDR + CONN_DEBUG_CTRL_REG_OFFSET, 0x32c8001c);
+}
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/pmic_mng.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/pmic_mng.c
new file mode 100755
index 0000000..39d7865
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/platform/pmic_mng.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#include "consys_hw.h"
+#include "pmic_mng.h"
+#include "osal.h"
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+const struct consys_platform_pmic_ops* consys_platform_pmic_ops = NULL;
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+int pmic_mng_init(
+ struct platform_device *pdev,
+ struct conninfra_dev_cb* dev_cb,
+ const struct conninfra_plat_data* plat_data)
+{
+ if (consys_platform_pmic_ops == NULL) {
+ consys_platform_pmic_ops =
+ (const struct consys_platform_pmic_ops*)plat_data->platform_pmic_ops;
+ }
+
+ if (consys_platform_pmic_ops && consys_platform_pmic_ops->consys_pmic_get_from_dts)
+ consys_platform_pmic_ops->consys_pmic_get_from_dts(pdev, dev_cb);
+
+ return 0;
+}
+
+int pmic_mng_deinit(void)
+{
+ return 0;
+}
+
+int pmic_mng_common_power_ctrl(unsigned int enable)
+{
+ int ret = 0;
+ if (consys_platform_pmic_ops &&
+ consys_platform_pmic_ops->consys_pmic_common_power_ctrl)
+ ret = consys_platform_pmic_ops->consys_pmic_common_power_ctrl(enable);
+ return ret;
+}
+
+int pmic_mng_wifi_power_ctrl(unsigned int enable)
+{
+ int ret = 0;
+ if (consys_platform_pmic_ops &&
+ consys_platform_pmic_ops->consys_pmic_wifi_power_ctrl)
+ ret = consys_platform_pmic_ops->consys_pmic_wifi_power_ctrl(enable);
+ return ret;
+
+}
+
+int pmic_mng_bt_power_ctrl(unsigned int enable)
+{
+ int ret = 0;
+ if (consys_platform_pmic_ops &&
+ consys_platform_pmic_ops->consys_pmic_bt_power_ctrl)
+ ret = consys_platform_pmic_ops->consys_pmic_bt_power_ctrl(enable);
+ return ret;
+}
+
+int pmic_mng_gps_power_ctrl(unsigned int enable)
+{
+ int ret = 0;
+ if (consys_platform_pmic_ops &&
+ consys_platform_pmic_ops->consys_pmic_gps_power_ctrl)
+ ret = consys_platform_pmic_ops->consys_pmic_gps_power_ctrl(enable);
+ return ret;
+}
+
+int pmic_mng_fm_power_ctrl(unsigned int enable)
+{
+ int ret = 0;
+ if (consys_platform_pmic_ops &&
+ consys_platform_pmic_ops->consys_pmic_fm_power_ctrl)
+ ret = consys_platform_pmic_ops->consys_pmic_fm_power_ctrl(enable);
+ return ret;
+}
+
+
+int pmic_mng_event_cb(unsigned int id, unsigned int event)
+{
+ if (consys_platform_pmic_ops &&
+ consys_platform_pmic_ops->consys_pmic_event_notifier)
+ consys_platform_pmic_ops->consys_pmic_event_notifier(id, event);
+ return 0;
+}
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/src/conninfra.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/src/conninfra.c
new file mode 100755
index 0000000..a4cf074
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/src/conninfra.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME "@(%s:%d) " fmt, __func__, __LINE__
+
+#include <linux/platform_device.h>
+#include <linux/cdev.h>
+#include <linux/module.h>
+#include <linux/fb.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include "conninfra.h"
+#include "emi_mng.h"
+#include "conninfra_core.h"
+#include "consys_hw.h"
+
+#include <linux/ratelimit.h>
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+#define CONNINFRA_RST_RATE_LIMIT 0
+
+#if CONNINFRA_RST_RATE_LIMIT
+DEFINE_RATELIMIT_STATE(g_rs, HZ, 1);
+
+#define DUMP_LOG() if (__ratelimit(&g_rs)) \
+ pr_info("rst is ongoing")
+
+#else
+#define DUMP_LOG()
+#endif
+
+struct conninfra_rst_data {
+ struct work_struct rst_worker;
+ enum consys_drv_type drv;
+ char *reason;
+};
+
+struct conninfra_rst_data rst_data;
+
+int conninfra_get_clock_schematic(void)
+{
+ return consys_hw_get_clock_schematic();
+}
+EXPORT_SYMBOL(conninfra_get_clock_schematic);
+
+void conninfra_get_phy_addr(unsigned int *addr, unsigned int *size)
+{
+ phys_addr_t base;
+
+ conninfra_get_emi_phy_addr(CONNSYS_EMI_FW_WFDMA, &base, size);
+ if (addr)
+ *addr = (unsigned int)base;
+ return;
+}
+EXPORT_SYMBOL(conninfra_get_phy_addr);
+
+void conninfra_get_emi_phy_addr(enum connsys_emi_type type, phys_addr_t* base, unsigned int *size)
+{
+ struct consys_emi_addr_info* addr_info = emi_mng_get_phy_addr();
+
+ switch (type) {
+ case CONNSYS_EMI_FW_WFDMA:
+ if (base)
+ *base = addr_info->emi_ap_phy_addr;
+ if (size)
+ *size = addr_info->emi_size;
+ break;
+ case CONNSYS_EMI_FW:
+ if (base)
+ *base = addr_info->emi_ap_phy_addr;
+ if (size)
+ *size = addr_info->fw_emi_size;
+ break;
+ case CONNSYS_EMI_WFDMA:
+ if (base)
+ *base = addr_info->emi_ap_phy_addr + addr_info->fw_emi_size;
+ if (size)
+ *size = addr_info->wfdma_emi_size;
+ break;
+ case CONNSYS_EMI_MCIF:
+ if (base)
+ *base = addr_info->md_emi_phy_addr;
+ if (size)
+ *size = addr_info->md_emi_size;
+ break;
+ default:
+ pr_err("Wrong EMI type: %d\n", type);
+ if (base)
+ *base = 0x0;
+ if (size)
+ *size = 0;
+ }
+}
+EXPORT_SYMBOL(conninfra_get_emi_phy_addr);
+
+int conninfra_pwr_on(enum consys_drv_type drv_type)
+{
+ pr_info("[%s] drv=[%d]", __func__, drv_type);
+ if (conninfra_core_is_rst_locking()) {
+ DUMP_LOG();
+ return CONNINFRA_ERR_RST_ONGOING;
+ }
+
+#if CFG_CONNINFRA_PRE_CAL_BLOCKING
+ conninfra_core_pre_cal_blocking();
+#endif
+
+ return conninfra_core_power_on(drv_type);
+}
+EXPORT_SYMBOL(conninfra_pwr_on);
+
+int conninfra_pwr_off(enum consys_drv_type drv_type)
+{
+ if (conninfra_core_is_rst_locking()) {
+ DUMP_LOG();
+ return CONNINFRA_ERR_RST_ONGOING;
+ }
+
+#if CFG_CONNINFRA_PRE_CAL_BLOCKING
+ conninfra_core_pre_cal_blocking();
+#endif
+
+ return conninfra_core_power_off(drv_type);
+}
+EXPORT_SYMBOL(conninfra_pwr_off);
+
+
+int conninfra_reg_readable(void)
+{
+ return conninfra_core_reg_readable();
+}
+EXPORT_SYMBOL(conninfra_reg_readable);
+
+
+int conninfra_reg_readable_no_lock(void)
+{
+ return conninfra_core_reg_readable_no_lock();
+}
+EXPORT_SYMBOL(conninfra_reg_readable_no_lock);
+
+int conninfra_is_bus_hang(void)
+{
+ if (conninfra_core_is_rst_locking()) {
+ DUMP_LOG();
+ return CONNINFRA_ERR_RST_ONGOING;
+ }
+ return conninfra_core_is_bus_hang();
+}
+EXPORT_SYMBOL(conninfra_is_bus_hang);
+
+int conninfra_trigger_whole_chip_rst(enum consys_drv_type who, char *reason)
+{
+ /* use schedule worker to trigger ??? */
+ /* so that function can be returned immediately */
+ int r;
+
+ r = conninfra_core_lock_rst();
+ if (r >= CHIP_RST_START) {
+ /* reset is ongoing */
+ pr_warn("[%s] r=[%d] chip rst is ongoing\n", __func__, r);
+ return 1;
+ }
+ pr_info("[%s] rst lock [%d] [%d] reason=%s", __func__, r, who, reason);
+
+ conninfra_core_trg_chip_rst(who, reason);
+
+ return 0;
+}
+EXPORT_SYMBOL(conninfra_trigger_whole_chip_rst);
+
+int conninfra_sub_drv_ops_register(enum consys_drv_type type,
+ struct sub_drv_ops_cb *cb)
+{
+ /* type validation */
+ if (type < 0 || type >= CONNDRV_TYPE_MAX) {
+ pr_err("[%s] incorrect drv type [%d]", __func__, type);
+ return -EINVAL;
+ }
+ pr_info("[%s] ----", __func__);
+ conninfra_core_subsys_ops_reg(type, cb);
+ return 0;
+}
+EXPORT_SYMBOL(conninfra_sub_drv_ops_register);
+
+int conninfra_sub_drv_ops_unregister(enum consys_drv_type type)
+{
+ /* type validation */
+ if (type < 0 || type >= CONNDRV_TYPE_MAX) {
+ pr_err("[%s] incorrect drv type [%d]", __func__, type);
+ return -EINVAL;
+ }
+ pr_info("[%s] ----", __func__);
+ conninfra_core_subsys_ops_unreg(type);
+ return 0;
+}
+EXPORT_SYMBOL(conninfra_sub_drv_ops_unregister);
+
+
+int conninfra_spi_read(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int *data)
+{
+ if (conninfra_core_is_rst_locking()) {
+ DUMP_LOG();
+ return CONNINFRA_ERR_RST_ONGOING;
+ }
+ if (subsystem >= SYS_SPI_MAX) {
+ pr_err("[%s] wrong subsys %d", __func__, subsystem);
+ return -EINVAL;
+ }
+ conninfra_core_spi_read(subsystem, addr, data);
+ return 0;
+}
+EXPORT_SYMBOL(conninfra_spi_read);
+
+int conninfra_spi_write(enum sys_spi_subsystem subsystem, unsigned int addr, unsigned int data)
+{
+ if (conninfra_core_is_rst_locking()) {
+ DUMP_LOG();
+ return CONNINFRA_ERR_RST_ONGOING;
+ }
+
+ if (subsystem >= SYS_SPI_MAX) {
+ pr_err("[%s] wrong subsys %d", __func__, subsystem);
+ return -EINVAL;
+ }
+ conninfra_core_spi_write(subsystem, addr, data);
+ return 0;
+}
+EXPORT_SYMBOL(conninfra_spi_write);
+
+int conninfra_adie_top_ck_en_on(enum consys_adie_ctl_type type)
+{
+ if (conninfra_core_is_rst_locking()) {
+ DUMP_LOG();
+ return CONNINFRA_ERR_RST_ONGOING;
+ }
+
+ return conninfra_core_adie_top_ck_en_on(type);
+}
+EXPORT_SYMBOL(conninfra_adie_top_ck_en_on);
+
+int conninfra_adie_top_ck_en_off(enum consys_adie_ctl_type type)
+{
+ if (conninfra_core_is_rst_locking()) {
+ DUMP_LOG();
+ return CONNINFRA_ERR_RST_ONGOING;
+ }
+
+ return conninfra_core_adie_top_ck_en_off(type);
+}
+EXPORT_SYMBOL(conninfra_adie_top_ck_en_off);
+
+int conninfra_spi_clock_switch(enum connsys_spi_speed_type type)
+{
+ return conninfra_core_spi_clock_switch(type);
+}
+EXPORT_SYMBOL(conninfra_spi_clock_switch);
+
+void conninfra_config_setup(void)
+{
+ if (conninfra_core_is_rst_locking()) {
+ DUMP_LOG();
+ return;
+ }
+
+ conninfra_core_config_setup();
+}
+EXPORT_SYMBOL(conninfra_config_setup);
+
+int conninfra_bus_clock_ctrl(enum consys_drv_type drv_type, unsigned int bus_clock, int status)
+{
+ return conninfra_core_bus_clock_ctrl(drv_type, bus_clock, status);
+}
+EXPORT_SYMBOL(conninfra_bus_clock_ctrl);
+
+int conninfra_debug_dump(void)
+{
+ return conninfra_core_debug_dump();
+
+}
+EXPORT_SYMBOL(conninfra_debug_dump);
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/src/conninfra_dev.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/src/conninfra_dev.c
new file mode 100755
index 0000000..6ea97e3
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/src/conninfra_dev.c
@@ -0,0 +1,593 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#include <linux/cdev.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include "conninfra.h"
+#include "conninfra_conf.h"
+#include "conninfra_core.h"
+#include "conninfra_dbg.h"
+#include "consys_hw.h"
+#include "wmt_build_in_adapter.h"
+#include "emi_mng.h"
+
+#if CFG_CONNINFRA_STEP_SUPPORT
+#include "conninfra_step.h"
+#endif /* CFG_CONNINFRA_STEP_SUPPORT */
+
+#if CFG_CONNINFRA_UT_SUPPORT
+#include "conninfra_test.h"
+#endif /* CFG_CONNINFRA_UT_SUPPORT */
+
+#if CFG_CONNINFRA_DEVAPC_SUPPORT
+#include <devapc_public.h>
+#endif /* CFG_CONNINFRA_DEVAPC_SUPPORT */
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+#define CONNINFRA_DEV_MAJOR 164
+#define CONNINFRA_DEV_NUM 1
+#define CONNINFRA_DRVIER_NAME "conninfra_drv"
+#define CONNINFRA_DEVICE_NAME "conninfra_dev"
+
+#define CONNINFRA_DEV_IOC_MAGIC 0xc2
+#define CONNINFRA_IOCTL_GET_CHIP_ID _IOR(CONNINFRA_DEV_IOC_MAGIC, 0, int)
+#define CONNINFRA_IOCTL_SET_COREDUMP_MODE _IOW(CONNINFRA_DEV_IOC_MAGIC, 1, unsigned int)
+
+#define CONNINFRA_DEV_INIT_TO_MS (2 * 1000)
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+enum conninfra_init_status {
+ CONNINFRA_INIT_NOT_START,
+ CONNINFRA_INIT_START,
+ CONNINFRA_INIT_DONE,
+};
+static int g_conninfra_init_status = CONNINFRA_INIT_NOT_START;
+static wait_queue_head_t g_conninfra_init_wq;
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+static int conninfra_dev_fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data);
+static int conninfra_dev_open(struct inode *inode, struct file *file);
+static int conninfra_dev_close(struct inode *inode, struct file *file);
+static ssize_t conninfra_dev_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos);
+static ssize_t conninfra_dev_write(struct file *filp,
+ const char __user *buf, size_t count,
+ loff_t *f_pos);
+static long conninfra_dev_unlocked_ioctl(
+ struct file *filp, unsigned int cmd, unsigned long arg);
+#ifdef CONFIG_COMPAT
+static long conninfra_dev_compat_ioctl(
+ struct file *filp, unsigned int cmd, unsigned long arg);
+#endif /* CONFIG_COMPAT */
+static int conninfra_mmap(struct file *pFile, struct vm_area_struct *pVma);
+
+static int conninfra_thermal_query_cb(void);
+static void conninfra_clock_fail_dump_cb(void);
+
+static int conninfra_conn_reg_readable(void);
+static int conninfra_conn_is_bus_hang(void);
+
+#if CFG_CONNINFRA_DEVAPC_SUPPORT
+static void conninfra_devapc_violation_cb(void);
+static void conninfra_register_devapc_callback(void);
+#endif /* CFG_CONNINFRA_DEVAPC_SUPPORT */
+
+static int conninfra_dev_suspend_cb(void);
+static int conninfra_dev_resume_cb(void);
+static int conninfra_dev_pmic_event_cb(unsigned int, unsigned int);
+static int conninfra_dev_thermal_query_cb(void*, int*);
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+struct class *pConninfraClass;
+struct device *pConninfraDev;
+static struct cdev gConninfraCdev;
+
+const struct file_operations gConninfraDevFops = {
+ .open = conninfra_dev_open,
+ .release = conninfra_dev_close,
+ .read = conninfra_dev_read,
+ .write = conninfra_dev_write,
+ .unlocked_ioctl = conninfra_dev_unlocked_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = conninfra_dev_compat_ioctl,
+#endif /* CONFIG_COMPAT */
+ .mmap = conninfra_mmap,
+};
+
+struct wmt_platform_bridge g_plat_bridge = {
+ .thermal_query_cb = conninfra_thermal_query_cb,
+ .clock_fail_dump_cb = conninfra_clock_fail_dump_cb,
+ .conninfra_reg_readable_cb = conninfra_conn_reg_readable,
+ .conninfra_reg_is_bus_hang_cb = conninfra_conn_is_bus_hang
+};
+
+static int gConnInfraMajor = CONNINFRA_DEV_MAJOR;
+
+/* screen on/off notification */
+static struct notifier_block conninfra_fb_notifier;
+static struct work_struct gPwrOnOffWork;
+static atomic_t g_es_lr_flag_for_blank = ATOMIC_INIT(0); /* for ctrl blank flag */
+static int last_thermal_value;
+static int g_temp_thermal_value;
+
+static struct conninfra_dev_cb g_conninfra_dev_cb = {
+ .conninfra_suspend_cb = conninfra_dev_suspend_cb,
+ .conninfra_resume_cb = conninfra_dev_resume_cb,
+ .conninfra_pmic_event_notifier = conninfra_dev_pmic_event_cb,
+ .conninfra_thermal_query_cb = conninfra_dev_thermal_query_cb,
+};
+
+/* For DEVAPC callback */
+#if CFG_CONNINFRA_DEVAPC_SUPPORT
+static struct work_struct g_conninfra_devapc_work;
+static struct devapc_vio_callbacks conninfra_devapc_handle = {
+ .id = INFRA_SUBSYS_CONN,
+ .debug_dump = conninfra_devapc_violation_cb,
+};
+#endif /* CFG_CONNINFRA_DEVAPC_SUPPORT */
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+int conninfra_dev_open(struct inode *inode, struct file *file)
+{
+ static DEFINE_RATELIMIT_STATE(_rs, HZ, 1);
+
+ if (!wait_event_timeout(
+ g_conninfra_init_wq,
+ g_conninfra_init_status == CONNINFRA_INIT_DONE,
+ msecs_to_jiffies(CONNINFRA_DEV_INIT_TO_MS))) {
+ if (__ratelimit(&_rs)) {
+ pr_warn("wait_event_timeout (%d)ms,(%lu)jiffies,return -EIO\n",
+ CONNINFRA_DEV_INIT_TO_MS, msecs_to_jiffies(CONNINFRA_DEV_INIT_TO_MS));
+ }
+ return -EIO;
+ }
+
+ pr_info("open major %d minor %d (pid %d)\n",
+ imajor(inode), iminor(inode), current->pid);
+
+ return 0;
+}
+
+int conninfra_dev_close(struct inode *inode, struct file *file)
+{
+ pr_info("close major %d minor %d (pid %d)\n",
+ imajor(inode), iminor(inode), current->pid);
+
+ return 0;
+}
+
+ssize_t conninfra_dev_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ return 0;
+}
+
+ssize_t conninfra_dev_write(struct file *filp,
+ const char __user *buf, size_t count, loff_t *f_pos)
+{
+ return 0;
+}
+
+static long conninfra_dev_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int retval = 0;
+
+ pr_info("[%s] cmd (%d),arg(%ld)\n", __func__, cmd, arg);
+ switch (cmd) {
+ case CONNINFRA_IOCTL_GET_CHIP_ID:
+ retval = consys_hw_chipid_get();
+ break;
+ case CONNINFRA_IOCTL_SET_COREDUMP_MODE:
+ #if CFG_CONNINFRA_COREDUMP_SUPPORT
+ connsys_coredump_set_dump_mode(arg);
+ #else
+ pr_info("Coredump is not support");
+ #endif /* CFG_CONNINFRA_COREDUMP_SUPPORT */
+ break;
+ }
+ return retval;
+
+}
+
+#ifdef CONFIG_COMPAT
+static long conninfra_dev_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ long ret;
+
+ pr_info("[%s] cmd (%d)\n", __func__, cmd);
+ ret = conninfra_dev_unlocked_ioctl(filp, cmd, arg);
+ return ret;
+}
+#endif /* CONFIG_COMPAT */
+
+static int conninfra_mmap(struct file *pFile, struct vm_area_struct *pVma)
+{
+#if CFG_CONNINFRA_COREDUMP_SUPPORT
+ unsigned long bufId = pVma->vm_pgoff;
+ struct consys_emi_addr_info* addr_info = emi_mng_get_phy_addr();
+
+ pr_info("conninfra_mmap start:%lu end:%lu size: %lu buffer id=%lu\n",
+ pVma->vm_start, pVma->vm_end,
+ pVma->vm_end - pVma->vm_start, bufId);
+
+ if (bufId == 0) {
+ if (pVma->vm_end - pVma->vm_start > addr_info->emi_size)
+ return -1;
+ pr_info("conninfra_mmap size: %lu\n", pVma->vm_end - pVma->vm_start);
+ if (remap_pfn_range(pVma, pVma->vm_start, addr_info->emi_ap_phy_addr >> PAGE_SHIFT,
+ pVma->vm_end - pVma->vm_start, pVma->vm_page_prot))
+ return -EAGAIN;
+ } else if (bufId == 1) {
+ if (addr_info == NULL)
+ return -1;
+ if (addr_info->md_emi_size == 0 ||
+ pVma->vm_end - pVma->vm_start > addr_info->md_emi_size)
+ return -1;
+ pr_info("MD direct path size=%u map size=%lu\n",
+ addr_info->md_emi_size,
+ pVma->vm_end - pVma->vm_start);
+ if (remap_pfn_range(pVma, pVma->vm_start,
+ addr_info->md_emi_phy_addr >> PAGE_SHIFT,
+ pVma->vm_end - pVma->vm_start, pVma->vm_page_prot))
+ return -EAGAIN;
+ }
+#endif /* CFG_CONNINFRA_COREDUMP_SUPPORT */
+ return -EINVAL;
+}
+
+static int conninfra_dev_get_blank_state(void)
+{
+ return atomic_read(&g_es_lr_flag_for_blank);
+}
+
+int conninfra_dev_fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ struct fb_event *evdata = data;
+ int blank;
+
+ pr_debug("conninfra_dev_fb_notifier_callback event=[%lu]\n", event);
+
+ /* If we aren't interested in this event, skip it immediately ... */
+ if (event != FB_EARLY_EVENT_BLANK)
+ return 0;
+
+ blank = *(int *)evdata->data;
+
+ switch (blank) {
+ case FB_BLANK_UNBLANK:
+ atomic_set(&g_es_lr_flag_for_blank, 1);
+ pr_info("@@@@@@@@@@ Conninfra enter UNBLANK @@@@@@@@@@@@@@\n");
+ schedule_work(&gPwrOnOffWork);
+ break;
+ case FB_BLANK_POWERDOWN:
+ atomic_set(&g_es_lr_flag_for_blank, 0);
+ pr_info("@@@@@@@@@@ Conninfra enter early POWERDOWN @@@@@@@@@@@@@@\n");
+ schedule_work(&gPwrOnOffWork);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static void conninfra_dev_pwr_on_off_handler(struct work_struct *work)
+{
+ pr_debug("conninfra_dev_pwr_on_off_handler start to run\n");
+
+ /* Update blank on status after wmt power on */
+ if (conninfra_dev_get_blank_state() == 1) {
+ conninfra_core_screen_on();
+ } else {
+ conninfra_core_screen_off();
+ }
+}
+
+static int conninfra_thermal_query_cb(void)
+{
+ int ret;
+
+ /* if rst is ongoing, return thermal val got from last time */
+ if (conninfra_core_is_rst_locking()) {
+ pr_info("[%s] rst is locking, return last temp ", __func__);
+ return last_thermal_value;
+ }
+ ret = conninfra_core_thermal_query(&g_temp_thermal_value);
+ if (ret == 0)
+ last_thermal_value = g_temp_thermal_value;
+ else if (ret == CONNINFRA_ERR_WAKEUP_FAIL)
+ conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_CONNINFRA, "Query thermal wakeup fail");
+
+ return last_thermal_value;
+}
+
+static void conninfra_clock_fail_dump_cb(void)
+{
+ conninfra_core_clock_fail_dump_cb();
+}
+
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+/* THIS FUNCTION IS ONLY FOR AUDIO DRIVER */
+/* this function go through consys_hw, skip conninfra_core */
+/* there is no lock and skip consys power on check */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+static int conninfra_conn_reg_readable(void)
+{
+ return consys_hw_reg_readable();
+ /*return conninfra_core_reg_readable(); */
+}
+
+static int conninfra_conn_is_bus_hang(void)
+{
+ /* if rst is ongoing, don't dump */
+ if (conninfra_core_is_rst_locking()) {
+ pr_info("[%s] rst is locking, skip dump", __func__);
+ return CONNINFRA_ERR_RST_ONGOING;
+ }
+ return conninfra_core_is_bus_hang();
+}
+
+#if CFG_CONNINFRA_DEVAPC_SUPPORT
+static void conninfra_devapc_violation_cb(void)
+{
+ schedule_work(&g_conninfra_devapc_work);
+}
+
+static void conninfra_devapc_handler(struct work_struct *work)
+{
+ conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_CONNINFRA, "CONNSYS DEVAPC");
+}
+
+static void conninfra_register_devapc_callback(void)
+{
+ INIT_WORK(&g_conninfra_devapc_work, conninfra_devapc_handler);
+ register_devapc_vio_callback(&conninfra_devapc_handle);
+}
+#endif /* CFG_CONNINFRA_DEVAPC_SUPPORT */
+
+static int conninfra_dev_suspend_cb(void)
+{
+ return 0;
+}
+
+static int conninfra_dev_resume_cb(void)
+{
+ conninfra_core_dump_power_state();
+ return 0;
+}
+
+static int conninfra_dev_pmic_event_cb(unsigned int id, unsigned int event)
+{
+ conninfra_core_pmic_event_cb(id, event);
+
+ return 0;
+}
+
+static int conninfra_dev_thermal_query_cb(void* data, int* temp)
+{
+ if (temp)
+ *temp = conninfra_thermal_query_cb();
+
+ return 0;
+}
+
+/************************************************************************/
+
+static int conninfra_dev_init(void)
+{
+ dev_t devID = MKDEV(gConnInfraMajor, 0);
+ int cdevErr = -1;
+ int iret = 0;
+
+ g_conninfra_init_status = CONNINFRA_INIT_START;
+ init_waitqueue_head((wait_queue_head_t *)&g_conninfra_init_wq);
+
+ iret = register_chrdev_region(devID, CONNINFRA_DEV_NUM,
+ CONNINFRA_DRVIER_NAME);
+ if (iret) {
+ pr_err("fail to register chrdev\n");
+ g_conninfra_init_status = CONNINFRA_INIT_NOT_START;
+ return -1;
+ }
+
+ cdev_init(&gConninfraCdev, &gConninfraDevFops);
+ gConninfraCdev.owner = THIS_MODULE;
+
+ cdevErr = cdev_add(&gConninfraCdev, devID, CONNINFRA_DEV_NUM);
+ if (cdevErr) {
+ pr_err("cdev_add() fails (%d)\n", cdevErr);
+ goto err1;
+ }
+
+ pConninfraClass = class_create(THIS_MODULE, CONNINFRA_DEVICE_NAME);
+ if (IS_ERR(pConninfraClass)) {
+ pr_err("class create fail, error code(%ld)\n",
+ PTR_ERR(pConninfraClass));
+ goto err1;
+ }
+
+ pConninfraDev = device_create(pConninfraClass, NULL, devID,
+ NULL, CONNINFRA_DEVICE_NAME);
+ if (IS_ERR(pConninfraDev)) {
+ pr_err("device create fail, error code(%ld)\n",
+ PTR_ERR(pConninfraDev));
+ goto err2;
+ }
+
+ /* init power on off handler */
+ INIT_WORK(&gPwrOnOffWork, conninfra_dev_pwr_on_off_handler);
+ conninfra_fb_notifier.notifier_call
+ = conninfra_dev_fb_notifier_callback;
+ iret = fb_register_client(&conninfra_fb_notifier);
+ if (iret)
+ pr_err("register fb_notifier fail");
+ else
+ pr_info("register fb_notifier success");
+
+#if CFG_CONNINFRA_UT_SUPPORT
+ iret = conninfra_test_setup();
+ if (iret)
+ pr_err("init conninfra_test fail, ret = %d\n", iret);
+#endif /* CFG_CONNINFRA_UT_SUPPORT */
+
+ iret = conninfra_conf_init();
+ if (iret)
+ pr_warn("init conf fail\n");
+
+ iret = mtk_conninfra_drv_init(&g_conninfra_dev_cb);
+ if (iret) {
+ pr_err("init consys_hw fail, ret = %d\n", iret);
+ g_conninfra_init_status = CONNINFRA_INIT_NOT_START;
+ return -2;
+ }
+
+ iret = conninfra_core_init();
+ if (iret) {
+ pr_err("conninfra init fail");
+ g_conninfra_init_status = CONNINFRA_INIT_NOT_START;
+ return -3;
+ }
+
+ conninfra_dev_dbg_init();
+
+#if CFG_CONNINFRA_STEP_SUPPORT
+ CONNINFRA_STEP_INIT_FUNC();
+#endif /* CFG_CONNINFRA_STEP_SUPPORT */
+
+ wmt_export_platform_bridge_register(&g_plat_bridge);
+
+#if CFG_CONNINFRA_DEVAPC_SUPPORT
+ conninfra_register_devapc_callback();
+#endif /* CFG_CONNINFRA_DEVAPC_SUPPORT */
+
+ pr_info("ConnInfra Dev: init (%d)\n", iret);
+ g_conninfra_init_status = CONNINFRA_INIT_DONE;
+ return 0;
+
+err2:
+
+ pr_err("[conninfra_dev_init] err2");
+ if (pConninfraClass) {
+ class_destroy(pConninfraClass);
+ pConninfraClass = NULL;
+ }
+err1:
+ pr_err("[conninfra_dev_init] err1");
+ if (cdevErr == 0)
+ cdev_del(&gConninfraCdev);
+
+ if (iret == 0) {
+ unregister_chrdev_region(devID, CONNINFRA_DEV_NUM);
+ gConnInfraMajor = -1;
+ }
+
+ g_conninfra_init_status = CONNINFRA_INIT_NOT_START;
+ return -2;
+}
+
+static void conninfra_dev_deinit(void)
+{
+ dev_t dev = MKDEV(gConnInfraMajor, 0);
+ int iret = 0;
+
+ g_conninfra_init_status = CONNINFRA_INIT_NOT_START;
+ fb_unregister_client(&conninfra_fb_notifier);
+
+ iret = conninfra_dev_dbg_deinit();
+#if CFG_CONNINFRA_UT_SUPPORT
+ iret = conninfra_test_remove();
+#endif /* CFG_CONNINFRA_UT_SUPPORT */
+
+#if CFG_CONNINFRA_STEP_SUPPORT
+ CONNINFRA_STEP_DEINIT_FUNC();
+#endif /* CFG_CONNINFRA_STEP_SUPPORT */
+
+ iret = conninfra_core_deinit();
+
+ iret = mtk_conninfra_drv_deinit();
+
+ iret = conninfra_conf_deinit();
+
+ if (pConninfraDev) {
+ device_destroy(pConninfraClass, dev);
+ pConninfraDev = NULL;
+ }
+
+ if (pConninfraClass) {
+ class_destroy(pConninfraClass);
+ pConninfraClass = NULL;
+ }
+
+ cdev_del(&gConninfraCdev);
+ unregister_chrdev_region(dev, CONNINFRA_DEV_NUM);
+
+ pr_info("ConnInfra: platform init (%d)\n", iret);
+}
+
+module_init(conninfra_dev_init);
+module_exit(conninfra_dev_deinit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Willy.Yu @ CTD/SE5/CS5");
+
+module_param(gConnInfraMajor, uint, 0644);
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/cal_test.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/cal_test.c
new file mode 100755
index 0000000..4ba3cc8
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/cal_test.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#include <linux/slab.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include "conninfra.h"
+#include "conninfra_core.h"
+#include "osal.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+int pre_cal_power_on_handler(void)
+{
+ pr_info("[%s] ===========", __func__);
+ osal_sleep_ms(100);
+ return 0;
+}
+
+int pre_cal_do_cal_handler(void)
+{
+ pr_info("[%s] ===========", __func__);
+ return 0;
+}
+
+
+struct sub_drv_ops_cb g_cal_drv_ops_cb;
+
+int calibration_test(void)
+{
+ int ret;
+
+ memset(&g_cal_drv_ops_cb, 0, sizeof(struct sub_drv_ops_cb));
+
+ g_cal_drv_ops_cb.pre_cal_cb.pwr_on_cb = pre_cal_power_on_handler;
+ g_cal_drv_ops_cb.pre_cal_cb.do_cal_cb = pre_cal_do_cal_handler;
+
+
+ pr_info("[%s] cb init [%p][%p]", __func__,
+ g_cal_drv_ops_cb.pre_cal_cb.pwr_on_cb,
+ g_cal_drv_ops_cb.pre_cal_cb.do_cal_cb);
+
+ conninfra_sub_drv_ops_register(CONNDRV_TYPE_BT, &g_cal_drv_ops_cb);
+ conninfra_sub_drv_ops_register(CONNDRV_TYPE_WIFI, &g_cal_drv_ops_cb);
+
+ ret = conninfra_core_pre_cal_start();
+ if (ret)
+ pr_warn("[%s] fail [%d]", __func__, ret);
+
+ osal_sleep_ms(1000);
+
+ conninfra_core_screen_on();
+
+ conninfra_sub_drv_ops_unregister(CONNDRV_TYPE_BT);
+ conninfra_sub_drv_ops_unregister(CONNDRV_TYPE_WIFI);
+ pr_info("[%s] finish.", __func__);
+ return 0;
+}
+
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/chip_rst_test.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/chip_rst_test.c
new file mode 100755
index 0000000..bfd19b4
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/chip_rst_test.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#include <linux/slab.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include "conninfra.h"
+#include "osal.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+int pre_chip_rst_handler(enum consys_drv_type drv, char* reason)
+{
+ pr_info("[%s] ===========", __func__);
+ osal_sleep_ms(100);
+ return 0;
+}
+
+int post_chip_rst_handler(void)
+{
+ pr_info("[%s] ===========", __func__);
+ return 0;
+}
+
+int pre_chip_rst_timeout_handler(enum consys_drv_type drv, char* reason)
+{
+ pr_info("[%s] ++++++++++++", __func__);
+ osal_sleep_ms(800);
+ pr_info("[%s] ------------", __func__);
+ return 0;
+}
+
+struct sub_drv_ops_cb g_drv_ops_cb;
+struct sub_drv_ops_cb g_drv_timeout_ops_cb;
+
+int chip_rst_test(void)
+{
+ int ret;
+
+ memset(&g_drv_ops_cb, 0, sizeof(struct sub_drv_ops_cb));
+ memset(&g_drv_timeout_ops_cb, 0, sizeof(struct sub_drv_ops_cb));
+
+ g_drv_ops_cb.rst_cb.pre_whole_chip_rst = pre_chip_rst_handler;
+ g_drv_ops_cb.rst_cb.post_whole_chip_rst = post_chip_rst_handler;
+
+ g_drv_timeout_ops_cb.rst_cb.pre_whole_chip_rst = pre_chip_rst_timeout_handler;
+ g_drv_timeout_ops_cb.rst_cb.post_whole_chip_rst = post_chip_rst_handler;
+
+ pr_info("[%s] cb init [%p][%p]", __func__,
+ g_drv_ops_cb.rst_cb.pre_whole_chip_rst,
+ g_drv_ops_cb.rst_cb.post_whole_chip_rst);
+
+ conninfra_sub_drv_ops_register(CONNDRV_TYPE_BT, &g_drv_ops_cb);
+ conninfra_sub_drv_ops_register(CONNDRV_TYPE_WIFI, &g_drv_ops_cb);
+ conninfra_sub_drv_ops_register(CONNDRV_TYPE_FM, &g_drv_timeout_ops_cb);
+
+ pr_info("[%s] ++++++++++++++++++++++", __func__);
+
+ ret = conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_BT, "test reset");
+ if (ret)
+ pr_warn("[%s] fail [%d]", __func__, ret);
+ else
+ pr_info("Trigger chip reset success. Test pass.");
+ osal_sleep_ms(10);
+
+ pr_info("Try to trigger whole chip reset when reset is ongoing. It should be fail.");
+ ret = conninfra_trigger_whole_chip_rst(CONNDRV_TYPE_BT, "test reset");
+ pr_info("Test %s. ret = %d.", ret == 1? "pass": "fail", ret);
+
+ pr_info("Try to funcion on when reset is ongoing. It should be fail.");
+ ret = conninfra_pwr_on(CONNDRV_TYPE_WIFI);
+ pr_info("Test %s. ret = %d.", ret == CONNINFRA_ERR_RST_ONGOING ? "pass": "fail", ret);
+
+ osal_sleep_ms(3000);
+
+ conninfra_sub_drv_ops_unregister(CONNDRV_TYPE_BT);
+ conninfra_sub_drv_ops_unregister(CONNDRV_TYPE_WIFI);
+ pr_info("chip_rst_test finish");
+ return 0;
+}
+
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/conf_test.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/conf_test.c
new file mode 100755
index 0000000..4f39360
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/conf_test.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#include "conninfra_conf.h"
+#include "conf_test.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+
+int conninfra_conf_test(void)
+{
+ int ret;
+ const struct conninfra_conf *conf;
+
+#if 0
+ ret = conninfra_conf_set_cfg_file("WMT_SOC.cfg");
+ if (ret) {
+ pr_err("set cfg file fail [%d]", ret);
+ return -1;
+ }
+#endif
+
+ ret = conninfra_conf_init();
+ if (ret) {
+ pr_err("int conf fail [%d]", ret);
+ return -1;
+ }
+
+ conf = conninfra_conf_get_cfg();
+ if (NULL == conf) {
+ pr_err("int conf fail [%d]", ret);
+ return -1;
+ }
+ if (conf->tcxo_gpio != 0) {
+ pr_err("test tcxo gpio fail [%d]. For most case, it should be 0.",
+ conf->tcxo_gpio);
+ return -1;
+ }
+
+ pr_info("[%s] test PASS\n", __func__);
+ return 0;
+}
+
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/conninfra_step_test.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/conninfra_step_test.c
new file mode 100755
index 0000000..b4e5df5
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/conninfra_step_test.c
@@ -0,0 +1,4301 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include "osal.h"
+#include "conninfra_step_test.h"
+#include "conninfra_step.h"
+#include "emi_mng.h"
+#include "consys_hw.h"
+#include "consys_reg_mng.h"
+#include "consys_reg_util.h"
+
+
+#define TEST_WRITE_CR_TEST_CASE 0
+
+struct step_test_check g_conninfra_step_test_check;
+
+
+static void conninfra_step_test_create_emi_action(struct step_test_report *p_report);
+static void conninfra_step_test_create_cond_emi_action(struct step_test_report *p_report);
+static void conninfra_step_test_create_register_action(struct step_test_report *p_report);
+static void conninfra_step_test_create_cond_register_action(struct step_test_report *p_report);
+static void conninfra_step_test_check_register_symbol(struct step_test_report *p_report);
+static void conninfra_step_test_create_other_action(struct step_test_report *p_report);
+static void conninfra_step_test_do_emi_action(struct step_test_report *p_report);
+static void conninfra_step_test_do_cond_emi_action(struct step_test_report *p_report);
+static void conninfra_step_test_do_register_action(struct step_test_report *p_report);
+static void conninfra_step_test_do_cond_register_action(struct step_test_report *p_report);
+static void conninfra_step_test_do_gpio_action(struct step_test_report *p_report);
+static void conninfra_step_test_create_periodic_dump(struct step_test_report *p_report);
+static void conninfra_step_test_do_show_action(struct step_test_report *p_report);
+static void conninfra_step_test_do_sleep_action(struct step_test_report *p_report);
+static void conninfra_step_test_do_condition_action(struct step_test_report *p_report);
+static void conninfra_step_test_do_value_action(struct step_test_report *p_report);
+
+//static void conninfra_step_test_parse_data3(struct step_test_report *p_report);
+static void conninfra_step_test_parse_data1(struct step_test_report *p_report);
+static void conninfra_step_test_parse_data2(struct step_test_report *p_report);
+
+void conninfra_step_test_clear_parameter(char *params[])
+{
+ int i = 0;
+
+ for (i = 0; i < STEP_PARAMETER_SIZE; i++)
+ params[i] = NULL;
+}
+
+#define index_of_array(current_addr, base_addr, type) \
+ (((unsigned long)current_addr - (unsigned long)base_addr) / sizeof(type))
+
+
+int conninfra_step_test_check_write_tp2(struct step_action_list *p_act_list, enum step_drv_type drv_type,
+ enum step_action_id act_id, int param_num, char *params[])
+{
+ int index;
+ int i;
+ int tp_id;
+ struct step_test_scenario *cur_scn = g_conninfra_step_test_check.cur_test_scn;
+
+ if (cur_scn == NULL)
+ return 0;
+
+ if (g_conninfra_step_test_check.step_check_result == TEST_FAIL)
+ return 0;
+
+ index = cur_scn->test_idx;
+ cur_scn->test_idx++;
+
+ if (cur_scn->pt_acts[index].tp_id != -1) {
+
+ tp_id = index_of_array(p_act_list, g_step_drv_type_def[drv_type].action_list, struct step_action_list);
+
+ if (tp_id != cur_scn->pt_acts[index].tp_id) {
+ g_conninfra_step_test_check.step_check_result = TEST_FAIL;
+ pr_err("STEP test failed: [%d] drvType=[%d] tp_id %d: expect %d\n", index,
+ drv_type, tp_id, cur_scn->pt_acts[index].tp_id);
+ return 0;
+ }
+ }
+
+ if (act_id != cur_scn->pt_acts[index].act_id) {
+ g_conninfra_step_test_check.step_check_result = TEST_FAIL;
+ pr_err("STEP test failed: [%d] act_id %d: expect %d\n", index,
+ act_id, cur_scn->pt_acts[index].act_id);
+ return 0;
+ }
+
+ if (param_num != cur_scn->pt_acts[index].param_num) {
+ g_conninfra_step_test_check.step_check_result = TEST_FAIL;
+ pr_err("STEP test failed: [%d] param num %d: expect %d\n", index,
+ param_num, cur_scn->pt_acts[index].param_num);
+ return 0;
+ }
+
+ for (i = 0; i < STEP_PARAMETER_SIZE; i++) {
+ if (cur_scn->pt_acts[index].params[i] == NULL || strcmp(cur_scn->pt_acts[index].params[i], "") == 0)
+ break;
+
+ if (params[i] == NULL || strcmp(params[i], cur_scn->pt_acts[index].params[i]) != 0) {
+ g_conninfra_step_test_check.step_check_result = TEST_FAIL;
+ pr_err("STEP test failed: [%d] params[%d] %s: expect %s(%d)\n", index, i, params[i],
+ cur_scn->pt_acts[index].params[i]);
+ return 0;
+ }
+ }
+
+ g_conninfra_step_test_check.step_check_result = TEST_PASS;
+ return 0;
+}
+
+void __conninfra_step_test_parse_data2(const char *buf, struct step_test_report *p_report, char *err_result)
+{
+ struct step_test_scenario *cur_scn = g_conninfra_step_test_check.cur_test_scn;
+
+ conninfra_step_parse_data(buf, osal_strlen((char *)buf), conninfra_step_test_check_write_tp2);
+ if (cur_scn->total_test_sz != cur_scn->test_idx) {
+ pr_err("STEP test failed: index %d: expect total %d\n",
+ cur_scn->total_test_sz, cur_scn->test_idx);
+ g_conninfra_step_test_check.step_check_result = TEST_FAIL;
+ }
+ conninfra_step_test_update_result(g_conninfra_step_test_check.step_check_result, p_report, err_result);
+}
+
+void conninfra_step_test_check_emi_act(unsigned int len, ...)
+{
+ unsigned int offset;
+ unsigned int check_result;
+ unsigned int value;
+ unsigned char *p_virtual_addr = NULL;
+ va_list args;
+
+ if (g_conninfra_step_test_check.step_check_result == TEST_FAIL)
+ return;
+
+ offset = g_conninfra_step_test_check.step_check_emi_offset[g_conninfra_step_test_check.step_check_index];
+
+ p_virtual_addr = conninfra_step_test_get_emi_virt_offset(offset);
+ if (!p_virtual_addr) {
+ g_conninfra_step_test_check.step_check_result = TEST_FAIL;
+ pr_err("STEP test failed: p_virtual_addr offset(%d) is null", offset);
+ return;
+ }
+ check_result = CONSYS_REG_READ(p_virtual_addr);
+
+ va_start(args, len);
+ value = va_arg(args, unsigned int);
+ va_end(args);
+
+ conninfra_step_test_put_emi_virt_offset();
+
+ if (check_result == value) {
+ g_conninfra_step_test_check.step_check_result = TEST_PASS;
+ } else {
+ pr_err("STEP test failed: check index [%d] Value is %d, expect %d offset=[%x]",
+ g_conninfra_step_test_check.step_check_index,
+ value, check_result, offset);
+ g_conninfra_step_test_check.step_check_result = TEST_FAIL;
+ return;
+ }
+
+ if (g_conninfra_step_test_check.step_check_temp_register_id != -1) {
+ if (g_infra_step_env.temp_register[g_conninfra_step_test_check.step_check_temp_register_id] !=
+ (check_result & g_conninfra_step_test_check.step_test_mask)) {
+ pr_err("STEP test failed: Register id(%d) value is %d, expect %d mask 0x%08x",
+ g_conninfra_step_test_check.step_check_temp_register_id,
+ g_infra_step_env.temp_register[g_conninfra_step_test_check.step_check_temp_register_id],
+ check_result, g_conninfra_step_test_check.step_test_mask);
+ g_conninfra_step_test_check.step_check_result = TEST_FAIL;
+ }
+ }
+
+ g_conninfra_step_test_check.step_check_index++;
+}
+
+void conninfra_step_test_check_reg_read_act(unsigned int len, ...)
+{
+ unsigned int check_result;
+ unsigned int value;
+ va_list args;
+
+ if (g_conninfra_step_test_check.step_check_result == TEST_FAIL)
+ return;
+
+ va_start(args, len);
+ value = va_arg(args, unsigned int);
+ check_result = CONSYS_REG_READ(g_conninfra_step_test_check.step_check_register_addr);
+
+ if (check_result == value) {
+ g_conninfra_step_test_check.step_check_result = TEST_PASS;
+ } else {
+ pr_err("STEP test failed: Value is %d, expect %d(0x%08x)", value, check_result,
+ g_conninfra_step_test_check.step_check_register_addr);
+ g_conninfra_step_test_check.step_check_result = TEST_FAIL;
+ }
+
+ if (g_conninfra_step_test_check.step_check_temp_register_id != -1) {
+ if (g_infra_step_env.temp_register[g_conninfra_step_test_check.step_check_temp_register_id] !=
+ (check_result & g_conninfra_step_test_check.step_test_mask)) {
+ pr_err("STEP test failed: Register id(%d) value is %d, expect %d",
+ g_conninfra_step_test_check.step_check_temp_register_id,
+ g_infra_step_env.temp_register[g_conninfra_step_test_check.step_check_temp_register_id],
+ check_result);
+ g_conninfra_step_test_check.step_check_result = TEST_FAIL;
+ }
+ }
+
+ va_end(args);
+}
+
+void conninfra_step_test_check_reg_write_act(unsigned int len, ...)
+{
+ unsigned int value;
+ va_list args;
+ unsigned int mask = g_conninfra_step_test_check.step_test_mask;
+
+ va_start(args, len);
+ value = va_arg(args, unsigned int);
+
+ if (value == 0xdeadfeed) {
+ g_conninfra_step_test_check.step_check_result = TEST_PASS;
+ } else if (mask == 0xFFFFFFFF) {
+ if (g_conninfra_step_test_check.step_check_write_value == value) {
+ g_conninfra_step_test_check.step_check_result = TEST_PASS;
+ } else {
+ pr_err("STEP test failed: Value is %d, expect %d", value,
+ g_conninfra_step_test_check.step_check_write_value);
+ g_conninfra_step_test_check.step_check_result = TEST_FAIL;
+ }
+ } else {
+ if ((mask & value) != (mask & g_conninfra_step_test_check.step_check_write_value)) {
+ pr_err("STEP test failed: Overrite value: %d, expect value %d origin %d mask %d",
+ value,
+ g_conninfra_step_test_check.step_check_write_value,
+ g_conninfra_step_test_check.step_recovery_value,
+ mask);
+ g_conninfra_step_test_check.step_check_result = TEST_FAIL;
+ } else if ((~mask & value) != (~mask & g_conninfra_step_test_check.step_recovery_value)) {
+ pr_err("STEP test failed: No change value: %d, expect value %d origin %d mask %d",
+ value,
+ g_conninfra_step_test_check.step_check_write_value,
+ g_conninfra_step_test_check.step_recovery_value,
+ mask);
+ g_conninfra_step_test_check.step_check_result = TEST_FAIL;
+ } else {
+ g_conninfra_step_test_check.step_check_result = TEST_PASS;
+ }
+ }
+
+ va_end(args);
+}
+
+void conninfra_step_test_check_show_act(unsigned int len, ...)
+{
+ char *content;
+ va_list args;
+
+ va_start(args, len);
+ content = va_arg(args, char*);
+ if (content == NULL || g_conninfra_step_test_check.step_check_result_string == NULL) {
+ pr_err("STEP test failed: content is NULL");
+ g_conninfra_step_test_check.step_check_result = TEST_FAIL;
+ }
+ if (content != NULL && g_conninfra_step_test_check.step_check_result_string != NULL &&
+ osal_strcmp(content, g_conninfra_step_test_check.step_check_result_string) == 0) {
+ g_conninfra_step_test_check.step_check_result = TEST_PASS;
+ } else {
+ pr_err("STEP test failed: content(%s), expect(%s)",
+ content, g_conninfra_step_test_check.step_check_result_string);
+ g_conninfra_step_test_check.step_check_result = TEST_FAIL;
+ }
+ va_end(args);
+}
+
+void conninfra_step_test_check_condition(unsigned int len, ...)
+{
+ int value;
+ va_list args;
+
+ va_start(args, len);
+ value = va_arg(args, int);
+ if (value == g_conninfra_step_test_check.step_check_result_value) {
+ g_conninfra_step_test_check.step_check_result = TEST_PASS;
+ } else {
+ pr_err("STEP test failed: value(%d), expect(%d)",
+ value, g_conninfra_step_test_check.step_check_result_value);
+ g_conninfra_step_test_check.step_check_result = TEST_FAIL;
+ }
+ va_end(args);
+}
+
+void conninfra_step_test_check_value_act(unsigned int len, ...)
+{
+ int value;
+ va_list args;
+
+ va_start(args, len);
+ value = va_arg(args, int);
+ if (value == g_conninfra_step_test_check.step_check_result_value) {
+ g_conninfra_step_test_check.step_check_result = TEST_PASS;
+ } else {
+ pr_err("STEP test failed: value(%d), expect(%d)",
+ value, g_conninfra_step_test_check.step_check_result_value);
+ g_conninfra_step_test_check.step_check_result = TEST_FAIL;
+ }
+ va_end(args);
+}
+
+void conninfra_step_test_clear_check_data(void)
+{
+ unsigned int i = 0, j = 0;
+
+ for (i = 0; i < STEP_TEST_ACTION_NUMBER; i++) {
+ g_conninfra_step_test_check.step_check_test_tp_id[i] = 0;
+ g_conninfra_step_test_check.step_check_test_act_id[i] = 0;
+ g_conninfra_step_test_check.step_check_params_num[i] = 0;
+ g_conninfra_step_test_check.step_check_emi_offset[i] = 0;
+ for (j = 0; j < STEP_PARAMETER_SIZE; j++)
+ g_conninfra_step_test_check.step_check_params[i][j] = "";
+ }
+
+ g_conninfra_step_test_check.step_check_total = 0;
+ g_conninfra_step_test_check.step_check_index = 0;
+ g_conninfra_step_test_check.step_check_result = TEST_PASS;
+ g_conninfra_step_test_check.step_check_register_addr = 0;
+ g_conninfra_step_test_check.step_test_mask = 0xFFFFFFFF;
+ g_conninfra_step_test_check.step_recovery_value = 0;
+ g_conninfra_step_test_check.step_check_result_value = 0;
+ g_conninfra_step_test_check.step_check_temp_register_id = -1;
+
+ g_conninfra_step_test_check.cur_test_scn = NULL;
+}
+
+void conninfra_step_test_clear_temp_register(void)
+{
+ int i;
+
+ for (i = 0; i < STEP_TEMP_REGISTER_SIZE; i++)
+ g_infra_step_env.temp_register[i] = 0;
+}
+
+#if 0
+void __conninfra_step_test_parse_data(const char *buf, struct step_test_report *p_report, char *err_result)
+{
+ conninfra_step_parse_data(buf, osal_strlen((char *)buf), conninfra_step_test_check_write_tp);
+ if (g_conninfra_step_test_check.step_check_total != g_conninfra_step_test_check.step_check_index) {
+ pr_err("STEP test failed: index %d: expect total %d\n", g_conninfra_step_test_check.step_check_index,
+ g_conninfra_step_test_check.step_check_total);
+ g_conninfra_step_test_check.step_check_result = TEST_FAIL;
+ }
+ conninfra_step_test_update_result(g_conninfra_step_test_check.step_check_result, p_report, err_result);
+}
+#endif
+
+void __conninfra_step_test_do_emi_action(enum step_action_id act_id, int param_num, char *params[], int result_of_action,
+ struct step_test_report *p_report, char *err_result)
+{
+ struct step_action *p_act = NULL;
+
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ if (conninfra_step_do_emi_action(p_act, conninfra_step_test_check_emi_act) ==
+ result_of_action) {
+ if (g_conninfra_step_test_check.step_check_total != g_conninfra_step_test_check.step_check_index) {
+ p_report->fail++;
+ pr_err("%s, index %d: expect total %d\n", err_result,
+ g_conninfra_step_test_check.step_check_index, g_conninfra_step_test_check.step_check_total);
+ } else if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ p_report->pass++;
+ } else {
+ p_report->fail++;
+ pr_err("%s\n", err_result);
+ }
+ } else {
+ pr_err("%s, expect result is %d\n", err_result, result_of_action);
+ p_report->fail++;
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ if (result_of_action == -1) {
+ p_report->pass++;
+ } else {
+ p_report->fail++;
+ pr_err("%s, Create failed\n", err_result);
+ }
+ }
+}
+
+void __conninfra_step_test_do_cond_emi_action(enum step_action_id act_id, int param_num, char *params[], int result_of_action,
+ struct step_test_report *p_report, char *err_result)
+{
+ struct step_action *p_act = NULL;
+
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ if (conninfra_step_do_condition_emi_action(p_act, conninfra_step_test_check_emi_act) ==
+ result_of_action) {
+ if (g_conninfra_step_test_check.step_check_total != g_conninfra_step_test_check.step_check_index) {
+ p_report->fail++;
+ pr_err("%s, index %d: expect total %d\n", err_result,
+ g_conninfra_step_test_check.step_check_index, g_conninfra_step_test_check.step_check_total);
+ } else if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ p_report->pass++;
+ } else {
+ p_report->fail++;
+ pr_err("%s\n", err_result);
+ }
+ } else {
+ pr_err("%s, expect result is %d\n", err_result, result_of_action);
+ p_report->fail++;
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ if (result_of_action == -1) {
+ p_report->pass++;
+ } else {
+ p_report->fail++;
+ pr_err("%s, Create failed\n", err_result);
+ }
+ }
+}
+
+void __conninfra_step_test_do_register_action(enum step_action_id act_id, int param_num, char *params[], int result_of_action,
+ struct step_test_report *p_report, char *err_result)
+{
+ struct step_action *p_act = NULL;
+ int result;
+
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ if (osal_strcmp(params[0], "1") == 0) {
+ /* Write register test */
+ if (g_conninfra_step_test_check.step_check_register_addr != 0) {
+ g_conninfra_step_test_check.step_recovery_value =
+ CONSYS_REG_READ(g_conninfra_step_test_check.step_check_register_addr);
+ }
+ result = conninfra_step_do_register_action(p_act, conninfra_step_test_check_reg_write_act);
+ if (result == result_of_action) {
+ if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ p_report->pass++;
+ } else {
+ p_report->fail++;
+ pr_err("%s\n", err_result);
+ }
+ } else if (result == -2) {
+ p_report->check++;
+ pr_info("STEP check: %s, no clock is ok?\n", err_result);
+ } else {
+ pr_err("%s, expect result is %d\n", err_result,
+ result_of_action);
+ p_report->fail++;
+ }
+ if (g_conninfra_step_test_check.step_check_register_addr != 0) {
+ CONSYS_REG_WRITE(g_conninfra_step_test_check.step_check_register_addr,
+ g_conninfra_step_test_check.step_recovery_value);
+ }
+ } else {
+ /* Read register test */
+ g_conninfra_step_test_check.step_check_result = TEST_PASS;
+ result = conninfra_step_do_register_action(p_act, conninfra_step_test_check_reg_read_act);
+ if (result == result_of_action) {
+ if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ p_report->pass++;
+ } else {
+ p_report->fail++;
+ pr_err("%s\n", err_result);
+ }
+ } else if (result == -2) {
+ p_report->check++;
+ pr_info("STEP check: %s, no clock is ok?\n", err_result);
+ } else {
+ pr_err("%s, expect result is %d\n", err_result,
+ result_of_action);
+ p_report->fail++;
+ }
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ if (result_of_action == -1) {
+ p_report->pass++;
+ } else {
+ p_report->fail++;
+ pr_err("%s, Create failed\n", err_result);
+ }
+ }
+}
+
+void __conninfra_step_test_do_cond_register_action(enum step_action_id act_id, int param_num,
+ char *params[], int result_of_action,
+ struct step_test_report *p_report, char *err_result)
+{
+ struct step_action *p_act = NULL;
+ int result;
+
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ pr_info("[%s] == ", __func__);
+ if (p_act != NULL) {
+ if (osal_strcmp(params[1], "1") == 0) {
+ /* Write register test */
+ if (g_conninfra_step_test_check.step_check_register_addr != 0) {
+ g_conninfra_step_test_check.step_recovery_value =
+ CONSYS_REG_READ(g_conninfra_step_test_check.step_check_register_addr);
+ }
+
+ result = conninfra_step_do_condition_register_action(p_act, conninfra_step_test_check_reg_write_act);
+ if (result == result_of_action) {
+ if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ p_report->pass++;
+ } else {
+ p_report->fail++;
+ pr_err("%s\n", err_result);
+ }
+ } else if (result == -2) {
+ p_report->check++;
+ pr_info("STEP check: %s, no clock is ok?\n", err_result);
+ } else {
+ pr_err("%s, expect result is %d\n", err_result, result_of_action);
+ p_report->fail++;
+ }
+ if (g_conninfra_step_test_check.step_check_register_addr != 0) {
+ CONSYS_REG_WRITE(g_conninfra_step_test_check.step_check_register_addr,
+ g_conninfra_step_test_check.step_recovery_value);
+ }
+ } else {
+ pr_info("[%s] == read register test ", __func__);
+ /* Read register test */
+ g_conninfra_step_test_check.step_check_result = TEST_PASS;
+ result = conninfra_step_do_condition_register_action(p_act, conninfra_step_test_check_reg_read_act);
+ if (result == result_of_action) {
+ if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ p_report->pass++;
+ } else {
+ p_report->fail++;
+ pr_err("%s\n", err_result);
+ }
+ } else if (result == -2) {
+ p_report->check++;
+ pr_info("STEP check: %s, no clock is ok?\n", err_result);
+ } else {
+ pr_err("%s, expect result is %d\n", err_result, result_of_action);
+ p_report->fail++;
+ }
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ if (result_of_action == -1) {
+ p_report->pass++;
+ } else {
+ p_report->fail++;
+ pr_err("%s, Create failed\n", err_result);
+ }
+ }
+}
+
+void conninfra_step_test_all(void)
+{
+ struct step_test_report report = {0, 0, 0};
+ //bool is_enable_step = g_infra_step_env.is_enable;
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+
+ conninfra_step_init();
+
+ report.pass = 0;
+ report.fail = 0;
+ report.check = 0;
+
+ pr_info("STEP test: All start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ g_infra_step_env.is_enable = 0;
+
+ conninfra_step_test_read_file(&report);
+
+ //conninfra_step_test_parse_data3(&report);
+
+ conninfra_step_test_parse_data1(&report);
+ conninfra_step_test_parse_data2(&report);
+
+ g_infra_step_env.is_enable = 1;
+ conninfra_step_test_create_emi_action(&report);
+ conninfra_step_test_create_cond_emi_action(&report);
+ conninfra_step_test_create_register_action(&report);
+ conninfra_step_test_create_cond_register_action(&report);
+ conninfra_step_test_check_register_symbol(&report);
+ conninfra_step_test_create_other_action(&report);
+ //conninfra_step_test_parse_data(&report);
+
+ if (true) {
+ conninfra_step_test_do_emi_action(&report);
+ conninfra_step_test_do_cond_emi_action(&report);
+ }
+
+ /* NOT test yet */
+ conninfra_step_test_do_register_action(&report);
+ /* NOT test yet */
+ conninfra_step_test_do_cond_register_action(&report);
+
+ conninfra_step_test_do_gpio_action(&report);
+ //wmt_step_test_do_wakeup_action(&report);
+ conninfra_step_test_create_periodic_dump(&report);
+ conninfra_step_test_do_show_action(&report);
+ conninfra_step_test_do_sleep_action(&report);
+ conninfra_step_test_do_condition_action(&report);
+ conninfra_step_test_do_value_action(&report);
+
+ //conninfra_step_test_do_chip_reset_action(&report);
+ //g_infra_step_env.is_enable = is_enable_step;
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: All result",
+ &report, sec_begin, usec_begin, sec_end, usec_end);
+
+ conninfra_step_deinit();
+}
+
+void conninfra_step_test_read_file(struct step_test_report *p_report)
+{
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+
+ pr_info("STEP test: Read file start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ /********************************
+ ******** Test case 1 ***********
+ ******* Wrong file name ********
+ ********************************/
+ if (-1 == conninfra_step_read_file("conninfra_wrong_file.cfg")) {
+ temp_report.pass++;
+ } else {
+ pr_err("STEP test failed: (Read file TC-1) expect no file\n");
+ temp_report.fail++;
+ }
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Read file result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+
+
+char *parse_data_buf_tc1 =
+ "// TEST NOW\r\n"
+ "\r\n"
+ "[TP CONNINFRA 1] Before Chip reset\r\n"
+ "[AT] _EMI 0 0x50 0x9c\r\n"
+ "[AT] _REG 0 0x08 5 2\r\n"
+ "[TP CONNINFRA 2] After Chip reset\r\n"
+ "[AT] _REG 1 0x08 30\r\n"
+ "[AT] GPIO 0 8\r\n"
+ "[AT] GPIO 1 6 3\r\n"
+ "[AT] _REG 1 0x08 30 0xFF00FF00\r\n"
+ "[TP CONNINFRA 3] Before read consys thermal\r\n"
+ "[AT] SHOW Hello_World\r\n"
+ "[AT] _SLP 1000\r\n"
+ "[AT] COND $1 $2 == $3\r\n"
+ "[AT] COND $1 $2 == 16\r\n"
+ "[AT] _VAL $0 0x66\r\n"
+ "[TP CONNINFRA 4] Power on sequence(0): Start power on\r\n"
+ "[AT] _EMI 0 0x50 0xFFFFFFFF $1\r\n"
+ "[AT] _REG 0 0x08 0xFFFFFFFF $1\r\n"
+ "[AT] CEMI $2 0 0x50 0xFFFFFFFF $1\r\n"
+ "[AT] CREG $2 0 0x08 0xFFFFFFFF $1\r\n"
+ "[TP WF 1] Command Timeout\r\n"
+ "[AT] _EMI 0 0x50 0xFFFFFFFF $1\r\n"
+ "[TP WF 2] Before Chip reset\r\n"
+ "[AT] _EMI 0 0x50 0xFFFFFFFF $1\r\n"
+ "[TP BT 1] Command Timeout\r\n"
+ "[AT] _EMI 0 0x50 0xFFFFFFFF $1\r\n"
+ "[TP BT 2] Before Chip reset\r\n"
+ "[AT] _EMI 0 0x50 0xFFFFFFFF $1\r\n"
+ "[TP GPS 1] Command timeout\r\n"
+ "[AT] _EMI 0 0x50 0xFFFFFFFF $1\r\n"
+ "[TP GPS 2] Before Chip reset\r\n"
+ "[AT] _EMI 0 0x50 0xFFFFFFFF $1\r\n"
+ "[TP FM 1] Command timeout\r\n"
+ "[AT] _EMI 0 0x50 0xFFFFFFFF $1\r\n"
+ "[TP FM 2] Before Chip reset\r\n"
+ "[AT] _EMI 0 0x50 0xFFFFFFFF $1\r\n"
+ "\r\n";
+
+
+struct step_test_scenario parse_data_buf_scn1 = {
+ "// TC1\r\n", 0, 23,
+ { /* array */
+ /* ----------------------------------------------------------------------- */
+ /* [TP CONNINFRA 1] */
+ /* tp_id, act_id */
+ /* params */
+ { STEP_CONNINFRA_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_EMI,
+ 3, {"0", "0x50", "0x9c"} },
+ { STEP_CONNINFRA_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_REGISTER,
+ 4, {"0", "0x08", "5", "2"} },
+ /* [TP CONNINFRA 2] */
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_REGISTER,
+ 3, {"1", "0x08", "30"}},
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_GPIO,
+ 2, {"0", "8"}},
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_GPIO,
+ 3, {"1", "6", "3"}},
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_REGISTER,
+ 4, {"1", "0x08", "30", "0xFF00FF00"}},
+ /* [TP CONNINFRA 3] */
+ { STEP_CONNINFRA_TP_BEFORE_READ_THERMAL, STEP_ACTION_INDEX_SHOW_STRING,
+ 1, {"Hello_World"}},
+ { STEP_CONNINFRA_TP_BEFORE_READ_THERMAL, STEP_ACTION_INDEX_SLEEP,
+ 1, {"1000"}},
+ { STEP_CONNINFRA_TP_BEFORE_READ_THERMAL, STEP_ACTION_INDEX_CONDITION,
+ 4, {"$1", "$2", "==", "$3"}},
+ { STEP_CONNINFRA_TP_BEFORE_READ_THERMAL, STEP_ACTION_INDEX_CONDITION,
+ 4, {"$1", "$2", "==", "16"}},
+ { STEP_CONNINFRA_TP_BEFORE_READ_THERMAL, STEP_ACTION_INDEX_VALUE,
+ 2, {"$0", "0x66"}},
+ /* [TP CONNINFRA 4] */
+ { STEP_CONNINFRA_TP_POWER_ON_START, STEP_ACTION_INDEX_EMI,
+ 4, {"0", "0x50", "0xFFFFFFFF", "$1"}},
+ { STEP_CONNINFRA_TP_POWER_ON_START, STEP_ACTION_INDEX_REGISTER,
+ 4, {"0", "0x08", "0xFFFFFFFF", "$1"}},
+ { STEP_CONNINFRA_TP_POWER_ON_START, STEP_ACTION_INDEX_CONDITION_EMI,
+ 5, {"$2", "0", "0x50", "0xFFFFFFFF", "$1"}},
+ { STEP_CONNINFRA_TP_POWER_ON_START, STEP_ACTION_INDEX_CONDITION_REGISTER,
+ 5, {"$2", "0", "0x08", "0xFFFFFFFF", "$1"}},
+ /* ----------------------------------------------------------------------- */
+ /* [TP WF 1] */
+ { STEP_WF_TP_COMMAND_TIMEOUT, STEP_ACTION_INDEX_EMI,
+ 4, {"0", "0x50", "0xFFFFFFFF", "$1"}},
+ /* [TP WF 2] */
+ { STEP_WF_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_EMI,
+ 4, {"0", "0x50", "0xFFFFFFFF", "$1"}},
+ /* ----------------------------------------------------------------------- */
+ /* [TP BT 1] */
+ { STEP_BT_TP_COMMAND_TIMEOUT, STEP_ACTION_INDEX_EMI,
+ 4, {"0", "0x50", "0xFFFFFFFF", "$1"}},
+ /* [TP BT 2] */
+ { STEP_BT_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_EMI,
+ 4, {"0", "0x50", "0xFFFFFFFF", "$1"}},
+ /* ----------------------------------------------------------------------- */
+ /* [TP GPS 1] */
+ { STEP_GPS_TP_COMMAND_TIMEOUT, STEP_ACTION_INDEX_EMI,
+ 4, {"0", "0x50", "0xFFFFFFFF", "$1"}},
+ /* [TP GPS 2] */
+ { STEP_GPS_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_EMI,
+ 4, {"0", "0x50", "0xFFFFFFFF", "$1"}},
+ /* ----------------------------------------------------------------------- */
+ /* [TP FM 1] */
+ { STEP_FM_TP_COMMAND_TIMEOUT, STEP_ACTION_INDEX_EMI,
+ 4, {"0", "0x50", "0xFFFFFFFF", "$1"}},
+ /* [TP FM 2] */
+ { STEP_FM_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_EMI,
+ 4, {"0", "0x50", "0xFFFFFFFF", "$1"}},
+ }
+};
+
+static void conninfra_step_test_parse_data_tc1(struct step_test_report *temp_report)
+{
+ int i;
+
+ for (i = parse_data_buf_scn1.total_test_sz; i < STEP_TEST_ACTION_NUMBER; i++)
+ parse_data_buf_scn1.pt_acts[i].tp_id = -1;
+ parse_data_buf_scn1.test_idx = 0;
+
+ g_conninfra_step_test_check.cur_test_scn = &parse_data_buf_scn1;
+ __conninfra_step_test_parse_data2(parse_data_buf_tc1, temp_report,
+ "STEP test case failed: (Parse data TC-1) Normal case\n");
+
+}
+
+const char *parse_data_buf_tc2 =
+ "// TEST NOW\r\n"
+ "\r\n"
+ "[TP CONNINFRA 1] Before Chip reset\r\n"
+ "[AT] _EMI 0 0x50 0x9c \r\n"
+ "[AT] _REG 0 0x08 5 2\r\n"
+ " [PD+] 2\r\n"
+ " [AT] _EMI 0 0x50 0x9c\r\n"
+ " [PD-] \r\n"
+ " [TP CONNINFRA 2] After Chip reset\r\n"
+ "[AT] _REG 1 0x08 30\r\n"
+ "[AT] GPIO 0 8\r\n"
+ " [AT] GPIO 1 6 3\r\n"
+ " [PD+] 5\r\n"
+ " [AT] _EMI 0 0x50 0x9c\r\n"
+ " [PD-] \r\n"
+ "[TP CONNINFRA 3] Before read consys thermal\r\n"
+ " [AT] SHOW Hello\r\n"
+ "[AT] _SLP 1000\r\n"
+ " [AT] COND $1 $2 == $3\r\n"
+ " [AT] _VAL $0 0x66\r\n"
+ "[TP CONNINFRA 4] Power on sequence(0): Start power on\r\n"
+ "[AT] CEMI $2 0 0x50 0xFFFFFFFF $1\r\n"
+ " [AT] CREG $2 0 0x08 0xFFFFFFFF $1\r\n"
+ "\r\n";
+
+struct step_test_scenario parse_data_buf_scn_tc2 = {
+ "// TC1\r\n", 0, 15,
+ { /* array */
+ /* struct step_test_scn_tp_act */
+ /* tp_id, act_id */
+ /* [TP 1] */
+ /* params */
+ { STEP_CONNINFRA_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_EMI,
+ 3, {"0", "0x50", "0x9c"}},
+ { STEP_CONNINFRA_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_REGISTER,
+ 4, {"0", "0x08", "5", "2"}},
+ { -1, STEP_ACTION_INDEX_EMI,
+ 3, {"0", "0x50", "0x9c"}},
+ { STEP_CONNINFRA_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_PERIODIC_DUMP,
+ 0, {}},
+ /* [TP 2] */
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_REGISTER,
+ 3, {"1", "0x08", "30"}},
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_GPIO,
+ 2, {"0", "8"}},
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_GPIO,
+ 3, {"1", "6", "3"}},
+ { -1, STEP_ACTION_INDEX_EMI,
+ 3, {"0", "0x50", "0x9c"}},
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_PERIODIC_DUMP,
+ 0, {}
+ },
+ /* [TP 3] */
+ { STEP_CONNINFRA_TP_BEFORE_READ_THERMAL, STEP_ACTION_INDEX_SHOW_STRING,
+ 1, {"Hello"}
+ },
+ { STEP_CONNINFRA_TP_BEFORE_READ_THERMAL, STEP_ACTION_INDEX_SLEEP,
+ 1, {"1000"}
+ },
+ { STEP_CONNINFRA_TP_BEFORE_READ_THERMAL, STEP_ACTION_INDEX_CONDITION,
+ 4, {"$1", "$2", "==", "$3"}
+ },
+ { STEP_CONNINFRA_TP_BEFORE_READ_THERMAL, STEP_ACTION_INDEX_VALUE,
+ 2, {"$0", "0x66"}
+ },
+ /* [TP 4] */
+ { STEP_CONNINFRA_TP_POWER_ON_START, STEP_ACTION_INDEX_CONDITION_EMI,
+ 5, {"$2", "0", "0x50", "0xFFFFFFFF", "$1"}
+ },
+ { STEP_CONNINFRA_TP_POWER_ON_START, STEP_ACTION_INDEX_CONDITION_REGISTER,
+ 5, {"$2", "0", "0x08", "0xFFFFFFFF", "$1"}
+ },
+ }
+};
+
+static void conninfra_step_test_parse_data_tc2(struct step_test_report *temp_report)
+{
+ int i;
+
+ for (i = parse_data_buf_scn_tc2.total_test_sz; i < STEP_TEST_ACTION_NUMBER; i++)
+ parse_data_buf_scn_tc2.pt_acts[i].tp_id = -1;
+ parse_data_buf_scn_tc2.test_idx = 0;
+
+ g_conninfra_step_test_check.cur_test_scn = &parse_data_buf_scn_tc2;
+ __conninfra_step_test_parse_data2(parse_data_buf_tc2, temp_report,
+ "STEP test case failed: (Parse data TC-2) Normal case with some space\n");
+}
+
+char* parse_data_buf_tc3 =
+ "// TEST NOW\r\n"
+ "\r\n"
+ "[TP CONNINFRA 1] Before Chip reset\r\n"
+ "[AT] _EMI 0x50 0x9c\r\n"
+ "[AT] _REG 0 5 2\r\n"
+ "[TP CONNINFRA 2] After Chip reset\r\n"
+ "[AT] _REG 1 0x08\r\n"
+ "[AT] GPIO 0\r\n"
+ "[AT] GPIO 6 3\r\n"
+ "[TP CONNINFRA 3] Before read consys thermal\r\n"
+ "[AT] SHOW\r\n"
+ "[AT] _SLP\r\n"
+ "[AT] COND $1 $2 >\r\n"
+ "[AT] _VAL 0x66\r\n"
+ "\r\n";
+
+struct step_test_scenario parse_data_scn_tc3 = {
+ "// TC3 \r\n", 0, 9,
+ { /* array */
+ /* struct step_test_scn_tp_act */
+ /* tp_id */
+ /* [TP 1] */
+ /* act_id, params */
+ { STEP_CONNINFRA_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_EMI,
+ 2, {"0x50", "0x9c"}},
+ { STEP_CONNINFRA_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_REGISTER,
+ 3, {"0", "5", "2"}},
+ /* [TP 2] */
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_REGISTER,
+ 2, {"1", "0x08"}},
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_GPIO,
+ 1, {"0"}},
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_GPIO,
+ 2, {"6", "3"}},
+ /* [TP 3] */
+ { STEP_CONNINFRA_TP_BEFORE_READ_THERMAL, STEP_ACTION_INDEX_SHOW_STRING,
+ 0, {}},
+ { STEP_CONNINFRA_TP_BEFORE_READ_THERMAL, STEP_ACTION_INDEX_SLEEP,
+ 0, {}},
+ { STEP_CONNINFRA_TP_BEFORE_READ_THERMAL, STEP_ACTION_INDEX_CONDITION,
+ 3, {"$1", "$2", ">"}},
+ { STEP_CONNINFRA_TP_BEFORE_READ_THERMAL, STEP_ACTION_INDEX_VALUE,
+ 1, {"0x66"}},
+ }
+};
+
+static void conninfra_step_test_parse_data_tc3(struct step_test_report *temp_report)
+{
+ int i;
+
+ for (i = parse_data_scn_tc3.total_test_sz; i < STEP_TEST_ACTION_NUMBER; i++)
+ parse_data_scn_tc3.pt_acts[i].tp_id = -1;
+ parse_data_scn_tc3.test_idx = 0;
+
+ g_conninfra_step_test_check.cur_test_scn = &parse_data_scn_tc3;
+
+ __conninfra_step_test_parse_data2(parse_data_buf_tc3, temp_report,
+ "STEP test case failed: (Parse data TC-3) Not enough parameter\n");
+
+
+}
+
+static char *parse_data_buf_tc4 =
+ "// TEST NOW\r\n"
+ "\r\n"
+ "[Tp COnnINFRA 1] Before Chip reset\r\n"
+ "[aT] _emi 0 0x50 0x9c\r\n"
+ "[At] _reg 0 0x08 5 2\r\n"
+ "[tP CONNinfra 2] After Chip reset\r\n"
+ "[at] _reg 1 0x08 30\r\n"
+ "[at] gpio 0 8\r\n"
+ "[AT] gpio 1 6 3\r\n"
+ "[AT] _reg 1 0x08 30 0xFF00FF00\r\n"
+ "[pd+] 5\r\n"
+ "[At] gpio 0 8\r\n"
+ "[pd-]\r\n"
+ "[tp conninfra 3] Before read consys thermal\r\n"
+ "[AT] show Hello_World\r\n"
+ "[AT] _slp 1000\r\n"
+ "[AT] cond $1 $2 == $3\r\n"
+ "[AT] _val $0 0x66\r\n"
+ "[TP CONNINFRA 4] Power on sequence(0): Start power on\r\n"
+ "[AT] cemi $2 0 0x50 0xFFFFFFFF $1\r\n"
+ "[at] creg $2 0 0x08 0xffffffff $1\r\n"
+ "[TP wf 1] Command timeout\r\n"
+ "[AT] _EMI 0 0x50 0xFFFFFFFF $1\r\n"
+ "[tp WF 2] Before Chip reset\r\n"
+ "[AT] _EMI 0 0x50 0xFFFFFFFF $1\r\n"
+ "\r\n";
+
+static struct step_test_scenario parse_data_scn_tc4 = {
+ "// TC4 \r\n", 0, 16,
+ { /* array */
+ /* struct step_test_scn_tp_act */
+ /* tp_id */
+ /* act_id, params */
+ { STEP_CONNINFRA_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_EMI,
+ 3, {"0", "0x50", "0x9c"}},
+ { STEP_CONNINFRA_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_REGISTER,
+ 4, {"0", "0x08", "5", "2"}},
+ /* [TP 2] */
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_REGISTER,
+ 3, {"1", "0x08", "30"}},
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_GPIO,
+ 2, {"0", "8"}},
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_GPIO,
+ 3, {"1", "6", "3"}},
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_REGISTER,
+ 4, {"1", "0x08", "30", "0xFF00FF00"}},
+ { -1, STEP_ACTION_INDEX_GPIO,
+ 2, {"0", "8"}},
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_PERIODIC_DUMP,
+ 0, {}},
+ /* [TP 3] */
+ { STEP_CONNINFRA_TP_BEFORE_READ_THERMAL, STEP_ACTION_INDEX_SHOW_STRING,
+ 1, {"Hello_World"}},
+ { STEP_CONNINFRA_TP_BEFORE_READ_THERMAL, STEP_ACTION_INDEX_SLEEP,
+ 1, {"1000"}},
+ { STEP_CONNINFRA_TP_BEFORE_READ_THERMAL, STEP_ACTION_INDEX_CONDITION,
+ 4, {"$1", "$2", "==", "$3"}},
+ { STEP_CONNINFRA_TP_BEFORE_READ_THERMAL, STEP_ACTION_INDEX_VALUE,
+ 2, {"$0", "0x66"}},
+ /* [TP 4] */
+ { STEP_CONNINFRA_TP_POWER_ON_START, STEP_ACTION_INDEX_CONDITION_EMI,
+ 5, {"$2", "0", "0x50", "0xFFFFFFFF", "$1"}},
+ { STEP_CONNINFRA_TP_POWER_ON_START, STEP_ACTION_INDEX_CONDITION_REGISTER,
+ 5, {"$2", "0", "0x08", "0xffffffff", "$1"}},
+ /* ----------------------------------------------------------------------- */
+ /* [TP WF 1] */
+ { STEP_WF_TP_COMMAND_TIMEOUT, STEP_ACTION_INDEX_EMI,
+ 4, {"0", "0x50", "0xFFFFFFFF", "$1"}},
+ /* [TP WF 2] */
+ { STEP_WF_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_EMI,
+ 4, {"0", "0x50", "0xFFFFFFFF", "$1"}},
+
+ }
+};
+
+static void conninfra_step_test_parse_data_tc4(struct step_test_report *temp_report)
+{
+ int i;
+
+ for (i = parse_data_scn_tc4.total_test_sz; i < STEP_TEST_ACTION_NUMBER; i++)
+ parse_data_scn_tc4.pt_acts[i].tp_id = -1;
+ parse_data_scn_tc4.test_idx = 0;
+
+ g_conninfra_step_test_check.cur_test_scn = &parse_data_scn_tc4;
+ __conninfra_step_test_parse_data2(parse_data_buf_tc4, temp_report,
+ "STEP test case failed: (Parse data TC-4) Upcase and lowercase\n");
+}
+
+char *parse_data_buf_tc5 =
+ "// TEST NOW\r\n"
+ "\r\n"
+ "[TP CONNINFRA 2] After Chip reset\r\n"
+ "[AT] _REG 1 0x08 30\r\n"
+ "[AT] GPIO 0 8\r\n"
+ "[AT] GPIO 1 6 3\r\n"
+ "[tp conninfra 3] Before read consys thermal\r\n"
+ "[TP CONNINFRA 1] Before Chip reset\r\n"
+ "[AT] _EMI 0 0x50 0x9c\r\n"
+ "[AT] _REG 0 0x08 5 2\r\n"
+ "\r\n";
+
+struct step_test_scenario parse_data_scn_tc5 = {
+ "// TC4 \r\n", 0, 5,
+ { /* array */
+ /* struct step_test_scn_tp_act */
+ /* tp_id */
+ /* act_id, params */
+ /* [TP 2] */
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_REGISTER,
+ 3, {"1", "0x08", "30"}
+ },
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_GPIO,
+ 2, {"0", "8"}
+ },
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_GPIO,
+ 3, {"1", "6", "3"}
+ },
+ { STEP_CONNINFRA_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_EMI,
+ 3, {"0", "0x50", "0x9c"}
+ },
+ { STEP_CONNINFRA_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_REGISTER,
+ 4, {"0", "0x08", "5", "2"}
+ },
+ }
+};
+
+static void conninfra_step_test_parse_data_tc5(struct step_test_report *temp_report)
+{
+ int i;
+
+ for (i = parse_data_scn_tc5.total_test_sz; i < STEP_TEST_ACTION_NUMBER; i++)
+ parse_data_scn_tc5.pt_acts[i].tp_id = -1;
+ parse_data_scn_tc5.test_idx = 0;
+
+ g_conninfra_step_test_check.cur_test_scn = &parse_data_scn_tc5;
+ __conninfra_step_test_parse_data2(parse_data_buf_tc5, temp_report,
+ "STEP test case failed: (Parse data TC-5) TP sequence switch\n");
+
+}
+
+char *parse_data_buf_tc6 =
+ "// TEST NOW\r\n"
+ "\r\n"
+ "[TP CONNINFRA 1] Before Chip reset\r\n"
+ "[AT] _EMI 0 0x50 0x9c // show emi 0x50~0x9c\r\n"
+ "// show cregister\r\n"
+ "[AT] _REG 0 0x08 5 2\r\n"
+ "// Do some action\r\n"
+ "[TP CONNINFRA 2] After Chip reset\r\n"
+ "[AT] _REG 1 0x08 30\r\n"
+ "[AT] GPIO 0 8\r\n"
+ "[AT] GPIO 1 6 3\r\n"
+ "[PD+] 5 // pd start\r\n"
+ "[AT] GPIO 0 8 // just do it\r\n"
+ "// Do some action\r\n"
+ "[PD-] // pd ned\r\n"
+ "\r\n";
+
+struct step_test_scenario parse_data_scn_tc6 = {
+ "// TC4 \r\n", 0, 7,
+ { /* array */
+ /* struct step_test_scn_tp_act */
+ /* tp_id */
+ /* act_id, params */
+ { STEP_CONNINFRA_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_EMI,
+ 3, {"0", "0x50", "0x9c"}},
+ { STEP_CONNINFRA_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_REGISTER,
+ 4, {"0", "0x08", "5", "2"}},
+ /* [TP 2] */
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_REGISTER,
+ 3, {"1", "0x08", "30"}},
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_GPIO,
+ 2, {"0", "8"}},
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_GPIO,
+ 3, {"1", "6", "3"}},
+ { -1, STEP_ACTION_INDEX_GPIO,
+ 2, {"0", "8"}},
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_PERIODIC_DUMP,
+ 0, {}},
+ }
+};
+
+static void conninfra_step_test_parse_data_tc6(struct step_test_report *temp_report)
+{
+ int i;
+
+ for (i = parse_data_scn_tc6.total_test_sz; i < STEP_TEST_ACTION_NUMBER; i++)
+ parse_data_scn_tc6.pt_acts[i].tp_id = -1;
+
+ parse_data_scn_tc6.test_idx = 0;
+ g_conninfra_step_test_check.cur_test_scn = &parse_data_scn_tc6;
+
+ __conninfra_step_test_parse_data2(parse_data_buf_tc6, temp_report,
+ "STEP test case failed: (Parse data TC-6) More comment\n");
+
+}
+
+char *parse_data_buf_tc7 =
+ "// TEST NOW\r\n"
+ "\r\n"
+ "[TP adfacdadf 1]When Command timeout\r\n"
+ "[AT] _EMI 0 0x50 0x9c\r\n"
+ "[TPCONNINFRA1] Before Chip reset\r\n"
+ "[TP-CONNINFRA-1] Before Chip reset\r\n"
+ "[T P 2] After Chip reset\r\n"
+ "[AT] _slp\r\n"
+ "[TP CONNINFRA 2 After Chip reset\r\n"
+ "[AT] _slp\r\n"
+ "[PD+]\r\n"
+ "[PD-]\r\n"
+ "[TP CONNINFRA 2] After Chip reset\r\n"
+ "[AT]_REG 1 0x08 30\r\n"
+ "[A T] GPIO 0 8\r\n"
+ "[ AT ] GPIO 1 6 3\r\n"
+ "AT GPIO 0 8\r\n"
+ "[AT WAK+\r\n"
+ "\r\n";
+
+struct step_test_scenario parse_data_scn_tc7 = {
+ "// TC7 \r\n", 0, 0,
+ {}
+};
+
+
+static void conninfra_step_test_parse_data_tc7(struct step_test_report *temp_report)
+{
+ int i;
+
+ for (i = parse_data_scn_tc7.total_test_sz; i < STEP_TEST_ACTION_NUMBER; i++)
+ parse_data_scn_tc7.pt_acts[i].tp_id = -1;
+
+ parse_data_scn_tc7.test_idx = 0;
+ g_conninfra_step_test_check.cur_test_scn = &parse_data_scn_tc7;
+
+ __conninfra_step_test_parse_data2(parse_data_buf_tc7, temp_report,
+ "STEP test case failed: (Parse data TC-7) Wrong format\n");
+
+}
+
+char *parse_data_buf_tc8 =
+ "// TEST NOW\r\n"
+ "\r\n"
+ "[TP CONNINFRA 1] Before Chip reset\r\n"
+ "[PD+] 5\r\n"
+ "[AT] _EMI 0 0x50 0x9c\r\n"
+ "[AT] _REG 0 0x08 5 2\r\n"
+ "[PD-]\r\n"
+ "[TP CONNINFRA 2] After Chip reset\r\n"
+ "[AT] _REG 1 0x08 30\r\n"
+ "[PD+] 3\r\n"
+ "[AT] GPIO 0 8\r\n"
+ "[PD-]\r\n"
+ "[AT] GPIO 1 6 3\r\n"
+ "\r\n";
+
+struct step_test_scenario parse_data_scn_tc8 = {
+ "// TC4 \r\n", 0, 7,
+ { /* array */
+ /* tp_id */
+ /* act_id, params */
+ { -1, STEP_ACTION_INDEX_EMI,
+ 3, {"0", "0x50", "0x9c"}},
+ { -1, STEP_ACTION_INDEX_REGISTER,
+ 4, {"0", "0x08", "5", "2"}},
+ { STEP_CONNINFRA_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_PERIODIC_DUMP,
+ 0, {}},
+ /* [TP 2] */
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_REGISTER,
+ 3, {"1", "0x08", "30"}},
+ { -1, STEP_ACTION_INDEX_GPIO,
+ 2, {"0", "8"}},
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_PERIODIC_DUMP,
+ 0, {}},
+ { STEP_CONNINFRA_TP_AFTER_CHIP_RESET, STEP_ACTION_INDEX_GPIO,
+ 3, {"1", "6", "3"}},
+ }
+};
+
+static void conninfra_step_test_parse_data_tc8(struct step_test_report *temp_report)
+{
+ int i;
+
+ for (i = parse_data_scn_tc8.total_test_sz; i < STEP_TEST_ACTION_NUMBER; i++)
+ parse_data_scn_tc8.pt_acts[i].tp_id = -1;
+
+ parse_data_scn_tc8.test_idx = 0;
+ g_conninfra_step_test_check.cur_test_scn = &parse_data_scn_tc8;
+
+ __conninfra_step_test_parse_data2(parse_data_buf_tc8, temp_report,
+ "STEP test case failed: (Parse data TC-8) Periodic dump\n");
+
+}
+
+char *parse_data_buf_tc9 =
+ "// TEST NOW\r\n"
+ "\r\n"
+ "[TP CONNINFRA 1] Before Chip reset\r\n"
+ "[AT] _EMI 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0x10 0x11 0x12 0x13\r\n"
+ "\r\n";
+
+struct step_test_scenario parse_data_scn_tc9 = {
+ "// TC4 \r\n", 0, 1,
+ { /* array */
+ /* struct step_test_scn_tp_act */
+ /* tp_id */
+ /* act_id, params */
+ { STEP_CONNINFRA_TP_BEFORE_CHIP_RESET, STEP_ACTION_INDEX_EMI,
+ 10, {"0x1", "0x2", "0x3", "0x4", "0x5", "0x6", "0x7", "0x8", "0x9", "0x10"}
+ },
+ }
+};
+
+static void conninfra_step_test_parse_data_tc9(struct step_test_report *temp_report)
+{
+ int i;
+
+ for (i = parse_data_scn_tc9.total_test_sz; i < STEP_TEST_ACTION_NUMBER; i++)
+ parse_data_scn_tc9.pt_acts[i].tp_id = -1;
+
+ parse_data_scn_tc9.test_idx = 0;
+ g_conninfra_step_test_check.cur_test_scn = &parse_data_scn_tc9;
+
+ __conninfra_step_test_parse_data2(parse_data_buf_tc9, temp_report,
+ "STEP test case failed: (Parse data TC-8) Periodic dump\n");
+
+}
+
+void conninfra_step_test_parse_data1(struct step_test_report *p_report)
+{
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+
+ pr_info("STEP test: Parse data start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ /********************************
+ ******** Test case 1 ***********
+ ******** Normal case ***********
+ ********************************/
+ pr_info("STEP test: TC 1\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_parse_data_tc1(&temp_report);
+
+ /*********************************
+ ******** Test case 2 ************
+ ** Normal case with some space **
+ *********************************/
+ pr_info("STEP test: TC 2\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_parse_data_tc2(&temp_report);
+
+ /***************************************************
+ ****************** Test case 3 ********************
+ ** Failed case not enough parameter (Can parser) **
+ ***************************************************/
+ pr_info("STEP test: TC 3\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_parse_data_tc3(&temp_report);
+
+ /***************************************************
+ ****************** Test case 4 ********************
+ ************** Upcase and lowercase ***************
+ ***************************************************/
+ pr_info("STEP test: TC 4\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_parse_data_tc4(&temp_report);
+
+ /*************************************************
+ ****************** Test case 5 ******************
+ ************** TP sequence switch ***************
+ *************************************************/
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Parse data result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+
+}
+void conninfra_step_test_parse_data2(struct step_test_report *p_report)
+{
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+
+ pr_info("STEP test: Parse data start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+
+ pr_info("STEP test: TC 5\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_parse_data_tc5(&temp_report);
+
+ /*********************************
+ ********* Test case 6 ***********
+ ********* More comment **********
+ *********************************/
+ pr_info("STEP test: TC 6\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_parse_data_tc6(&temp_report);
+
+ /*********************************
+ ********* Test case 7 ***********
+ ********* Wrong format **********
+ *********************************/
+ pr_info("STEP test: TC 7\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_parse_data_tc7(&temp_report);
+
+ /********************************
+ ******** Test case 8 ***********
+ ******* Periodic dump **********
+ ********************************/
+ pr_info("STEP test: TC 8\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_parse_data_tc8(&temp_report);
+
+ /*********************************
+ ******** Test case 9 ************
+ *** Boundary: Much parameter ****
+ *********************************/
+ pr_info("STEP test: TC 9\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_parse_data_tc9(&temp_report);
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Parse data result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+
+void conninfra_step_test_create_emi_action(struct step_test_report *p_report)
+{
+ enum step_action_id act_id;
+ char *params[STEP_PARAMETER_SIZE];
+ int check_params[STEP_PARAMETER_SIZE];
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+ int param_num = 0;
+
+ pr_info("STEP test: Create EMI action start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ act_id = STEP_ACTION_INDEX_EMI;
+
+ /*****************************
+ ******** Test case 1 ********
+ **** EMI create for read ****
+ *****************************/
+ pr_info("STEP test: TC 1\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ params[1] = "0x50";
+ params[2] = "0x9c";
+ param_num = 3;
+ check_params[0] = 0;
+ check_params[1] = 0x50;
+ check_params[2] = 0x9c;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-1) EMI create");
+
+ /************************************
+ ********** Test case 2 ************
+ **** EMI create fail less param ****
+ ************************************/
+ pr_info("STEP test: TC 2\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ params[1] = "0x50";
+ param_num = 2;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-2) EMI create fail");
+
+ /*************************************************
+ **************** Test case 3 *******************
+ ********** Save emi to temp register ************
+ *************************************************/
+ pr_info("STEP test: TC 3\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ params[1] = "0x50";
+ params[2] = "0x00000030";
+ params[3] = "$3";
+ param_num = 4;
+ check_params[0] = 0;
+ check_params[1] = 0x50;
+ check_params[2] = 0x00000030;
+ check_params[3] = 3;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-3) Save emi to temp register");
+
+ /*************************************************
+ **************** Test case 4 *******************
+ ** Boundary: Save emi to wrong temp register ****
+ *************************************************/
+ pr_info("STEP test: TC 4\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ params[1] = "0x50";
+ params[2] = "0x00000030";
+ params[3] = "$30";
+ param_num = 4;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-4) Boundary: Save emi to wrong temp register");
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Create EMI action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+
+void conninfra_step_test_create_cond_emi_action(struct step_test_report *p_report)
+{
+ enum step_action_id act_id;
+ char *params[STEP_PARAMETER_SIZE];
+ int check_params[STEP_PARAMETER_SIZE];
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+ int param_num = 0;
+
+ pr_info("STEP test: Create condition EMI action start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ act_id = STEP_ACTION_INDEX_CONDITION_EMI;
+
+ /*************************************************
+ **************** Test case 1 *******************
+ ************ Condition emi create ***************
+ *************************************************/
+ pr_info("STEP test: TC 1\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$1";
+ params[1] = "0";
+ params[2] = "0x50";
+ params[3] = "0x70";
+ param_num = 4;
+ check_params[0] = 1;
+ check_params[1] = 0;
+ check_params[2] = 0x50;
+ check_params[3] = 0x70;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-1) Condition emi create");
+
+ /*************************************************
+ **************** Test case 2 *******************
+ ****** Save condition emi to temp register ******
+ *************************************************/
+ pr_info("STEP test: TC 2\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$2";
+ params[1] = "0";
+ params[2] = "0x50";
+ params[3] = "0x00000030";
+ params[4] = "$3";
+ param_num = 5;
+ check_params[0] = 2;
+ check_params[1] = 0;
+ check_params[2] = 0x50;
+ check_params[3] = 0x00000030;
+ check_params[4] = 3;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-2) Save condition emi to temp register");
+
+ /***********************************************************
+ ******************** Test case 3 *************************
+ ** Boundary: Save condition emi to wrong temp register ****
+ ***********************************************************/
+ pr_info("STEP test: TC 3\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$1";
+ params[1] = "0";
+ params[2] = "0x50";
+ params[3] = "0x00000030";
+ params[4] = "$30";
+ param_num = 5;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-3) Boundary: Boundary: Save condition emi to wrong temp register");
+
+ /***********************************************************
+ ******************** Test case 4 *************************
+ ** Boundary: Save condition emi is wrong temp register ****
+ ***********************************************************/
+ pr_info("STEP test: TC 4\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$30";
+ params[1] = "0";
+ params[2] = "0x50";
+ params[3] = "0x00000030";
+ params[4] = "$1";
+ param_num = 5;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-4) Boundary: Boundary: Save condition emi is wrong temp register");
+
+ /*************************************************
+ **************** Test case 5 *******************
+ ******* Condition emi create less params ********
+ *************************************************/
+ pr_info("STEP test: TC 5\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$1";
+ params[1] = "0";
+ params[2] = "0x50";
+ param_num = 3;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-5) Condition emi create less params");
+
+ /*************************************************
+ **************** Test case 6 *******************
+ ******* Condition emi create wrong symbol *******
+ *************************************************/
+ pr_info("STEP test: TC 6\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "1";
+ params[1] = "0";
+ params[2] = "0x50";
+ params[3] = "0x00000030";
+ params[4] = "$1";
+ param_num = 5;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-6) Condition emi create wrong symbol");
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Create condition EMI action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+
+void conninfra_step_test_create_register_action(struct step_test_report *p_report)
+{
+ enum step_action_id act_id;
+ char *params[STEP_PARAMETER_SIZE];
+ int check_params[STEP_PARAMETER_SIZE];
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+ int param_num = 0;
+
+ pr_info("STEP test: Create Register action start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ act_id = STEP_ACTION_INDEX_REGISTER;
+
+ /****************************************
+ ************ Test case 1 ***************
+ **** REGISTER(Addr) create for read ****
+ ****************************************/
+ pr_info("STEP test: TC 1\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ params[1] = "0x124dfad";
+ params[2] = "0x9c";
+ params[3] = "2";
+ params[4] = "10";
+ param_num = 5;
+ check_params[0] = 0;
+ check_params[1] = 0x124dfad;
+ check_params[2] = 0x9c;
+ check_params[3] = 2;
+ check_params[4] = 10;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-1) REG create read");
+
+ /*****************************************
+ ************ Test case 2 ****************
+ **** REGISTER(Addr) create for write ****
+ *****************************************/
+ pr_info("STEP test: TC 2\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "1";
+ params[1] = "0x124dfad";
+ params[2] = "0x9c";
+ params[3] = "15";
+ param_num = 4;
+ check_params[0] = 1;
+ check_params[1] = 0x124dfad;
+ check_params[2] = 0x9c;
+ check_params[3] = 15;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-2) REG create write");
+
+ /******************************************
+ ************** Test case 3 ***************
+ ******* Boundary: read wrong symbol ******
+ ******************************************/
+ pr_info("STEP test: TC 3\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ params[1] = "#10000";
+ params[2] = "0x204";
+ params[3] = "1";
+ params[4] = "0";
+ param_num = 5;
+ check_params[0] = 0;
+ check_params[1] = 0x124dfad;
+ check_params[2] = 0x9c;
+ check_params[3] = 2;
+ check_params[4] = 10;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-3) Boundary: read wrong symbol");
+
+ /****************************************************
+ **************** Test case 4 **********************
+ **** REGISTER(Addr) create read fail less param ****
+ ****************************************************/
+ pr_info("STEP test: TC 4\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ params[1] = "0x124dfad";
+ params[2] = "0x9c";
+ param_num = 3;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-4) REG create read fail");
+
+ /*****************************************************
+ ************ Test case 5 ***************************
+ **** REGISTER(Addr) create write fail less param ****
+ *****************************************************/
+ pr_info("STEP test: TC 5\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "1";
+ params[1] = "0x124dfad";
+ params[2] = "0x9c";
+ param_num = 3;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-5) REG create write fail");
+
+ /*****************************************
+ ************ Test case 6 ****************
+ ** REGISTER(Addr) create for write bit ***
+ *****************************************/
+ pr_info("STEP test: TC 6\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "1";
+ params[1] = "0x124dfad";
+ params[2] = "0x9c";
+ params[3] = "15";
+ params[4] = "0xFF00FF00";
+ param_num = 5;
+ check_params[0] = 1;
+ check_params[1] = 0x124dfad;
+ check_params[2] = 0x9c;
+ check_params[3] = 15;
+ check_params[4] = 0xFF00FF00;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-6) REG create write");
+
+ /*********************************************************
+ ******************** Test case 7 ***********************
+ **** REGISTER(Addr) create for read to temp register ****
+ *********************************************************/
+ pr_info("STEP test: TC 7\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ params[1] = "0x124dfad";
+ params[2] = "0x9c";
+ params[3] = "0x00000030";
+ params[4] = "$5";
+ param_num = 5;
+ check_params[0] = 0;
+ check_params[1] = 0x124dfad;
+ check_params[2] = 0x9c;
+ check_params[3] = 0x00000030;
+ check_params[4] = 5;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-7) REGISTER(Addr) create for read to temp register");
+
+ /*********************************************************
+ ******************** Test case 8 ***********************
+ *** REGISTER(Symbol) create for read to temp register ***
+ *********************************************************/
+ pr_info("STEP test: TC 8\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ params[1] = "#1";
+ params[2] = "0x9c";
+ params[3] = "0x00000030";
+ params[4] = "$7";
+ param_num = 5;
+ check_params[0] = 0;
+ check_params[1] = 1;
+ check_params[2] = 0x9c;
+ check_params[3] = 0x00000030;
+ check_params[4] = 7;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-8) REGISTER(Symbol) create for read to temp register");
+
+ /*********************************************************
+ ******************** Test case 9 ***********************
+ ********** REGISTER(Symbol) create for read *************
+ *********************************************************/
+ pr_info("STEP test: TC 9\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ params[1] = "#1";
+ params[2] = "0x9c";
+ params[3] = "1";
+ params[4] = "10";
+ param_num = 5;
+ check_params[0] = 0;
+ check_params[1] = 1;
+ check_params[2] = 0x9c;
+ check_params[3] = 1;
+ check_params[4] = 10;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-9) REGISTER(Symbol) create for read");
+
+ /*********************************************************
+ ******************** Test case 10 ***********************
+ ************ REGISTER(Addr) less parameter **************
+ *********************************************************/
+ pr_info("STEP test: TC 10\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ params[1] = "0x124dfad";
+ params[2] = "0x9c";
+ params[3] = "0x555";
+ param_num = 4;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-10) REGISTER(Addr) less parameter");
+
+ /*********************************************************
+ ******************** Test case 11 ***********************
+ ************ REGISTER(Symbol) less parameter **************
+ *********************************************************/
+ pr_info("STEP test: TC 11\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ params[1] = "#1";
+ params[2] = "0x9c";
+ params[3] = "0x555";
+ param_num = 4;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-11) REGISTER(Symbol) less parameter");
+
+ /**********************************************************
+ *********************** Test case 12 *********************
+ ** Boundary: REGISTER(Addr) read to worng temp register **
+ **********************************************************/
+ pr_info("STEP test: TC 12\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ params[1] = "0x124dfad";
+ params[2] = "0x9c";
+ params[3] = "0x00000030";
+ params[4] = "$35";
+ param_num = 5;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-12) Boundary: REGISTER(Addr) read to worng temp registe");
+
+ /************************************************************
+ *********************** Test case 13 ***********************
+ ** Boundary: REGISTER(Symbol) read to worng temp register **
+ ************************************************************/
+ pr_info("STEP test: TC 13\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ params[1] = "#1";
+ params[2] = "0x9c";
+ params[3] = "0x00000030";
+ params[4] = "$35";
+ param_num = 5;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-13) Boundary: REGISTER(Symbol) read to worng temp registe");
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Create register action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+
+void conninfra_step_test_create_cond_register_action(struct step_test_report *p_report)
+{
+ enum step_action_id act_id;
+ char *params[STEP_PARAMETER_SIZE];
+ int check_params[STEP_PARAMETER_SIZE];
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+ int param_num = 0;
+
+ pr_info("STEP test: Create condition Register action start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ act_id = STEP_ACTION_INDEX_CONDITION_REGISTER;
+
+ /****************************************
+ ************ Test case 1 ***************
+ **** COND_REG(Addr) create for read ****
+ ****************************************/
+ pr_info("STEP test: TC 1\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$5";
+ params[1] = "0";
+ params[2] = "0x124dfad";
+ params[3] = "0x9c";
+ params[4] = "2";
+ params[5] = "10";
+ param_num = 6;
+ check_params[0] = 5;
+ check_params[1] = 0;
+ check_params[2] = 0x124dfad;
+ check_params[3] = 0x9c;
+ check_params[4] = 2;
+ check_params[5] = 10;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-1) COND_REG(Addr) create for read");
+
+ /*****************************************
+ ************ Test case 2 ****************
+ **** COND_REG(Addr) create for write ****
+ *****************************************/
+ pr_info("STEP test: TC 2\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$7";
+ params[1] = "1";
+ params[2] = "0x124dfad";
+ params[3] = "0x9c";
+ params[4] = "15";
+ param_num = 5;
+ check_params[0] = 7;
+ check_params[1] = 1;
+ check_params[2] = 0x124dfad;
+ check_params[3] = 0x9c;
+ check_params[4] = 15;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-2) COND_REG(Addr) create write");
+
+ /******************************************
+ ************** Test case 3 ***************
+ ******* Boundary: read wrong symbol ******
+ ******************************************/
+ pr_info("STEP test: TC 3\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$2";
+ params[1] = "0";
+ params[2] = "#10000";
+ params[3] = "0x204";
+ params[4] = "1";
+ params[5] = "0";
+ param_num = 6;
+ check_params[0] = 2;
+ check_params[1] = 0;
+ check_params[2] = 0x124dfad;
+ check_params[3] = 0x9c;
+ check_params[4] = 2;
+ check_params[5] = 10;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-3) Boundary: read wrong symbol");
+
+ /****************************************************
+ **************** Test case 4 **********************
+ **** COND_REG(Addr) create read fail less param ****
+ ****************************************************/
+ pr_info("STEP test: TC 4\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$3";
+ params[1] = "0";
+ params[2] = "0x124dfad";
+ params[3] = "0x9c";
+ param_num = 4;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-4) COND_REG create read fail");
+
+ /*****************************************************
+ ************ Test case 5 ***************************
+ **** COND_REG(Addr) create write fail less param ****
+ *****************************************************/
+ pr_info("STEP test: TC 5\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$4";
+ params[1] = "1";
+ params[2] = "0x124dfad";
+ params[3] = "0x9c";
+ param_num = 4;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-5) COND_REG create write fail");
+
+ /*****************************************
+ ************ Test case 6 ****************
+ ** COND_REG(Addr) create for write bit ***
+ *****************************************/
+ pr_info("STEP test: TC 6\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$9";
+ params[1] = "1";
+ params[2] = "0x124dfad";
+ params[3] = "0x9c";
+ params[4] = "15";
+ params[5] = "0xFF00FF00";
+ param_num = 6;
+ check_params[0] = 9;
+ check_params[1] = 1;
+ check_params[2] = 0x124dfad;
+ check_params[3] = 0x9c;
+ check_params[4] = 15;
+ check_params[5] = 0xFF00FF00;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-6) COND_REG create write");
+
+ /*********************************************************
+ ******************** Test case 7 ***********************
+ **** COND_REG(Addr) create for read to temp register ****
+ *********************************************************/
+ pr_info("STEP test: TC 7\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$9";
+ params[1] = "0";
+ params[2] = "0x124dfad";
+ params[3] = "0x9c";
+ params[4] = "0x00000030";
+ params[5] = "$5";
+ param_num = 6;
+ check_params[0] = 9;
+ check_params[1] = 0;
+ check_params[2] = 0x124dfad;
+ check_params[3] = 0x9c;
+ check_params[4] = 0x00000030;
+ check_params[5] = 5;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-7) COND_REG(Addr) create for read to temp register");
+
+ /*********************************************************
+ ******************** Test case 8 ***********************
+ *** COND_REG(Symbol) create for read to temp register ***
+ *********************************************************/
+ pr_info("STEP test: TC 8\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$1";
+ params[1] = "0";
+ params[2] = "#1";
+ params[3] = "0x9c";
+ params[4] = "0x00000030";
+ params[5] = "$7";
+ param_num = 6;
+ check_params[0] = 1;
+ check_params[1] = 0;
+ check_params[2] = 1;
+ check_params[3] = 0x9c;
+ check_params[4] = 0x00000030;
+ check_params[5] = 7;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-8) COND_REG(Symbol) create for read to temp register");
+
+ /*********************************************************
+ ******************** Test case 9 ***********************
+ ********** COND_REG(Symbol) create for read *************
+ *********************************************************/
+ pr_info("STEP test: TC 9\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$2";
+ params[1] = "0";
+ params[2] = "#1";
+ params[3] = "0x9c";
+ params[4] = "1";
+ params[5] = "10";
+ param_num = 6;
+ check_params[0] = 2;
+ check_params[1] = 0;
+ check_params[2] = 1;
+ check_params[3] = 0x9c;
+ check_params[4] = 1;
+ check_params[5] = 10;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-9) COND_REG(Symbol) create for read");
+
+ /*********************************************************
+ ******************** Test case 10 ***********************
+ ************ COND_REG(Addr) less parameter **************
+ *********************************************************/
+ pr_info("STEP test: TC 10\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$3";
+ params[1] = "0";
+ params[2] = "0x124dfad";
+ params[3] = "0x9c";
+ params[4] = "0x555";
+ param_num = 5;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-10) COND_REG(Addr) less parameter");
+
+ /*********************************************************
+ ******************** Test case 11 ***********************
+ ************ COND_REG(Symbol) less parameter **************
+ *********************************************************/
+ pr_info("STEP test: TC 11\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$4";
+ params[1] = "0";
+ params[2] = "#1";
+ params[3] = "0x9c";
+ params[4] = "0x555";
+ param_num = 5;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-11) COND_REG(Symbol) less parameter");
+
+ /**********************************************************
+ *********************** Test case 12 *********************
+ ** Boundary: COND_REG(Addr) read to worng temp register **
+ **********************************************************/
+ pr_info("STEP test: TC 12\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$5";
+ params[1] = "0";
+ params[2] = "0x124dfad";
+ params[3] = "0x9c";
+ params[4] = "0x00000030";
+ params[5] = "$35";
+ param_num = 6;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-12) Boundary: COND_REG(Addr) read to worng temp registe");
+
+ /************************************************************
+ *********************** Test case 13 ***********************
+ ** Boundary: COND_REG(Symbol) read to worng temp register **
+ ************************************************************/
+ pr_info("STEP test: TC 13\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$6";
+ params[1] = "0";
+ params[2] = "#1";
+ params[3] = "0x9c";
+ params[4] = "0x00000030";
+ params[5] = "$35";
+ param_num = 6;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-13) Boundary: COND_REG(Symbol) read to worng temp registe");
+
+ /*********************************************************
+ ******************** Test case 14 ***********************
+ ************* COND_REG(Symbol) worng symbol *************
+ *********************************************************/
+ pr_info("STEP test: TC 14\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "8";
+ params[1] = "0";
+ params[2] = "#1";
+ params[3] = "0x9c";
+ params[4] = "1";
+ params[5] = "10";
+ param_num = 6;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-14) Boundary: COND_REG(Symbol) worng symbol");
+
+ /*********************************************************
+ ******************** Test case 15 ***********************
+ ********* COND_REG(Symbol) worng temp register id *******
+ *********************************************************/
+ pr_info("STEP test: TC 15\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$88";
+ params[1] = "0";
+ params[2] = "#1";
+ params[3] = "0x9c";
+ params[4] = "1";
+ params[5] = "10";
+ param_num = 6;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-15) Boundary: COND_REG(Symbol) read to worng temp registe");
+
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Create condition register action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+
+
+#if 0
+int conninfra_step_test_get_symbol_num(void)
+{
+ int len;
+ struct device_node *node = NULL;
+
+ if (g_pdev != NULL) {
+ node = g_pdev->dev.of_node;
+ if (node) {
+ of_get_property(node, "reg", &len);
+ len /= (of_n_addr_cells(node) + of_n_size_cells(node));
+ len /= (sizeof(int));
+ } else {
+ pr_err("STEP test failed: node null");
+ return -1;
+ }
+ } else {
+ pr_err("STEP test failed: gdev null");
+ return -1;
+ }
+
+ return len;
+}
+#endif
+
+void conninfra_step_test_check_register_symbol(struct step_test_report *p_report)
+{
+ enum step_action_id act_id;
+ char *params[STEP_PARAMETER_SIZE];
+ int check_params[STEP_PARAMETER_SIZE];
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+ int param_num = 0;
+ int i = 0;
+ /* use CONSYS_BASE_ADDR_MAX directly */
+ //int symbol_num = conninfra_step_test_get_symbol_num();
+ int symbol_num = consys_reg_mng_get_reg_symbol_num();
+ unsigned char buf[4];
+
+ pr_info("STEP test: Check Register symbol start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ act_id = STEP_ACTION_INDEX_REGISTER;
+ /*********************************************************
+ ******************** Test case 1 ***********************
+ ********** REGISTER(Symbol) create for read *************
+ *********************************************************/
+ pr_info("STEP test: TC 1\n");
+ if (symbol_num < 0) {
+ temp_report.fail++;
+ } else {
+ pr_info("STEP test: symbol_num = [%d]\n", symbol_num);
+ for (i = 1; i <= symbol_num; i++) {
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ snprintf(buf, 4, "#%d", i);
+ params[1] = buf;
+ params[2] = "0x9c";
+ params[3] = "1";
+ params[4] = "10";
+ param_num = 5;
+ check_params[0] = 0;
+ check_params[1] = i;
+ check_params[2] = 0x9c;
+ check_params[3] = 1;
+ check_params[4] = 10;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Check Register symbol TC-1) REGISTER(Symbol) create for read");
+ }
+ }
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Check Register symbol result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+
+void conninfra_step_test_create_other_action(struct step_test_report *p_report)
+{
+ enum step_action_id act_id;
+ char *params[STEP_PARAMETER_SIZE];
+ int check_params[STEP_PARAMETER_SIZE];
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+ struct step_pd_entry fack_pd_entry;
+ int param_num = 0;
+
+ pr_info("STEP test: Create other action start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ /******************************************
+ ************ Test case 1 *****************
+ ********** GPIO create for read **********
+ ******************************************/
+ pr_info("STEP test: TC 1\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_GPIO;
+ params[0] = "0";
+ params[1] = "8";
+ param_num = 2;
+ check_params[0] = 0;
+ check_params[1] = 8;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-1) GPIO create read");
+
+ /*************************************************
+ **************** Test case 6 *******************
+ ********** GPIO create fail less param **********
+ *************************************************/
+ pr_info("STEP test: TC 6\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_GPIO;
+ params[0] = "0";
+ param_num = 1;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-6) GPIO create fail");
+
+ /*************************************************
+ **************** Test case 7 *******************
+ ************** Periodic dump create *************
+ *************************************************/
+ pr_info("STEP test: TC 7\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_PERIODIC_DUMP;
+ params[0] = (char*)&fack_pd_entry;
+ param_num = 1;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-7) Periodic dump create fail");
+
+ /*************************************************
+ **************** Test case 8 *******************
+ ****** Periodic dump create fail no param *******
+ *************************************************/
+ pr_info("STEP test: TC 8\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_PERIODIC_DUMP;
+ param_num = 0;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-8) Periodic dump create fail");
+
+ /*************************************************
+ **************** Test case 9 *******************
+ **************** Show create ********************
+ *************************************************/
+ pr_info("STEP test: TC 9\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_SHOW_STRING;
+ params[0] = "Hello";
+ param_num = 1;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-9) Show create");
+
+ /*************************************************
+ **************** Test case 10 *******************
+ ******** Show create failed no param ************
+ *************************************************/
+ pr_info("STEP test: TC 10\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_SHOW_STRING;
+ param_num = 0;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-10) Show create failed no param");
+
+ /*************************************************
+ **************** Test case 11 *******************
+ **************** Sleep create *******************
+ *************************************************/
+ pr_info("STEP test: TC 11\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_SLEEP;
+ params[0] = "1000";
+ param_num = 1;
+ check_params[0] = 1000;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-11) Sleep create");
+
+ /*************************************************
+ **************** Test case 12 *******************
+ ********* Sleep create failed no param **********
+ *************************************************/
+ pr_info("STEP test: TC 12\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_SLEEP;
+ param_num = 0;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-12) Sleep create failed no param");
+
+ /*************************************************
+ **************** Test case 13 *******************
+ ************** Condition create *****************
+ *************************************************/
+ pr_info("STEP test: TC 13\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_CONDITION;
+ params[0] = "$0";
+ params[1] = "$1";
+ params[2] = "==";
+ params[3] = "$2";
+ param_num = 4;
+ check_params[0] = 0;
+ check_params[1] = 1;
+ check_params[2] = STEP_OPERATOR_EQUAL;
+ check_params[3] = 2;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-13) Condition create");
+
+ /*************************************************
+ **************** Test case 14 *******************
+ *********** Condition create value **************
+ *************************************************/
+ pr_info("STEP test: TC 14\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_CONDITION;
+ params[0] = "$0";
+ params[1] = "$1";
+ params[2] = "==";
+ params[3] = "16";
+ param_num = 4;
+ check_params[0] = 0;
+ check_params[1] = 1;
+ check_params[2] = STEP_OPERATOR_EQUAL;
+ check_params[3] = 16;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-14) Condition create");
+
+ /*************************************************
+ **************** Test case 15 *******************
+ ****** Condition create failed less param *******
+ *************************************************/
+ pr_info("STEP test: TC 15\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_CONDITION;
+ params[0] = "$0";
+ params[1] = "$1";
+ params[2] = "$2";
+ param_num = 3;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-15) Condition create failed less param");
+
+ /*************************************************
+ **************** Test case 16 *******************
+ ******** Condition create failed no value********
+ *************************************************/
+ pr_info("STEP test: TC 16\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_CONDITION;
+ params[0] = "==";
+ param_num = 1;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-16) Condition create failed no value");
+
+ /*************************************************
+ **************** Test case 17 *******************
+ * Boundary: Condition create failed over reg id *
+ *************************************************/
+ pr_info("STEP test: TC 17\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_CONDITION;
+ params[0] = "$25";
+ params[1] = "$1";
+ params[2] = "==";
+ params[3] = "$2";
+ param_num = 4;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-17) Boundary: Condition create failed over reg id");
+
+ /*************************************************
+ **************** Test case 18 *******************
+ * Boundary: Condition create failed over reg id *
+ *************************************************/
+ pr_info("STEP test: TC 18\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_CONDITION;
+ params[0] = "$0";
+ params[1] = "$1";
+ params[2] = "==";
+ params[3] = "$20";
+ param_num = 4;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-18) Boundary: Condition create failed over reg id");
+
+ /*************************************************
+ **************** Test case 19 *******************
+ ******** Condition create failed operator********
+ *************************************************/
+ pr_info("STEP test: TC 19\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_CONDITION;
+ params[0] = "$0";
+ params[1] = "$1";
+ params[2] = "&";
+ params[3] = "$2";
+ param_num = 4;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-19) Condition create failed operator");
+
+ /*************************************************
+ **************** Test case 20 *******************
+ **************** Value create *******************
+ *************************************************/
+ pr_info("STEP test: TC 20\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_VALUE;
+ params[0] = "$0";
+ params[1] = "0x123";
+ param_num = 2;
+ check_params[0] = 0;
+ check_params[1] = 0x123;
+ conninfra_step_test_create_action(act_id, param_num, params, 0, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-20) Condition create");
+
+ /*************************************************
+ **************** Test case 21 *******************
+ ******* Value create failed wrong order *********
+ *************************************************/
+ pr_info("STEP test: TC 21\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_VALUE;
+ params[0] = "0x123";
+ params[1] = "$1";
+ param_num = 2;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-21) Value create failed wrong order");
+
+ /*************************************************
+ **************** Test case 22 *******************
+ ********* Value create failed no value **********
+ *************************************************/
+ pr_info("STEP test: TC 22\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_VALUE;
+ params[0] = "$1";
+ param_num = 1;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-22) Value create failed no value");
+
+ /*************************************************
+ **************** Test case 23 *******************
+ *** Boundary: Value create failed over reg id ***
+ *************************************************/
+ pr_info("STEP test: TC 23\n");
+ conninfra_step_test_clear_parameter(params);
+ act_id = STEP_ACTION_INDEX_VALUE;
+ params[0] = "$25";
+ params[1] = "0x123";
+ param_num = 2;
+ conninfra_step_test_create_action(act_id, param_num, params, -1, check_params, &temp_report,
+ "STEP test case failed: (Create action TC-23) Boundary: Value create failed over reg id");
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Create other action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+
+#if 0
+/* this offset only for FPGA */
+#define CONNINFRA_STEP_TEST_EMI_COREDUMP_OFFSET 0x4f000
+/* formal chip use this offset*/
+//#define CONNINFRA_STEP_TEST_EMI_COREDUMP_OFFSET 0x27f000
+
+int conninfra_step_test_get_emi_offset(unsigned char buf[], int offset)
+{
+ P_CONSYS_EMI_ADDR_INFO emi_phy_addr = NULL;
+
+ emi_phy_addr = emi_mng_get_phy_addr();
+ if (emi_phy_addr != NULL) {
+ /* TODO: fix this, change the region to coredump */
+
+ snprintf(buf, 11, "0x%08x", (CONNINFRA_STEP_TEST_EMI_COREDUMP_OFFSET /*->emi_core_dump_offset*/ + offset));
+ //snprintf(buf, 11, "0x%08x", ((unsigned int)emi_phy_addr->emi_ap_phy_addr /*->emi_core_dump_offset*/ + offset));
+ } else {
+ pr_err("STEP test failed: emi_phy_addr is NULL\n");
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+void conninfra_step_test_do_emi_action(struct step_test_report *p_report)
+{
+ enum step_action_id act_id;
+ char *params[STEP_PARAMETER_SIZE];
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+ unsigned char buf_begin[11];
+ unsigned char buf_end[11];
+ int param_num;
+ struct consys_emi_addr_info* emi_phy_addr = NULL;
+
+ pr_info("STEP test: Do EMI action start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ act_id = STEP_ACTION_INDEX_EMI;
+
+ emi_phy_addr = emi_mng_get_phy_addr();
+ if (emi_phy_addr == NULL) {
+ temp_report.fail++;
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Do EMI action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+ return;
+ }
+
+ if (conninfra_step_test_get_emi_offset(buf_begin, 0x0) != 0) {
+ temp_report.fail++;
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Do EMI action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+ return;
+ }
+
+ /*****************************************
+ ************ Test case 1 ****************
+ ********** EMI dump 32 bit **************
+ *****************************************/
+ pr_info("STEP test: TC 1\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ conninfra_step_test_get_emi_offset(buf_begin, 0x44);
+ params[1] = buf_begin;
+ conninfra_step_test_get_emi_offset(buf_end, 0x48);
+ params[2] = buf_end;
+ param_num = 3;
+ g_conninfra_step_test_check.step_check_total = 1;
+ g_conninfra_step_test_check.step_check_emi_offset[0] = 0x44;
+ __conninfra_step_test_do_emi_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do EMI action TC-1) dump 32bit");
+
+
+ /*****************************************
+ ************ Test case 2 ****************
+ ****** EMI dump check for address *******
+ *****************************************/
+ pr_info("STEP test: TC 2\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ conninfra_step_test_get_emi_offset(buf_begin, 0x24);
+ params[1] = buf_begin;
+ conninfra_step_test_get_emi_offset(buf_end, 0x44);
+ params[2] = buf_end;
+ param_num = 3;
+ g_conninfra_step_test_check.step_check_total = 8;
+ g_conninfra_step_test_check.step_check_emi_offset[0] = 0x24;
+ g_conninfra_step_test_check.step_check_emi_offset[1] = 0x28;
+ g_conninfra_step_test_check.step_check_emi_offset[2] = 0x2c;
+ g_conninfra_step_test_check.step_check_emi_offset[3] = 0x30;
+ g_conninfra_step_test_check.step_check_emi_offset[4] = 0x34;
+ g_conninfra_step_test_check.step_check_emi_offset[5] = 0x38;
+ g_conninfra_step_test_check.step_check_emi_offset[6] = 0x3c;
+ g_conninfra_step_test_check.step_check_emi_offset[7] = 0x40;
+ __conninfra_step_test_do_emi_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do EMI action TC-2) more address");
+
+ /*****************************************
+ ************ Test case 3 ****************
+ **** EMI dump begin larger than end *****
+ *****************************************/
+ pr_info("STEP test: TC 3\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ conninfra_step_test_get_emi_offset(buf_begin, 0x20);
+ params[1] = buf_begin;
+ conninfra_step_test_get_emi_offset(buf_end, 0x08);
+ params[2] = buf_end;
+ param_num = 3;
+ g_conninfra_step_test_check.step_check_total = 6;
+ g_conninfra_step_test_check.step_check_emi_offset[0] = 0x08;
+ g_conninfra_step_test_check.step_check_emi_offset[1] = 0x0c;
+ g_conninfra_step_test_check.step_check_emi_offset[2] = 0x10;
+ g_conninfra_step_test_check.step_check_emi_offset[3] = 0x14;
+ g_conninfra_step_test_check.step_check_emi_offset[4] = 0x18;
+ g_conninfra_step_test_check.step_check_emi_offset[5] = 0x1c;
+ __conninfra_step_test_do_emi_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do EMI action TC-3) begin larger than end");
+
+ /****************************************
+ ************ Test case 4 ***************
+ ******** EMI only support read *********
+ ****************************************/
+ pr_info("STEP test: TC 4\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "1";
+ conninfra_step_test_get_emi_offset(buf_begin, 0x08);
+ params[1] = buf_begin;
+ conninfra_step_test_get_emi_offset(buf_end, 0x20);
+ params[2] = buf_end;
+ param_num = 3;
+ __conninfra_step_test_do_emi_action(act_id, param_num, params, -1, &temp_report,
+ "STEP test case failed: (Do EMI action TC-4) only support read");
+
+ /****************************************
+ ************ Test case 5 ***************
+ ********* EMI dump not 32bit ***********
+ ****************************************/
+ pr_info("STEP test: TC 5\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ conninfra_step_test_get_emi_offset(buf_begin, 0x08);
+ params[1] = buf_begin;
+ conninfra_step_test_get_emi_offset(buf_end, 0x0e);
+ params[2] = buf_end;
+ param_num = 3;
+ g_conninfra_step_test_check.step_check_total = 2;
+ g_conninfra_step_test_check.step_check_emi_offset[0] = 0x08;
+ g_conninfra_step_test_check.step_check_emi_offset[1] = 0x0c;
+ __conninfra_step_test_do_emi_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do EMI action TC-5) not 32bit");
+
+ /*****************************************
+ ************ Test case 6 ****************
+ ***** EMI dump over emi max size ********
+ *****************************************/
+ pr_info("STEP test: TC 6\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ conninfra_step_test_get_emi_offset(buf_begin, (emi_phy_addr->emi_size + 0x08));
+ params[1] = buf_begin;
+ conninfra_step_test_get_emi_offset(buf_end, (emi_phy_addr->emi_size+ 0x0e));
+ params[2] = buf_end;
+ param_num = 3;
+ __conninfra_step_test_do_emi_action(act_id, param_num, params, -1, &temp_report,
+ "STEP test case failed: (Do EMI action TC-6) over emi max size");
+
+ /*****************************************
+ ************ Test case 7 ****************
+ ************* page fault ****************
+ *****************************************/
+ pr_info("STEP test: TC 7\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ conninfra_step_test_get_emi_offset(buf_begin, 0x02);
+ params[1] = buf_begin;
+ conninfra_step_test_get_emi_offset(buf_end, 0x08);
+ params[2] = buf_end;
+ param_num = 3;
+ __conninfra_step_test_do_emi_action(act_id, param_num, params, -1, &temp_report,
+ "STEP test case failed: (Do EMI action TC-7) page fault");
+
+ /*****************************************
+ ************ Test case 8 ****************
+ ********** save to temp reg *************
+ *****************************************/
+ pr_info("STEP test: TC 8\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "0";
+ conninfra_step_test_get_emi_offset(buf_begin, 0x08);
+ params[1] = buf_begin;
+ params[2] = "0x0F0F0F0F";
+ params[3] = "$1";
+ param_num = 4;
+ g_conninfra_step_test_check.step_check_total = 1;
+ g_conninfra_step_test_check.step_check_emi_offset[0] = 0x08;
+ g_conninfra_step_test_check.step_test_mask = 0x0F0F0F0F;
+ g_conninfra_step_test_check.step_check_temp_register_id = 1;
+ __conninfra_step_test_do_emi_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do EMI action TC-8) save to temp reg");
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Do EMI action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+
+void conninfra_step_test_do_cond_emi_action(struct step_test_report *p_report)
+{
+ enum step_action_id act_id;
+ char *params[STEP_PARAMETER_SIZE];
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+ unsigned char buf_begin[11];
+ unsigned char buf_end[11];
+ int param_num;
+ struct consys_emi_addr_info* emi_phy_addr = NULL;
+
+ pr_info("STEP test: Do condition EMI action start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ act_id = STEP_ACTION_INDEX_CONDITION_EMI;
+
+ emi_phy_addr = emi_mng_get_phy_addr();
+ if (emi_phy_addr == NULL) {
+ temp_report.fail++;
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Do Condition EMI action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+ return;
+ }
+
+ /*****************************************
+ ************ Test case 1 ****************
+ ********** EMI dump 32 bit **************
+ *****************************************/
+ pr_info("STEP test: TC 1\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$0";
+ params[1] = "0";
+ conninfra_step_test_get_emi_offset(buf_begin, 0x44);
+ params[2] = buf_begin;
+ conninfra_step_test_get_emi_offset(buf_end, 0x48);
+ params[3] = buf_end;
+ param_num = 4;
+ g_infra_step_env.temp_register[0] = 1;
+
+ g_conninfra_step_test_check.step_check_total = 1;
+ g_conninfra_step_test_check.step_check_emi_offset[0] = 0x44;
+ __conninfra_step_test_do_cond_emi_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do COND EMI action TC-1) dump 32bit");
+
+ /*****************************************
+ ************ Test case 2 ****************
+ ****** EMI dump check for address *******
+ *****************************************/
+ pr_info("STEP test: TC 2\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$1";
+ params[1] = "0";
+ conninfra_step_test_get_emi_offset(buf_begin, 0x24);
+ params[2] = buf_begin;
+ conninfra_step_test_get_emi_offset(buf_end, 0x44);
+ params[3] = buf_end;
+ param_num = 4;
+ g_infra_step_env.temp_register[1] = 1;
+
+ g_conninfra_step_test_check.step_check_total = 8;
+ g_conninfra_step_test_check.step_check_emi_offset[0] = 0x24;
+ g_conninfra_step_test_check.step_check_emi_offset[1] = 0x28;
+ g_conninfra_step_test_check.step_check_emi_offset[2] = 0x2c;
+ g_conninfra_step_test_check.step_check_emi_offset[3] = 0x30;
+ g_conninfra_step_test_check.step_check_emi_offset[4] = 0x34;
+ g_conninfra_step_test_check.step_check_emi_offset[5] = 0x38;
+ g_conninfra_step_test_check.step_check_emi_offset[6] = 0x3c;
+ g_conninfra_step_test_check.step_check_emi_offset[7] = 0x40;
+ __conninfra_step_test_do_cond_emi_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do COND EMI action TC-2) more address");
+
+ /*****************************************
+ ************ Test case 3 ****************
+ **** EMI dump begin larger than end *****
+ *****************************************/
+ pr_info("STEP test: TC 3\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$0";
+ params[1] = "0";
+ conninfra_step_test_get_emi_offset(buf_begin, 0x20);
+ params[2] = buf_begin;
+ conninfra_step_test_get_emi_offset(buf_end, 0x08);
+ params[3] = buf_end;
+ param_num = 4;
+ g_infra_step_env.temp_register[0] = 15;
+
+ g_conninfra_step_test_check.step_check_total = 6;
+ g_conninfra_step_test_check.step_check_emi_offset[0] = 0x08;
+ g_conninfra_step_test_check.step_check_emi_offset[1] = 0x0c;
+ g_conninfra_step_test_check.step_check_emi_offset[2] = 0x10;
+ g_conninfra_step_test_check.step_check_emi_offset[3] = 0x14;
+ g_conninfra_step_test_check.step_check_emi_offset[4] = 0x18;
+ g_conninfra_step_test_check.step_check_emi_offset[5] = 0x1c;
+ __conninfra_step_test_do_cond_emi_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do COND EMI action TC-3) begin larger than end");
+
+ /****************************************
+ ************ Test case 4 ***************
+ ******** EMI only support read *********
+ ****************************************/
+ pr_info("STEP test: TC 4\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$1";
+ params[1] = "1";
+ conninfra_step_test_get_emi_offset(buf_begin, 0x08);
+ params[2] = buf_begin;
+ conninfra_step_test_get_emi_offset(buf_end, 0x20);
+ params[3] = buf_end;
+ param_num = 4;
+ g_infra_step_env.temp_register[1] = 1;
+
+ __conninfra_step_test_do_cond_emi_action(act_id, param_num, params, -1, &temp_report,
+ "STEP test case failed: (Do COND EMI action TC-4) only support read");
+
+ /****************************************
+ ************ Test case 5 ***************
+ ********* EMI dump not 32bit ***********
+ ****************************************/
+ pr_info("STEP test: TC 5\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$0";
+ params[1] = "0";
+ conninfra_step_test_get_emi_offset(buf_begin, 0x08);
+ params[2] = buf_begin;
+ conninfra_step_test_get_emi_offset(buf_end, 0x0e);
+ params[3] = buf_end;
+ param_num = 4;
+ g_infra_step_env.temp_register[0] = 1;
+
+ g_conninfra_step_test_check.step_check_total = 2;
+ g_conninfra_step_test_check.step_check_emi_offset[0] = 0x08;
+ g_conninfra_step_test_check.step_check_emi_offset[1] = 0x0c;
+ __conninfra_step_test_do_cond_emi_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do COND EMI action TC-5) not 32bit");
+
+ /*****************************************
+ ************ Test case 6 ****************
+ ***** EMI dump over emi max size ********
+ *****************************************/
+ pr_info("STEP test: TC 6\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$9";
+ params[1] = "0";
+ conninfra_step_test_get_emi_offset(buf_begin, (emi_phy_addr->emi_size + 0x08));
+ params[2] = buf_begin;
+ conninfra_step_test_get_emi_offset(buf_end, (emi_phy_addr->emi_size + 0x0e));
+ params[3] = buf_end;
+ param_num = 4;
+ g_infra_step_env.temp_register[9] = 1;
+
+ __conninfra_step_test_do_cond_emi_action(act_id, param_num, params, -1, &temp_report,
+ "STEP test case failed: (Do COND EMI action TC-6) over emi max size");
+
+ /*****************************************
+ ************ Test case 7 ****************
+ ************* page fault ****************
+ *****************************************/
+ pr_info("STEP test: TC 7\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$0";
+ params[1] = "0";
+ conninfra_step_test_get_emi_offset(buf_begin, 0x02);
+ params[2] = buf_begin;
+ conninfra_step_test_get_emi_offset(buf_end, 0x08);
+ params[3] = buf_end;
+ param_num = 4;
+ g_infra_step_env.temp_register[0] = 1;
+
+ __conninfra_step_test_do_cond_emi_action(act_id, param_num, params, -1, &temp_report,
+ "STEP test case failed: (Do COND EMI action TC-7) page fault");
+
+ /*****************************************
+ ************ Test case 8 ****************
+ ********** save to temp reg *************
+ *****************************************/
+ pr_info("STEP test: TC 8\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$0";
+ params[1] = "0";
+ conninfra_step_test_get_emi_offset(buf_begin, 0x08);
+ params[2] = buf_begin;
+ params[3] = "0x0F0F0F0F";
+ params[4] = "$1";
+ param_num = 5;
+ g_conninfra_step_test_check.step_check_total = 1;
+ g_conninfra_step_test_check.step_check_emi_offset[0] = 0x08;
+ g_conninfra_step_test_check.step_test_mask = 0x0F0F0F0F;
+ g_conninfra_step_test_check.step_check_temp_register_id = 1;
+ g_infra_step_env.temp_register[0] = 1;
+ __conninfra_step_test_do_cond_emi_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do EMI action TC-8) save to temp reg");
+
+
+ /*****************************************
+ ************ Test case 9 ****************
+ ******** condition invalid **************
+ *****************************************/
+ pr_info("STEP test: TC 9\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$0";
+ params[1] = "0";
+ conninfra_step_test_get_emi_offset(buf_begin, 0x08);
+ params[2] = buf_begin;
+ conninfra_step_test_get_emi_offset(buf_end, 0x0e);
+ params[3] = buf_end;
+ param_num = 4;
+ g_infra_step_env.temp_register[0] = 0;
+
+ __conninfra_step_test_do_cond_emi_action(act_id, param_num, params, -1, &temp_report,
+ "STEP test case failed: (Do COND EMI action TC-9) condition invalid");
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Do condition EMI action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+
+void conninfra_step_test_do_register_action(struct step_test_report *p_report)
+{
+#define TEST_BUF_LEN 12
+ enum step_action_id act_id;
+ char *params[STEP_PARAMETER_SIZE];
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+ unsigned char buf[TEST_BUF_LEN], buf2[TEST_BUF_LEN];
+ int param_num;
+ unsigned int can_write_idx = 0, chip_id_idx = 0;
+ unsigned long can_write_offset = 0, chip_id_offset = 0;
+ unsigned long can_write_vir_addr = 0, can_write_phy_addr = 0;
+ unsigned long chip_id_vir_addr = 0, chip_id_phy_addr = 0;
+ unsigned long first_idx_vir_addr = 0, first_idx_phy_addr = 0;
+ unsigned char can_write_offset_char[11];
+
+ pr_info("STEP test: Do register action start\n");
+
+ /* TODO: need to redefine the test case */
+#if TEST_WRITE_CR_TEST_CASE
+ if (consys_reg_mng_find_can_write_reg(&can_write_idx, &can_write_offset)) {
+ p_report->fail++;
+ pr_err("STEP test: Do register action init can_write_offset failed\n");
+ return;
+ }
+#endif
+ snprintf(can_write_offset_char, 11, "0x%08lx", can_write_offset);
+
+ if (consys_reg_mng_get_chip_id_idx_offset(&chip_id_idx, &chip_id_offset)) {
+ p_report->fail++;
+ pr_err("STEP test: Do register action init chip id idx and offset fail \n");
+ return;
+ }
+ can_write_vir_addr = consys_reg_mng_get_virt_addr_by_idx(can_write_idx);
+ can_write_phy_addr = consys_reg_mng_get_phy_addr_by_idx(can_write_idx);
+
+ chip_id_vir_addr = consys_reg_mng_get_virt_addr_by_idx(chip_id_idx);
+ chip_id_phy_addr = consys_reg_mng_get_phy_addr_by_idx(chip_id_idx);
+
+ pr_info("[%s] chipId idx=[%d] vir=[%p] phy=[%p] offset=[%x]", __func__,
+ chip_id_idx, chip_id_vir_addr, chip_id_phy_addr, chip_id_offset);
+
+ if (can_write_vir_addr == 0 || can_write_phy_addr == 0 ||
+ chip_id_vir_addr == 0 || chip_id_phy_addr == 0) {
+ p_report->fail++;
+ pr_err("STEP test: Do register action init vir/phy addr fail [%x][%x] [%x][%x] chipidIdx=[%d]\n",
+ can_write_vir_addr, can_write_phy_addr,
+ chip_id_vir_addr, chip_id_phy_addr, chip_id_idx);
+ return;
+ }
+
+ pr_info("[%s] offset=[%s]", __func__, can_write_offset_char);
+
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ act_id = STEP_ACTION_INDEX_REGISTER;
+ /****************************************
+ ************ Test case 1 ***************
+ ******** REG read HW chip id **********
+ ****************************************/
+ pr_info("STEP test: TC 1\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+
+ snprintf(buf, TEST_BUF_LEN, "#%d", chip_id_idx+1);
+ snprintf(buf2, TEST_BUF_LEN, "0x%lx", chip_id_offset);
+
+ params[0] = "0";
+ //params[1] = "#1";
+ params[1] = buf;
+ //params[2] = "0x04";
+ params[2] = buf2;
+ params[3] = "1";
+ params[4] = "0";
+ param_num = 5;
+ /* Chip id may different by projects, TODO: the address should be define on consys_hw */
+ //g_conninfra_step_test_check.step_check_register_addr = (CON_REG_INFRA_CFG_ADDR + 0x04);
+ g_conninfra_step_test_check.step_check_register_addr = (chip_id_vir_addr + chip_id_offset);
+ __conninfra_step_test_do_register_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do register action TC-1) MCU chip id");
+
+ /**********************************************
+ *************** Test case 2 ******************
+ ** REG read MCU chip id by physical address **
+ **********************************************/
+ pr_info("STEP test: TC 2\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ snprintf(buf, TEST_BUF_LEN, "0x%08lx", chip_id_phy_addr);
+ params[1] = buf;
+ //params[2] = "0x04";
+ params[2] = buf2;
+ params[3] = "1";
+ params[4] = "0";
+ param_num = 5;
+ g_conninfra_step_test_check.step_check_register_addr = (chip_id_vir_addr + chip_id_offset);
+ __conninfra_step_test_do_register_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do register action TC-3) MCU chip id by phy");
+
+ /*****************************************
+ ************* Test case 3 ***************
+ ******** REG read over base size ********
+ *****************************************/
+ pr_info("STEP test: TC 3 >>>> \n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ params[1] = "#1";
+ params[2] = "0x11204";
+ params[3] = "1";
+ params[4] = "0";
+ param_num = 5;
+ __conninfra_step_test_do_register_action(act_id, param_num, params, -1, &temp_report,
+ "STEP test case failed: (Do register action TC-5) Over size");
+
+ /******************************************
+ ************** Test case 4 ***************
+ ***** REG read over base size by phy *****
+ ******************************************/
+ pr_info("STEP test: TC 6\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+
+ first_idx_phy_addr = consys_reg_mng_get_phy_addr_by_idx(0);
+ first_idx_vir_addr = consys_reg_mng_get_virt_addr_by_idx(0);
+ if (first_idx_phy_addr != 0 && first_idx_vir_addr != 0) {
+ snprintf(buf, TEST_BUF_LEN, "0x%08lx", first_idx_phy_addr);
+ params[1] = buf;
+ params[2] = "0x204";
+ params[3] = "1";
+ params[4] = "0";
+ param_num = 5;
+ g_conninfra_step_test_check.step_check_register_addr = (first_idx_vir_addr + 0x204);
+ __conninfra_step_test_do_register_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do register action TC-6) Over size by phy");
+ } else {
+ p_report->fail++;
+ pr_err("STEP test case failed: get physical address failed\n");
+ }
+
+ /******************************************
+ ************** Test case 5 ***************
+ *************** REG write ****************
+ ******************************************/
+#if TEST_WRITE_CR_TEST_CASE
+ pr_info("STEP test: TC 5\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+
+ snprintf(buf, TEST_BUF_LEN, "#%d", can_write_idx+1);
+ params[0] = "1";
+ //params[1] = "#0";
+ params[1] = buf;
+ params[2] = can_write_offset_char;
+ params[3] = "0x2";
+ param_num = 4;
+ g_conninfra_step_test_check.step_check_register_addr = (can_write_vir_addr + can_write_offset);
+ g_conninfra_step_test_check.step_check_write_value = 0x2;
+ __conninfra_step_test_do_register_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do register action TC-7) REG write");
+#endif
+
+ /******************************************
+ ************** Test case 6 ***************
+ *********** REG write by phy *************
+ ******************************************/
+#if TEST_WRITE_CR_TEST_CASE
+ pr_info("STEP test: TC 6\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "1";
+
+ snprintf(buf, TEST_BUF_LEN, "0x%08x", can_write_phy_addr);
+ params[1] = buf;
+ params[2] = can_write_offset_char;
+ params[3] = "0x7";
+ param_num = 4;
+ g_conninfra_step_test_check.step_check_register_addr = (can_write_vir_addr + can_write_offset);
+ g_conninfra_step_test_check.step_check_write_value = 0x7;
+ __conninfra_step_test_do_register_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do register action TC-8) REG write by phy");
+#endif
+
+ /******************************************
+ ************** Test case 7 ***************
+ ************* REG write bit **************
+ ******************************************/
+#if TEST_WRITE_CR_TEST_CASE
+ pr_info("STEP test: TC 7\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+
+ snprintf(buf, TEST_BUF_LEN, "#%d", can_write_idx+1);
+
+ params[0] = "1";
+ //params[1] = "#0";
+ params[1] = buf;
+ params[2] = can_write_offset_char;
+ params[3] = "0x321";
+ params[4] = "0x00F";
+ param_num = 5;
+ g_conninfra_step_test_check.step_check_register_addr = (can_write_vir_addr + can_write_offset);
+ g_conninfra_step_test_check.step_check_write_value = 0x001;
+ g_conninfra_step_test_check.step_test_mask = 0x00F;
+ __conninfra_step_test_do_register_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do register action TC-9) REG write bit");
+#endif
+
+ /******************************************
+ ************** Test case 8 **************
+ ********* REG write bit by phy ***********
+ ******************************************/
+#if TEST_WRITE_CR_TEST_CASE
+ pr_info("STEP test: TC 8\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "1";
+ //if (conninfra_step_test_get_reg_base_phy_addr(buf, 0) == 0) {
+ snprintf(buf, TEST_BUF_LEN, "0x%08x", can_write_phy_addr);
+ params[1] = buf;
+ params[2] = can_write_offset_char;
+ params[3] = "0x32f";
+ params[4] = "0x002";
+ param_num = 5;
+ g_conninfra_step_test_check.step_check_register_addr = (can_write_vir_addr + can_write_offset);
+ g_conninfra_step_test_check.step_check_write_value = 0x002;
+ g_conninfra_step_test_check.step_test_mask = 0x002;
+ __conninfra_step_test_do_register_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do register action TC-10) REG write bit by phy");
+#endif
+
+ /******************************************
+ ************** Test case 9 **************
+ ********* REG read to temp reg ***********
+ ******************************************/
+ pr_info("STEP test: TC 9\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "0";
+ params[1] = "#1";
+ params[2] = "0x08";
+ params[3] = "0x0F0F0F0F";
+ params[4] = "$2";
+ param_num = 5;
+ g_conninfra_step_test_check.step_check_register_addr = (first_idx_vir_addr + 0x08);
+ g_conninfra_step_test_check.step_test_mask = 0x0F0F0F0F;
+ g_conninfra_step_test_check.step_check_temp_register_id = 2;
+ __conninfra_step_test_do_register_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do register action TC-11) REG read to temp reg");
+
+ /******************************************
+ ************** Test case 10 **************
+ ******* REG read phy to temp reg *********
+ ******************************************/
+ pr_info("STEP test: TC 10\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "0";
+
+ snprintf(buf, TEST_BUF_LEN, "0x%08lx", first_idx_phy_addr);
+ params[1] = buf;
+ params[2] = "0x08";
+ params[3] = "0x0F0F0F0F";
+ params[4] = "$3";
+ param_num = 5;
+ g_conninfra_step_test_check.step_check_register_addr = (first_idx_vir_addr + 0x08);
+ g_conninfra_step_test_check.step_test_mask = 0x0F0F0F0F;
+ g_conninfra_step_test_check.step_check_temp_register_id = 3;
+ __conninfra_step_test_do_register_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do register action TC-12) REG read phy to temp reg");
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Do register action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+
+void conninfra_step_test_do_cond_register_action(struct step_test_report *p_report)
+{
+ enum step_action_id act_id;
+ char *params[STEP_PARAMETER_SIZE];
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+ unsigned char buf[TEST_BUF_LEN], buf2[TEST_BUF_LEN];
+ int param_num;
+ unsigned int can_write_idx = 0, chip_id_idx = 0;
+ unsigned long can_write_offset = 0, chip_id_offset = 0;
+ unsigned long can_write_vir_addr = 0, can_write_phy_addr = 0;
+ unsigned long chip_id_vir_addr, chip_id_phy_addr;
+ unsigned long first_idx_vir_addr, first_idx_phy_addr;
+ unsigned char can_write_offset_char[11];
+
+ pr_info("STEP test: Do condition register action start\n");
+
+#if TEST_WRITE_CR_TEST_CASE
+ if (consys_reg_mng_find_can_write_reg(&can_write_idx, &can_write_offset)) {
+ p_report->fail++;
+ pr_err("STEP test: Do register action init can_write_offset failed\n");
+ return;
+ }
+#endif
+ snprintf(can_write_offset_char, 11, "0x%08lx", can_write_offset);
+
+ if (consys_reg_mng_get_chip_id_idx_offset(&chip_id_idx, &chip_id_offset)) {
+ p_report->fail++;
+ pr_err("STEP test: Do register action init chip id idx and offset fail \n");
+ return;
+ }
+ can_write_vir_addr = consys_reg_mng_get_virt_addr_by_idx(can_write_idx);
+ can_write_phy_addr = consys_reg_mng_get_phy_addr_by_idx(can_write_idx);
+
+ chip_id_vir_addr = consys_reg_mng_get_virt_addr_by_idx(chip_id_idx);
+ chip_id_phy_addr = consys_reg_mng_get_phy_addr_by_idx(chip_id_idx);
+
+ if (can_write_vir_addr == 0 || can_write_phy_addr == 0 ||
+ chip_id_vir_addr == 0 || chip_id_phy_addr == 0) {
+ p_report->fail++;
+ pr_err("STEP test: Do register action init vir/phy addr fail [%x][%x][%x] \n"
+ , can_write_vir_addr, chip_id_vir_addr, chip_id_phy_addr);
+ return;
+ }
+
+ pr_info("STEP test: chipId=[%d] [%x][%x] offset=[%x] canWrite=[%d] [%x][%x]",
+ chip_id_idx, chip_id_vir_addr, chip_id_phy_addr, chip_id_offset,
+ can_write_idx, can_write_vir_addr, can_write_phy_addr);
+
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ act_id = STEP_ACTION_INDEX_CONDITION_REGISTER;
+ /****************************************
+ ************ Test case 1 ***************
+ ******** REG read MCU chip id **********
+ ****************************************/
+ pr_info("STEP test: TC 1\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+
+ snprintf(buf, TEST_BUF_LEN, "#%d", chip_id_idx+1);
+ snprintf(buf2, TEST_BUF_LEN, "0x%08lx", chip_id_offset);
+
+ params[0] = "$0";
+ params[1] = "0";
+ //params[2] = "#1";
+ params[2] = buf;
+ //params[3] = "0x04";
+ params[3] = buf2;
+ params[4] = "1";
+ params[5] = "0";
+ param_num = 6;
+ g_infra_step_env.temp_register[0] = 1;
+
+ g_conninfra_step_test_check.step_check_register_addr = (chip_id_vir_addr + chip_id_offset);
+ __conninfra_step_test_do_cond_register_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do cond register action TC-1) MCU chip id");
+
+ /**********************************************
+ *************** Test case 2 ******************
+ ** REG read chip id by physical address **
+ **********************************************/
+ pr_info("STEP test: TC 2\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$2";
+ params[1] = "0";
+
+ snprintf(buf, TEST_BUF_LEN, "0x%08lx", chip_id_phy_addr);
+ params[2] = buf;
+ //params[3] = "0x04";
+ params[3] = buf2;
+ params[4] = "1";
+ params[5] = "0";
+ param_num = 6;
+ g_infra_step_env.temp_register[2] = 1;
+
+ g_conninfra_step_test_check.step_check_register_addr = (chip_id_vir_addr + chip_id_offset);
+ __conninfra_step_test_do_cond_register_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do cond register action TC-3) MCU chip id by phy");
+
+ /*****************************************
+ ************* Test case 3 ***************
+ ******** REG read over base size ********
+ *****************************************/
+ pr_info("STEP test: TC 3\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$4";
+ params[1] = "0";
+ params[2] = "#1";
+ params[3] = "0x11204";
+ params[4] = "1";
+ params[5] = "0";
+ param_num = 6;
+ g_infra_step_env.temp_register[4] = 10;
+
+ __conninfra_step_test_do_cond_register_action(act_id, param_num, params, -1, &temp_report,
+ "STEP test case failed: (Do cond register action TC-5) Over size");
+
+ /******************************************
+ ************** Test case 4 ***************
+ ***** REG read over base size by phy *****
+ ******************************************/
+ pr_info("STEP test: TC 4\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$5";
+ params[1] = "0";
+
+ first_idx_phy_addr = consys_reg_mng_get_phy_addr_by_idx(0);
+ first_idx_vir_addr = consys_reg_mng_get_virt_addr_by_idx(0);
+
+ if (first_idx_phy_addr != 0 && first_idx_vir_addr != 0) {
+ snprintf(buf, TEST_BUF_LEN, "0x%08lx", first_idx_phy_addr);
+ params[2] = buf;
+ params[3] = "0x204";
+ params[4] = "1";
+ params[5] = "0";
+ param_num = 6;
+ g_infra_step_env.temp_register[5] = 1;
+
+ g_conninfra_step_test_check.step_check_register_addr = (first_idx_vir_addr + 0x204);
+ __conninfra_step_test_do_cond_register_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do cond register action TC-6) Over size by phy");
+ } else {
+ p_report->fail++;
+ pr_err("STEP test case failed: get physical address failed\n");
+ }
+
+ /******************************************
+ ************** Test case 5 ***************
+ *************** REG write ****************
+ ******************************************/
+#if TEST_WRITE_CR_TEST_CASE
+ pr_info("STEP test: TC 5\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+
+ snprintf(buf, TEST_BUF_LEN, "#%d", can_write_idx+1);
+ params[0] = "$6";
+ params[1] = "1";
+ params[2] = buf;
+ params[3] = can_write_offset_char;
+ params[4] = "0x2";
+ param_num = 5;
+ g_infra_step_env.temp_register[6] = 1;
+
+ //g_conninfra_step_test_check.step_check_register_addr = (CON_REG_INFRA_RGU_ADDR + can_write_offset);
+ g_conninfra_step_test_check.step_check_register_addr = (can_write_vir_addr + can_write_offset);
+ g_conninfra_step_test_check.step_check_write_value = 0x2;
+ __conninfra_step_test_do_cond_register_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do cond register action TC-7) REG write");
+#endif
+
+ /******************************************
+ ************** Test case 6 ***************
+ *********** REG write by phy *************
+ ******************************************/
+#if TEST_WRITE_CR_TEST_CASE
+ pr_info("STEP test: TC 6\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$7";
+ params[1] = "1";
+ //if (conninfra_step_test_get_reg_base_phy_addr(buf, 0) == 0) {
+
+ snprintf(buf, TEST_BUF_LEN, "0x%08x", can_write_phy_addr);
+ params[2] = buf;
+ params[3] = can_write_offset_char;
+ params[4] = "0x7";
+ param_num = 5;
+ g_infra_step_env.temp_register[7] = 1;
+
+ //g_conninfra_step_test_check.step_check_register_addr = (CON_REG_INFRA_RGU_ADDR + can_write_offset);
+ g_conninfra_step_test_check.step_check_register_addr = (can_write_vir_addr + can_write_offset);
+ g_conninfra_step_test_check.step_check_write_value = 0x7;
+ __conninfra_step_test_do_cond_register_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do cond register action TC-8) REG write by phy");
+#endif
+ //} else {
+ // p_report->fail++;
+ // pr_err("STEP test case failed: get physical address failed\n");
+ //}
+
+ /******************************************
+ ************** Test case 7 ***************
+ ************* REG write bit **************
+ ******************************************/
+#if TEST_WRITE_CR_TEST_CASE
+ pr_info("STEP test: TC 7\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+
+ snprintf(buf, TEST_BUF_LEN, "#%d", can_write_idx+1);
+ params[0] = "$8";
+ params[1] = "1";
+ params[2] = buf;
+ params[3] = can_write_offset_char;
+ params[4] = "0x321";
+ params[5] = "0x00F";
+ param_num = 6;
+ g_infra_step_env.temp_register[8] = 1;
+
+ g_conninfra_step_test_check.step_check_register_addr = (can_write_vir_addr + can_write_offset);
+ //g_conninfra_step_test_check.step_check_register_addr = (CON_REG_INFRA_RGU_ADDR + can_write_offset);
+ g_conninfra_step_test_check.step_check_write_value = 0x001;
+ g_conninfra_step_test_check.step_test_mask = 0x00F;
+ __conninfra_step_test_do_cond_register_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do cond register action TC-9) REG write bit");
+#endif
+
+ /******************************************
+ ************** Test case 8 **************
+ ********* REG write bit by phy ***********
+ ******************************************/
+#if TEST_WRITE_CR_TEST_CASE
+ pr_info("STEP test: TC 8\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$9";
+ params[1] = "1";
+ snprintf(buf, TEST_BUF_LEN, "0x%08x", can_write_phy_addr);
+ params[2] = buf;
+ params[3] = can_write_offset_char;
+ params[4] = "0x32f";
+ params[5] = "0x002";
+ param_num = 6;
+ g_infra_step_env.temp_register[9] = 1;
+
+ g_conninfra_step_test_check.step_check_register_addr = (can_write_vir_addr + can_write_offset);
+ g_conninfra_step_test_check.step_check_write_value = 0x002;
+ g_conninfra_step_test_check.step_test_mask = 0x002;
+ __conninfra_step_test_do_cond_register_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do cond register action TC-10) REG write bit by phy");
+#endif
+
+ /******************************************
+ ************** Test case 9 **************
+ ********* REG read to temp reg ***********
+ ******************************************/
+ pr_info("STEP test: TC 9\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$8";
+ params[1] = "0";
+ params[2] = "#1";
+ params[3] = "0x08";
+ params[4] = "0x0F0F0F0F";
+ params[5] = "$2";
+ param_num = 6;
+ g_conninfra_step_test_check.step_check_register_addr = (first_idx_vir_addr + 0x08);
+ g_conninfra_step_test_check.step_test_mask = 0x0F0F0F0F;
+ g_conninfra_step_test_check.step_check_temp_register_id = 2;
+ g_infra_step_env.temp_register[8] = 1;
+ __conninfra_step_test_do_register_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do register action TC-11) REG read to temp reg");
+
+ /******************************************
+ ************** Test case 10 **************
+ ******* REG read phy to temp reg *********
+ ******************************************/
+ pr_info("STEP test: TC 12\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$8";
+ params[1] = "0";
+ snprintf(buf, TEST_BUF_LEN, "0x%08lx", first_idx_phy_addr);
+ params[2] = buf;
+ params[3] = "0x08";
+ params[4] = "0x0F0F0F0F";
+ params[5] = "$3";
+ param_num = 6;
+ g_conninfra_step_test_check.step_check_register_addr = (first_idx_vir_addr + 0x08);
+ g_conninfra_step_test_check.step_test_mask = 0x0F0F0F0F;
+ g_conninfra_step_test_check.step_check_temp_register_id = 3;
+ g_infra_step_env.temp_register[8] = 1;
+ __conninfra_step_test_do_register_action(act_id, param_num, params, 0, &temp_report,
+ "STEP test case failed: (Do register action TC-12) REG read phy to temp reg");
+
+ /******************************************
+ ************** Test case 11 **************
+ ************* condition invalid **********
+ ******************************************/
+ pr_info("STEP test: TC 13\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$8";
+ params[1] = "1";
+ params[2] = "#1";
+ params[3] = "0x160";
+ params[4] = "0x123";
+ params[5] = "0xF00";
+ param_num = 6;
+ g_infra_step_env.temp_register[8] = 0;
+
+ __conninfra_step_test_do_cond_register_action(act_id, param_num, params, -1, &temp_report,
+ "STEP test case failed: (Do cond register action TC-13) condition invalid");
+
+ /******************************************
+ ************** Test case 12 **************
+ ********** condition invalid write *******
+ ******************************************/
+ pr_info("STEP test: TC 12\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$6";
+ params[1] = "1";
+ params[2] = "#1";
+ params[3] = "0x110";
+ params[4] = "0x200";
+ param_num = 5;
+ g_infra_step_env.temp_register[6] = 0;
+
+ __conninfra_step_test_do_cond_register_action(act_id, param_num, params, -1, &temp_report,
+ "STEP test case failed: (Do cond register action TC-14) condition invalid write");
+
+ /******************************************
+ ************** Test case 13 **************
+ ********** condition invalid read *******
+ ******************************************/
+ pr_info("STEP test: TC 13\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ conninfra_step_test_clear_temp_register();
+ params[0] = "$0";
+ params[1] = "0";
+ params[2] = "#1";
+ params[3] = "0x08";
+ params[4] = "1";
+ params[5] = "0";
+ param_num = 6;
+ g_infra_step_env.temp_register[0] = 0;
+
+ __conninfra_step_test_do_cond_register_action(act_id, param_num, params, -1, &temp_report,
+ "STEP test case failed: (Do cond register action TC-15) REG write");
+
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Do condition register action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+
+void conninfra_step_test_do_gpio_action(struct step_test_report *p_report)
+{
+ enum step_action_id act_id;
+ char *params[STEP_PARAMETER_SIZE];
+ struct step_action *p_act = NULL;
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+ int param_num;
+
+ pr_info("STEP test: Do GPIO action start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ act_id = STEP_ACTION_INDEX_GPIO;
+ /****************************************
+ ************* Test case 1 **************
+ ************* GPIO read #8 *************
+ ****************************************/
+ pr_info("STEP test: TC 1\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "0";
+ params[1] = "8";
+ param_num = 2;
+
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ if (conninfra_step_do_gpio_action(p_act, NULL) == 0) {
+ pr_info("STEP check: Do gpio action TC-1(Read #8): search(8: )");
+ temp_report.check++;
+ } else {
+ pr_err("STEP test case failed: (Do gpio action TC-1) Read #8\n");
+ temp_report.fail++;
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ temp_report.fail++;
+ pr_err("STEP test case failed: (Do gpio action TC-1) Create failed\n");
+ }
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Do GPIO action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+
+#if 0
+void conninfra_step_test_do_chip_reset_action(struct step_test_report *p_report)
+{
+ enum step_action_id act_id;
+ char *params[STEP_PARAMETER_SIZE];
+ struct step_action *p_act = NULL;
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+ int param_num;
+
+ pr_info("STEP test: Do chip reset action start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ act_id = STEP_ACTION_INDEX_CHIP_RESET;
+ /****************************************
+ ************* Test case 1 **************
+ ************* chip reset ***************
+ ****************************************/
+ pr_info("STEP test: TC 1\n");
+ param_num = 0;
+
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ if (wmt_step_do_chip_reset_action(p_act, NULL) == 0) {
+ pr_info("STEP check: Do chip reset TC-1(chip reset): Trigger AEE");
+ temp_report.check++;
+ } else {
+ pr_err("STEP test case failed: (Do chip reset action TC-1) chip reset\n");
+ temp_report.fail++;
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ temp_report.fail++;
+ pr_err("STEP test case failed: (Do chip reset action TC-1) Create failed\n");
+ }
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Do chip reset action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+#endif
+
+#if 0
+void wmt_step_test_do_wakeup_action(struct step_test_report *p_report)
+{
+ enum step_action_id act_id;
+ char *params[STEP_PARAMETER_SIZE];
+ struct step_action *p_act = NULL;
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+ int param_num;
+
+ pr_info("STEP test: Do wakeup action start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ /****************************************
+ ************* Test case 1 **************
+ ***** Wakeup then read/write reg *******
+ ****************************************/
+ pr_info("STEP test: TC 1\n");
+ act_id = STEP_ACTION_INDEX_KEEP_WAKEUP;
+ param_num = 0;
+
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ wmt_step_do_keep_wakeup_action(p_act, NULL);
+ conninfra_step_test_do_register_action(&temp_report);
+ conninfra_step_remove_action(p_act);
+ } else {
+ temp_report.fail++;
+ pr_err("STEP test case failed: (Do wakeup) Create failed\n");
+ }
+
+ act_id = STEP_ACTION_INDEX_CANCEL_WAKEUP;
+ param_num = 0;
+
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ wmt_step_do_cancel_wakeup_action(p_act, NULL);
+ conninfra_step_remove_action(p_act);
+ } else {
+ temp_report.fail++;
+ pr_err("STEP test case failed: (Do cancel wakeup) Create failed\n");
+ }
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Do wakeup action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+#endif
+
+void conninfra_step_test_do_show_action(struct step_test_report *p_report)
+{
+ enum step_action_id act_id;
+ char *params[STEP_PARAMETER_SIZE];
+ struct step_action *p_act = NULL;
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+ int param_num;
+
+ pr_info("STEP test: Do show action start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ act_id = STEP_ACTION_INDEX_SHOW_STRING;
+ /****************************************
+ ************* Test case 1 **************
+ ********** Show Hello world ************
+ ****************************************/
+ pr_info("STEP test: TC 1\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "Hello_World";
+ param_num = 1;
+
+ g_conninfra_step_test_check.step_check_result_string = "Hello_World";
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ conninfra_step_do_show_string_action(p_act, conninfra_step_test_check_show_act);
+ if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ temp_report.pass++;
+ } else {
+ pr_err("STEP test case failed: Do show TC-1(Show Hello world)\n");
+ temp_report.fail++;
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ temp_report.fail++;
+ pr_err("STEP test case failed: Do show TC-1(Show Hello world) Create failed\n");
+ }
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Do show action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+
+#if 1
+void conninfra_step_test_do_sleep_action(struct step_test_report *p_report)
+{
+ enum step_action_id act_id;
+ char *params[STEP_PARAMETER_SIZE];
+ struct step_action *p_act = NULL;
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+ int check_sec_b, check_sec_e;
+ int check_usec_b, check_usec_e;
+ int param_num;
+
+ pr_info("STEP test: Do sleep action start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ act_id = STEP_ACTION_INDEX_SLEEP;
+ /****************************************
+ ************* Test case 1 **************
+ *************** Sleep 1s ***************
+ ****************************************/
+ pr_info("STEP test: TC 1\n");
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "1000";
+ param_num = 1;
+
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ osal_gettimeofday(&check_sec_b, &check_usec_b);
+ conninfra_step_do_sleep_action(p_act, NULL);
+ osal_gettimeofday(&check_sec_e, &check_usec_e);
+ if (check_sec_e > check_sec_b) {
+ temp_report.pass++;
+ } else {
+ pr_err("STEP test case failed: Do show TC-1(Sleep 1s), begin(%d.%d) end(%d.%d)\n",
+ check_sec_b, check_usec_b, check_sec_e, check_usec_e);
+ temp_report.fail++;
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ temp_report.fail++;
+ pr_err("STEP test case failed: Do show TC-1(Sleep 1s) Create failed\n");
+ }
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Do sleep action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+#endif
+
+#if 1
+void conninfra_step_test_do_condition_action(struct step_test_report *p_report)
+{
+ enum step_action_id act_id;
+ char *params[STEP_PARAMETER_SIZE];
+ struct step_action *p_act = NULL;
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+ int param_num;
+
+ pr_info("STEP test: Do condition action start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ act_id = STEP_ACTION_INDEX_CONDITION;
+ /****************************************
+ ************* Test case 1 **************
+ *********** Condition equal ************
+ ****************************************/
+ pr_info("STEP test: TC 1\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_temp_register();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$0";
+ params[1] = "$1";
+ params[2] = "==";
+ params[3] = "$2";
+ param_num = 4;
+
+ g_conninfra_step_test_check.step_check_result_value = 1;
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ conninfra_step_do_condition_action(p_act, conninfra_step_test_check_condition);
+ if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ temp_report.pass++;
+ } else {
+ pr_err("STEP test case failed: Do condition TC-1(equal)\n");
+ temp_report.fail++;
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ temp_report.fail++;
+ pr_err("STEP test case failed: Do condition TC-1(equal) Create failed\n");
+ }
+
+ /****************************************
+ ************* Test case 2 **************
+ ********** Condition greater ***********
+ ****************************************/
+ pr_info("STEP test: TC 2\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_temp_register();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$0";
+ params[1] = "$1";
+ params[2] = ">";
+ params[3] = "$2";
+ param_num = 4;
+ g_infra_step_env.temp_register[1] = 0;
+ g_infra_step_env.temp_register[2] = 1;
+
+ g_conninfra_step_test_check.step_check_result_value = 0;
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ conninfra_step_do_condition_action(p_act, conninfra_step_test_check_condition);
+ if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ temp_report.pass++;
+ } else {
+ pr_err("STEP test case failed: Do condition TC-2(greater)\n");
+ temp_report.fail++;
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ temp_report.fail++;
+ pr_err("STEP test case failed: Do condition TC-2(greater) Create failed\n");
+ }
+
+ /****************************************
+ ************* Test case 3 **************
+ ******* Condition greater equal ********
+ ****************************************/
+ pr_info("STEP test: TC 3\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_temp_register();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$0";
+ params[1] = "$1";
+ params[2] = ">=";
+ params[3] = "$2";
+ param_num = 4;
+ g_infra_step_env.temp_register[1] = 2;
+ g_infra_step_env.temp_register[2] = 2;
+
+ g_conninfra_step_test_check.step_check_result_value = 1;
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ conninfra_step_do_condition_action(p_act, conninfra_step_test_check_condition);
+ if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ temp_report.pass++;
+ } else {
+ pr_err("STEP test case failed: Do condition TC-3(greater equal)\n");
+ temp_report.fail++;
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ temp_report.fail++;
+ pr_err("STEP test case failed: Do condition TC-3(greater equal) Create failed\n");
+ }
+
+ /****************************************
+ ************* Test case 4 **************
+ ************ Condition less ************
+ ****************************************/
+ pr_info("STEP test: TC 4\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_temp_register();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$0";
+ params[1] = "$1";
+ params[2] = "<";
+ params[3] = "$2";
+ param_num = 4;
+ g_infra_step_env.temp_register[1] = 10;
+ g_infra_step_env.temp_register[2] = 0;
+
+ g_conninfra_step_test_check.step_check_result_value = 0;
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ conninfra_step_do_condition_action(p_act, conninfra_step_test_check_condition);
+ if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ temp_report.pass++;
+ } else {
+ pr_err("STEP test case failed: Do condition TC-4(less)\n");
+ temp_report.fail++;
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ temp_report.fail++;
+ pr_err("STEP test case failed: Do condition TC-4(less) Create failed\n");
+ }
+
+ /****************************************
+ ************* Test case 5 **************
+ ********* Condition less equal *********
+ ****************************************/
+ pr_info("STEP test: TC 5\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_temp_register();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$0";
+ params[1] = "$1";
+ params[2] = "<=";
+ params[3] = "$2";
+ param_num = 4;
+ g_infra_step_env.temp_register[1] = 0;
+ g_infra_step_env.temp_register[2] = 10;
+
+ g_conninfra_step_test_check.step_check_result_value = 1;
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ conninfra_step_do_condition_action(p_act, conninfra_step_test_check_condition);
+ if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ temp_report.pass++;
+ } else {
+ pr_err("STEP test case failed: Do condition TC-5(less equal)\n");
+ temp_report.fail++;
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ temp_report.fail++;
+ pr_err("STEP test case failed: Do condition TC-5(less equal) Create failed\n");
+ }
+
+ /****************************************
+ ************* Test case 6 **************
+ ********* Condition not equal **********
+ ****************************************/
+ pr_info("STEP test: TC 6\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_temp_register();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$1";
+ params[1] = "$2";
+ params[2] = "!=";
+ params[3] = "$3";
+ param_num = 4;
+ g_infra_step_env.temp_register[2] = 3;
+ g_infra_step_env.temp_register[3] = 3;
+
+ g_conninfra_step_test_check.step_check_result_value = 0;
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ conninfra_step_do_condition_action(p_act, conninfra_step_test_check_condition);
+ if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ temp_report.pass++;
+ } else {
+ pr_err("STEP test case failed: Do condition TC-6(not equal)\n");
+ temp_report.fail++;
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ temp_report.fail++;
+ pr_err("STEP test case failed: Do condition TC-6(not equal) Create failed\n");
+ }
+
+ /****************************************
+ ************* Test case 7 **************
+ ************ Condition and *************
+ ****************************************/
+ pr_info("STEP test: TC 7\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_temp_register();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$1";
+ params[1] = "$2";
+ params[2] = "&&";
+ params[3] = "$3";
+ param_num = 4;
+ g_infra_step_env.temp_register[2] = 0x10;
+ g_infra_step_env.temp_register[3] = 0x00;
+
+ g_conninfra_step_test_check.step_check_result_value = 0;
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ conninfra_step_do_condition_action(p_act, conninfra_step_test_check_condition);
+ if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ temp_report.pass++;
+ } else {
+ pr_err("STEP test case failed: Do condition TC-7(and)\n");
+ temp_report.fail++;
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ temp_report.fail++;
+ pr_err("STEP test case failed: Do condition TC-7(and) Create failed\n");
+ }
+
+ /****************************************
+ ************* Test case 8 **************
+ ************* Condition or *************
+ ****************************************/
+ pr_info("STEP test: TC 8\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_temp_register();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$1";
+ params[1] = "$2";
+ params[2] = "||";
+ params[3] = "$3";
+ param_num = 4;
+ g_infra_step_env.temp_register[2] = 0x10;
+ g_infra_step_env.temp_register[3] = 0x00;
+
+ g_conninfra_step_test_check.step_check_result_value = 1;
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ conninfra_step_do_condition_action(p_act, conninfra_step_test_check_condition);
+ if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ temp_report.pass++;
+ } else {
+ pr_err("STEP test case failed: Do condition TC-8(or)\n");
+ temp_report.fail++;
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ temp_report.fail++;
+ pr_err("STEP test case failed: Do condition TC-8(or) Create failed\n");
+ }
+
+ /****************************************
+ ************* Test case 9 **************
+ ****** Condition not equal value *******
+ ****************************************/
+ pr_info("STEP test: TC 9\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_temp_register();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$1";
+ params[1] = "$2";
+ params[2] = "!=";
+ params[3] = "99";
+ param_num = 4;
+ g_infra_step_env.temp_register[2] = 99;
+
+ g_conninfra_step_test_check.step_check_result_value = 0;
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ conninfra_step_do_condition_action(p_act, conninfra_step_test_check_condition);
+ if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ temp_report.pass++;
+ } else {
+ pr_err("STEP test case failed: Do condition TC-9(not equal value)\n");
+ temp_report.fail++;
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ temp_report.fail++;
+ pr_err("STEP test case failed: Do condition TC-9(not equal value) Create failed\n");
+ }
+
+ /****************************************
+ ************* Test case 10 *************
+ ********* Condition equal value ********
+ ****************************************/
+ pr_info("STEP test: TC 10\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_temp_register();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$1";
+ params[1] = "$2";
+ params[2] = "==";
+ params[3] = "18";
+ param_num = 4;
+ g_infra_step_env.temp_register[2] = 18;
+
+ g_conninfra_step_test_check.step_check_result_value = 1;
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ conninfra_step_do_condition_action(p_act, conninfra_step_test_check_condition);
+ if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ temp_report.pass++;
+ } else {
+ pr_err("STEP test case failed: Do condition TC-10(equal value)\n");
+ temp_report.fail++;
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ temp_report.fail++;
+ pr_err("STEP test case failed: Do condition TC-10(equal value) Create failed\n");
+ }
+
+ /****************************************
+ ************* Test case 11 *************
+ ****** Condition equal value (HEX) *****
+ ****************************************/
+ pr_info("STEP test: TC 10\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_temp_register();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$1";
+ params[1] = "$2";
+ params[2] = "==";
+ params[3] = "0x18";
+ param_num = 4;
+ g_infra_step_env.temp_register[2] = 24;
+
+ g_conninfra_step_test_check.step_check_result_value = 1;
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ conninfra_step_do_condition_action(p_act, conninfra_step_test_check_condition);
+ if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ temp_report.pass++;
+ } else {
+ pr_err("STEP test case failed: Do condition TC-11(equal value HEX)\n");
+ temp_report.fail++;
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ temp_report.fail++;
+ pr_err("STEP test case failed: Do condition TC-11(equal value HEX) Create failed\n");
+ }
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Do condition action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+#endif
+
+#if 1
+void conninfra_step_test_do_value_action(struct step_test_report *p_report)
+{
+ enum step_action_id act_id;
+ char *params[STEP_PARAMETER_SIZE];
+ struct step_action *p_act = NULL;
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+ int param_num;
+
+ pr_info("STEP test: Do value action start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+ act_id = STEP_ACTION_INDEX_VALUE;
+ /****************************************
+ ************* Test case 1 **************
+ ******* Save value to register *********
+ ****************************************/
+ pr_info("STEP test: TC 1\n");
+ conninfra_step_test_clear_check_data();
+ conninfra_step_test_clear_temp_register();
+ conninfra_step_test_clear_parameter(params);
+ params[0] = "$2";
+ params[1] = "0x66";
+ param_num = 2;
+
+ g_conninfra_step_test_check.step_check_result_value = 0x66;
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ conninfra_step_do_value_action(p_act, conninfra_step_test_check_value_act);
+ if (g_conninfra_step_test_check.step_check_result == TEST_PASS) {
+ temp_report.pass++;
+ } else {
+ pr_err("STEP test case failed: Do show TC-1(Save value to register)");
+ temp_report.fail++;
+ }
+ conninfra_step_remove_action(p_act);
+ } else {
+ temp_report.fail++;
+ pr_err("STEP test case failed: Do show TC-1(Save value to register) Create failed\n");
+ }
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Do value action result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+#endif
+
+#if 1
+void conninfra_step_test_create_periodic_dump(struct step_test_report *p_report)
+{
+ int expires_ms;
+ struct step_test_report temp_report = {0, 0, 0};
+ int sec_begin = 0;
+ int usec_begin = 0;
+ int sec_end = 0;
+ int usec_end = 0;
+ struct step_pd_entry *p_current;
+ bool is_thread_run_for_test = 0;
+
+ pr_info("STEP test: Create periodic dump start\n");
+ osal_gettimeofday(&sec_begin, &usec_begin);
+
+ if (g_infra_step_env.pd_struct.step_pd_wq == NULL) {
+ if (conninfra_step_init_pd_env() != 0) {
+ pr_err("STEP test case failed: Start thread failed\n");
+ return;
+ }
+ is_thread_run_for_test = 1;
+ }
+
+ /****************************************
+ ************* Test case 1 **************
+ *************** Normal *****************
+ ****************************************/
+ pr_info("STEP test: TC 1\n");
+ expires_ms = 5;
+ p_current = conninfra_step_get_periodic_dump_entry(expires_ms);
+ if (p_current == NULL) {
+ pr_err("STEP test case failed: (Create periodic dump TC-1) No entry\n");
+ temp_report.fail++;
+ } else {
+ if (p_current->expires_ms == expires_ms) {
+ temp_report.pass++;
+ } else {
+ pr_err("STEP test case failed: (Create periodic dump TC-1) Currect %d not %d\n",
+ p_current->expires_ms, expires_ms);
+ temp_report.fail++;
+ }
+ list_del_init(&p_current->list);
+ kfree(p_current);
+ }
+
+ if (is_thread_run_for_test == 1)
+ conninfra_step_deinit_pd_env();
+
+ osal_gettimeofday(&sec_end, &usec_end);
+ conninfra_step_test_show_result_report("STEP result: Create periodic dump result",
+ &temp_report, sec_begin, usec_begin, sec_end, usec_end);
+ conninfra_step_test_update_result_report(p_report, &temp_report);
+}
+#endif
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/conninfra_step_test_util.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/conninfra_step_test_util.c
new file mode 100755
index 0000000..b1c59b6
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/conninfra_step_test_util.c
@@ -0,0 +1,577 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include "conninfra_step.h"
+#include "conninfra_step_test.h"
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <asm/io.h>
+#include "emi_mng.h"
+#include "consys_hw.h"
+#include "consys_reg_mng.h"
+#include "consys_reg_util.h"
+
+
+void conninfra_step_test_update_result(int result, struct step_test_report *p_report, char *err_result)
+{
+ if (result != TEST_FAIL) {
+ p_report->pass++;
+ } else {
+ pr_err("%s", err_result);
+ p_report->fail++;
+ }
+}
+
+void conninfra_step_test_update_result_report(struct step_test_report *p_dest_report,
+ struct step_test_report *p_src_report)
+{
+ p_dest_report->pass += p_src_report->pass;
+ p_dest_report->fail += p_src_report->fail;
+ p_dest_report->check += p_src_report->check;
+}
+
+void conninfra_step_test_show_result_report(char *test_name, struct step_test_report *p_report, int sec_begin, int usec_begin,
+ int sec_end, int usec_end)
+{
+ unsigned int total = 0;
+ unsigned int pass = 0;
+ unsigned int fail = 0;
+ unsigned int check = 0;
+ int sec = 0;
+ int usec = 0;
+
+ pass = p_report->pass;
+ fail = p_report->fail;
+ check = p_report->check;
+
+ if (usec_end >= usec_begin) {
+ sec = sec_end - sec_begin;
+ usec = usec_end - usec_begin;
+ } else {
+ sec = sec_end - sec_begin - 1;
+ usec = usec_end - usec_begin + 1000000;
+ }
+
+ total = pass + fail + check;
+ pr_info("%s Total: %d, PASS: %d, FAIL: %d, CHECK: %d, Spend Time: %d.%.6d\n",
+ test_name, total, pass, fail, check, sec, usec);
+}
+
+static int conninfra_step_test_check_create_read_reg(struct step_register_info *p_reg_info,
+ int check_params[], char *err_result, int check_index)
+{
+ int result = TEST_FAIL;
+
+ if (p_reg_info->address_type == 0 /*STEP_REGISTER_PHYSICAL_ADDRESS*/) {
+ if (p_reg_info->address != check_params[check_index + 1] ||
+ p_reg_info->offset != check_params[check_index + 2]) {
+ pr_err(
+ "%s, C1 reg params: %d, %p, %d\n",
+ err_result, p_reg_info->is_write, p_reg_info->address,
+ p_reg_info->offset);
+ return TEST_FAIL;
+ }
+ } else {
+ if (p_reg_info->address_type != check_params[check_index + 1] ||
+ p_reg_info->offset != check_params[check_index + 2]) {
+ pr_err(
+ "%s, C2 reg params: %d, %p, %d\n",
+ err_result, p_reg_info->is_write, p_reg_info->address,
+ p_reg_info->offset);
+ return TEST_FAIL;
+ }
+ }
+
+ if (p_reg_info->output_mode == STEP_OUTPUT_LOG) {
+ if (p_reg_info->times != check_params[check_index + 3] ||
+ p_reg_info->delay_time != check_params[check_index + 4]) {
+ pr_err(
+ "%s, C3 reg params: %d, %p, %d, %d, %d\n",
+ err_result, p_reg_info->is_write, p_reg_info->address,
+ p_reg_info->offset, p_reg_info->times, p_reg_info->delay_time);
+ result = TEST_FAIL;
+ } else {
+ result = TEST_PASS;
+ }
+ } else if (p_reg_info->output_mode == STEP_OUTPUT_REGISTER) {
+ if (p_reg_info->mask != check_params[check_index + 3] ||
+ p_reg_info->temp_reg_id != check_params[check_index + 4]) {
+ pr_err(
+ "%s, C4 reg params: %d, %p, %d, %d, %d\n",
+ err_result, p_reg_info->is_write, p_reg_info->address,
+ p_reg_info->offset, p_reg_info->mask, p_reg_info->temp_reg_id);
+ result = TEST_FAIL;
+ } else {
+ result = TEST_PASS;
+ }
+ } else {
+ result = TEST_FAIL;
+ }
+
+ return result;
+}
+
+static int conninfra_step_test_check_create_write_reg(struct step_register_info *p_reg_info,
+ int check_params[], char *err_result, int check_index)
+{
+ int result = TEST_FAIL;
+
+ if (p_reg_info->address_type == 0 /*STEP_REGISTER_PHYSICAL_ADDRESS*/) {
+ if (p_reg_info->address != check_params[check_index + 1] ||
+ p_reg_info->offset != check_params[check_index + 2] ||
+ p_reg_info->value != check_params[check_index + 3]) {
+ pr_err(
+ "%s, C1 reg params: %d, %p, %d, %d\n",
+ err_result, p_reg_info->is_write, p_reg_info->address,
+ p_reg_info->offset, p_reg_info->value);
+ result = TEST_FAIL;
+ } else {
+ result = TEST_PASS;
+ }
+ } else {
+ if (p_reg_info->address_type != check_params[check_index + 1] ||
+ p_reg_info->offset != check_params[check_index + 2] ||
+ p_reg_info->value != check_params[check_index + 3]) {
+ pr_err(
+ "%s, C2 reg params: %d, %p, %d, %d\n",
+ err_result, p_reg_info->is_write, p_reg_info->address_type,
+ p_reg_info->offset, p_reg_info->value);
+ result = TEST_FAIL;
+ } else {
+ result = TEST_PASS;
+ }
+ }
+
+ return result;
+}
+
+int conninfra_step_test_check_create_emi(struct step_emi_action *p_emi_act, int check_params[],
+ char *err_result)
+{
+ struct step_emi_info *p_emi_info = NULL;
+ int result = TEST_FAIL;
+
+ p_emi_info = &p_emi_act->info;
+ if (p_emi_act->base.action_id != STEP_ACTION_INDEX_EMI) {
+ pr_err("%s, id wrong: %d\n", err_result, p_emi_act->base.action_id);
+ result = TEST_FAIL;
+ } else if (p_emi_info->output_mode == STEP_OUTPUT_LOG) {
+ if (p_emi_info->is_write != check_params[0] ||
+ p_emi_info->begin_offset != check_params[1] ||
+ p_emi_info->end_offset != check_params[2]) {
+ pr_err("%s, C1 emi log params: %d, %d, %d\n",
+ err_result, p_emi_info->is_write, p_emi_info->begin_offset,
+ p_emi_info->end_offset);
+ result = TEST_FAIL;
+ } else {
+ result = TEST_PASS;
+ }
+ } else if (p_emi_info->output_mode == STEP_OUTPUT_REGISTER) {
+ if (p_emi_info->is_write != check_params[0] ||
+ p_emi_info->begin_offset != check_params[1] ||
+ p_emi_info->mask != check_params[2] ||
+ p_emi_info->temp_reg_id != check_params[3]) {
+ pr_err("%s, C2 emi reg params: %d, %d, %d, %d\n",
+ err_result, p_emi_info->is_write, p_emi_info->begin_offset,
+ p_emi_info->mask, p_emi_info->temp_reg_id);
+ result = TEST_FAIL;
+ } else {
+ result = TEST_PASS;
+ }
+ } else {
+ result = TEST_FAIL;
+ }
+
+ return result;
+}
+
+int conninfra_step_test_check_create_reg(struct step_register_action *p_reg_act, int check_params[],
+ char *err_result)
+{
+ struct step_register_info *p_reg_info = NULL;
+ int result = TEST_FAIL;
+
+ p_reg_info = &p_reg_act->info;
+ if (p_reg_act->base.action_id != STEP_ACTION_INDEX_REGISTER) {
+ pr_err("%s, id wrong: %d\n", err_result, p_reg_act->base.action_id);
+ result = TEST_FAIL;
+ } else if (p_reg_info->is_write != check_params[0]) {
+ pr_err("%s, write failed: %d expect(%d)", err_result, p_reg_info->is_write, check_params[0]);
+ result = TEST_FAIL;
+ } else {
+ if (p_reg_info->is_write == 0)
+ result = conninfra_step_test_check_create_read_reg(p_reg_info, check_params, err_result, 0);
+ else
+ result = conninfra_step_test_check_create_write_reg(p_reg_info, check_params, err_result, 0);
+ }
+
+ return result;
+}
+
+
+
+int conninfra_step_test_check_create_condition_emi(struct step_condition_emi_action *p_cond_emi_act, int check_params[],
+ char *err_result)
+{
+ struct step_emi_info *p_emi_info = NULL;
+ int result = TEST_FAIL;
+
+ p_emi_info = &p_cond_emi_act->info;
+ if (p_cond_emi_act->base.action_id != STEP_ACTION_INDEX_CONDITION_EMI) {
+ pr_err("%s, id wrong: %d\n", err_result, p_cond_emi_act->base.action_id);
+ result = TEST_FAIL;
+ } else if (p_emi_info->output_mode == STEP_OUTPUT_LOG) {
+ if (p_cond_emi_act->cond_reg_id != check_params[0] ||
+ p_emi_info->is_write != check_params[1] ||
+ p_emi_info->begin_offset != check_params[2] ||
+ p_emi_info->end_offset != check_params[3]) {
+ pr_err("%s, C1 emi log params: %d, %d, %d, %d\n",
+ err_result, p_cond_emi_act->cond_reg_id, p_emi_info->is_write,
+ p_emi_info->begin_offset, p_emi_info->end_offset);
+ result = TEST_FAIL;
+ } else {
+ result = TEST_PASS;
+ }
+ } else if (p_emi_info->output_mode == STEP_OUTPUT_REGISTER) {
+ if (p_cond_emi_act->cond_reg_id != check_params[0] ||
+ p_emi_info->is_write != check_params[1] ||
+ p_emi_info->begin_offset != check_params[2] ||
+ p_emi_info->mask != check_params[3] ||
+ p_emi_info->temp_reg_id != check_params[4]) {
+ pr_err("%s, C2 emi reg params: %d, %d, %d, %d, %d\n",
+ err_result, p_cond_emi_act->cond_reg_id, p_emi_info->is_write,
+ p_emi_info->begin_offset, p_emi_info->mask, p_emi_info->temp_reg_id);
+ result = TEST_FAIL;
+ } else {
+ result = TEST_PASS;
+ }
+ } else {
+ result = TEST_FAIL;
+ }
+
+ return result;
+}
+
+int conninfra_step_test_check_create_condition_reg(struct step_condition_register_action *p_cond_reg_act, int check_params[],
+ char *err_result)
+{
+ struct step_register_info *p_reg_info = NULL;
+ int result = TEST_FAIL;
+
+ p_reg_info = &p_cond_reg_act->info;
+ if (p_cond_reg_act->base.action_id != STEP_ACTION_INDEX_CONDITION_REGISTER) {
+ pr_err("%s, id wrong: %d\n", err_result, p_cond_reg_act->base.action_id);
+ result = TEST_FAIL;
+ } else if (p_cond_reg_act->cond_reg_id != check_params[0]) {
+ pr_err("%s, reg id failed: %d expect(%d)", err_result,
+ p_cond_reg_act->cond_reg_id, check_params[0]);
+ result = TEST_FAIL;
+ } else if (p_reg_info->is_write != check_params[1]) {
+ pr_err("%s, write failed: %d expect(%d)", err_result,
+ p_reg_info->is_write, check_params[1]);
+ result = TEST_FAIL;
+ } else {
+ if (p_reg_info->is_write == 0)
+ result = conninfra_step_test_check_create_read_reg(p_reg_info, check_params, err_result, 1);
+ else
+ result = conninfra_step_test_check_create_write_reg(p_reg_info, check_params, err_result, 1);
+ }
+
+ return result;
+}
+
+int conninfra_step_test_check_create_gpio(struct step_gpio_action *p_gpio_act, int check_params[],
+ char *err_result)
+{
+ int result = TEST_FAIL;
+
+ if (p_gpio_act->base.action_id != STEP_ACTION_INDEX_GPIO) {
+ pr_err("%s, id wrong: %d\n", err_result, p_gpio_act->base.action_id);
+ result = TEST_FAIL;
+ } else if (p_gpio_act->is_write != check_params[0]) {
+ pr_err("%s, write failed: %d", err_result, p_gpio_act->is_write);
+ result = TEST_FAIL;
+ } else {
+ if (p_gpio_act->pin_symbol != check_params[1]) {
+ pr_err("%s, gpio params: %d, %d\n",
+ err_result, p_gpio_act->is_write, p_gpio_act->pin_symbol);
+ result = TEST_FAIL;
+ } else {
+ result = TEST_PASS;
+ }
+ }
+
+ return result;
+}
+
+int conninfra_step_test_check_create_periodic_dump(struct step_periodic_dump_action *p_pd_act,
+ int check_params[], char *err_result)
+{
+ int result = TEST_FAIL;
+
+ if (p_pd_act->base.action_id != STEP_ACTION_INDEX_PERIODIC_DUMP) {
+ pr_err("%s, id wrong: %d\n", err_result, p_pd_act->base.action_id);
+ result = TEST_FAIL;
+ } else {
+ result = TEST_PASS;
+ }
+
+ return result;
+}
+
+int conninfra_step_test_check_create_show_string(struct step_show_string_action *p_show_act,
+ int check_params[], char *err_result)
+{
+ int result = TEST_FAIL;
+
+ if (p_show_act->base.action_id != STEP_ACTION_INDEX_SHOW_STRING) {
+ pr_err("%s, id wrong: %d\n", err_result, p_show_act->base.action_id);
+ result = TEST_FAIL;
+ } else {
+ result = TEST_PASS;
+ }
+
+ return result;
+}
+
+int conninfra_step_test_check_create_sleep(struct step_sleep_action *p_sleep_act,
+ int check_params[], char *err_result)
+{
+ int result = TEST_FAIL;
+
+ if (p_sleep_act->base.action_id != STEP_ACTION_INDEX_SLEEP) {
+ pr_err("%s, id wrong: %d\n", err_result, p_sleep_act->base.action_id);
+ result = TEST_FAIL;
+ } else if (p_sleep_act->ms != check_params[0]) {
+ pr_err("%s, param failed: %d expect(%d)", err_result, p_sleep_act->ms, check_params[0]);
+ result = TEST_FAIL;
+ } else {
+ result = TEST_PASS;
+ }
+
+ return result;
+}
+
+int conninfra_step_test_check_create_condition(struct step_condition_action *p_cond_act,
+ int check_params[], char *err_result)
+{
+ int result = TEST_FAIL;
+
+ if (p_cond_act->base.action_id != STEP_ACTION_INDEX_CONDITION) {
+ pr_err("%s, id wrong: %d\n", err_result, p_cond_act->base.action_id);
+ result = TEST_FAIL;
+ } else if (p_cond_act->result_temp_reg_id != check_params[0] ||
+ p_cond_act->l_temp_reg_id != check_params[1] ||
+ p_cond_act->operator_id != check_params[2]) {
+ pr_err("%s, C1 param failed: %d %d %d %d expect(%d %d %d %d)",
+ err_result, p_cond_act->result_temp_reg_id, p_cond_act->l_temp_reg_id,
+ p_cond_act->operator_id, p_cond_act->r_temp_reg_id,
+ check_params[0], check_params[1], check_params[2], check_params[3]);
+ result = TEST_FAIL;
+ } else {
+ if (p_cond_act->mode == STEP_CONDITION_RIGHT_REGISTER && p_cond_act->r_temp_reg_id != check_params[3]) {
+ pr_err("%s, C2 param failed: %d %d %d %d expect(%d %d %d %d)",
+ err_result, p_cond_act->result_temp_reg_id, p_cond_act->l_temp_reg_id,
+ p_cond_act->operator_id, p_cond_act->r_temp_reg_id,
+ check_params[0], check_params[1], check_params[2], check_params[3]);
+ result = TEST_FAIL;
+ } else if (p_cond_act->mode == STEP_CONDITION_RIGHT_VALUE && p_cond_act->value != check_params[3]) {
+ pr_err("%s, C3 param failed: %d %d %d %d expect(%d %d %d %d)",
+ err_result, p_cond_act->result_temp_reg_id, p_cond_act->l_temp_reg_id,
+ p_cond_act->operator_id, p_cond_act->value,
+ check_params[0], check_params[1], check_params[2], check_params[3]);
+ result = TEST_FAIL;
+ } else {
+ result = TEST_PASS;
+ }
+ }
+
+ return result;
+}
+
+int conninfra_step_test_check_create_value(struct step_value_action *p_val_act,
+ int check_params[], char *err_result)
+{
+ int result = TEST_FAIL;
+
+ if (p_val_act->base.action_id != STEP_ACTION_INDEX_VALUE) {
+ pr_err("%s, id wrong: %d\n", err_result, p_val_act->base.action_id);
+ result = TEST_FAIL;
+ } else if (p_val_act->temp_reg_id != check_params[0] ||
+ p_val_act->value != check_params[1]) {
+ pr_err("%s, param failed: %d %d expect(%d %d)",
+ err_result, p_val_act->temp_reg_id, p_val_act->value,
+ check_params[0], check_params[1]);
+ result = TEST_FAIL;
+ } else {
+ result = TEST_PASS;
+ }
+
+ return result;
+}
+
+void conninfra_step_test_create_action(enum step_action_id act_id, int param_num, char *params[], int result_of_action,
+ int check_params[], struct step_test_report *p_report, char *err_result)
+{
+ struct step_action *p_act = NULL;
+ int result = TEST_FAIL;
+
+ p_act = conninfra_step_create_action(STEP_DRV_TYPE_CONNINFRA, act_id, param_num, params);
+ if (p_act != NULL) {
+ switch (p_act->action_id) {
+ case STEP_ACTION_INDEX_EMI:
+ {
+ struct step_emi_action *p_emi_act = NULL;
+
+ p_emi_act = clist_entry_action(emi, p_act);
+ result = conninfra_step_test_check_create_emi(p_emi_act, check_params,
+ err_result);
+ }
+ break;
+ case STEP_ACTION_INDEX_REGISTER:
+ {
+ struct step_register_action *p_reg_act = NULL;
+
+ p_reg_act = clist_entry_action(register, p_act);
+ result = conninfra_step_test_check_create_reg(p_reg_act, check_params,
+ err_result);
+ }
+ break;
+ case STEP_ACTION_INDEX_GPIO:
+ {
+ struct step_gpio_action *p_gpio_act = NULL;
+
+ p_gpio_act = clist_entry_action(gpio, p_act);
+ result = conninfra_step_test_check_create_gpio(p_gpio_act, check_params,
+ err_result);
+ }
+ break;
+ case STEP_ACTION_INDEX_PERIODIC_DUMP:
+ {
+ struct step_periodic_dump_action *p_pd_act = NULL;
+
+ p_pd_act = clist_entry_action(periodic_dump, p_act);
+ result = conninfra_step_test_check_create_periodic_dump(p_pd_act,
+ check_params, err_result);
+ }
+ break;
+ case STEP_ACTION_INDEX_SHOW_STRING:
+ {
+ struct step_show_string_action *p_show_act = NULL;
+
+ p_show_act = clist_entry_action(show_string, p_act);
+ result = conninfra_step_test_check_create_show_string(p_show_act,
+ check_params, err_result);
+ }
+ break;
+ case STEP_ACTION_INDEX_SLEEP:
+ {
+ struct step_sleep_action *p_sleep_act = NULL;
+
+ p_sleep_act = clist_entry_action(sleep, p_act);
+ result = conninfra_step_test_check_create_sleep(p_sleep_act,
+ check_params, err_result);
+ }
+ break;
+ case STEP_ACTION_INDEX_CONDITION:
+ {
+ struct step_condition_action *p_cond_act = NULL;
+
+ p_cond_act = clist_entry_action(condition, p_act);
+ result = conninfra_step_test_check_create_condition(p_cond_act,
+ check_params, err_result);
+ }
+ break;
+ case STEP_ACTION_INDEX_VALUE:
+ {
+ struct step_value_action *p_val_act = NULL;
+
+ p_val_act = clist_entry_action(value, p_act);
+ result = conninfra_step_test_check_create_value(p_val_act,
+ check_params, err_result);
+ }
+ break;
+ case STEP_ACTION_INDEX_CONDITION_EMI:
+ {
+ struct step_condition_emi_action *p_cond_emi_act = NULL;
+
+ p_cond_emi_act = clist_entry_action(condition_emi, p_act);
+ result = conninfra_step_test_check_create_condition_emi(p_cond_emi_act, check_params,
+ err_result);
+ }
+ break;
+ case STEP_ACTION_INDEX_CONDITION_REGISTER:
+ {
+ struct step_condition_register_action *p_cond_reg_act = NULL;
+
+ p_cond_reg_act = clist_entry_action(condition_register, p_act);
+ result = conninfra_step_test_check_create_condition_reg(p_cond_reg_act, check_params,
+ err_result);
+ }
+ break;
+ default:
+ result = TEST_FAIL;
+ break;
+ }
+
+ if (result_of_action == -1)
+ result = TEST_FAIL;
+
+ conninfra_step_remove_action(p_act);
+ } else {
+ if (result_of_action == -1)
+ result = TEST_PASS;
+ else
+ result = TEST_FAIL;
+ }
+ conninfra_step_test_update_result(result, p_report, err_result);
+}
+
+/* this offset only for FPGA */
+#define CONNINFRA_STEP_TEST_EMI_COREDUMP_OFFSET 0x4f000
+/* formal chip use this offset*/
+//#define CONNINFRA_STEP_TEST_EMI_COREDUMP_OFFSET 0x27f000
+
+int conninfra_step_test_get_emi_offset(unsigned char buf[], int offset)
+{
+ struct consys_emi_addr_info *emi_phy_addr = NULL;
+
+ emi_phy_addr = emi_mng_get_phy_addr();
+ if (emi_phy_addr != NULL) {
+ /* TODO: fix this, change the region to coredump */
+ snprintf(buf, 11, "0x%08x", (CONNINFRA_STEP_TEST_EMI_COREDUMP_OFFSET + offset));
+ } else {
+ pr_err("STEP test failed: emi_phy_addr is NULL\n");
+ return -1;
+ }
+ return 0;
+}
+
+static unsigned char __iomem *emi_map_addr = NULL;
+
+unsigned char* conninfra_step_test_get_emi_virt_offset(unsigned int offset)
+{
+ struct consys_emi_addr_info *emi_addr_info = NULL;
+
+ if (emi_map_addr == NULL) {
+ emi_addr_info = emi_mng_get_phy_addr();
+ if (emi_addr_info != NULL) {
+ emi_map_addr = ioremap_nocache(emi_addr_info->emi_ap_phy_addr +
+ CONNINFRA_STEP_TEST_EMI_COREDUMP_OFFSET + offset,
+ 0x100);
+ }
+ }
+ return emi_map_addr;
+}
+
+void conninfra_step_test_put_emi_virt_offset(void)
+{
+ if (emi_map_addr != NULL) {
+ iounmap(emi_map_addr);
+ emi_map_addr = NULL;
+ }
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/conninfra_test.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/conninfra_test.c
new file mode 100755
index 0000000..12ec2fa
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/conninfra_test.c
@@ -0,0 +1,512 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#define pr_fmt(fmt) "conninfra_test@(%s:%d) " fmt, __func__, __LINE__
+
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include "conninfra_test.h"
+#include "osal.h"
+
+#include "conninfra.h"
+#include "conninfra_core.h"
+#include "consys_reg_mng.h"
+
+#include "connsyslog_test.h"
+#include "conf_test.h"
+#include "cal_test.h"
+#include "msg_evt_test.h"
+#include "chip_rst_test.h"
+#include "mailbox_test.h"
+#include "conninfra_step_test.h"
+#include "coredump_test.h"
+#include "consys_hw.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+#define CONNINFRA_TEST_PROCNAME "driver/conninfra_test"
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+static ssize_t conninfra_test_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos);
+static ssize_t conninfra_test_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos);
+
+static int core_tc(int par1, int par2, int par3);
+static int conf_tc(int par1, int par2, int par3);
+static int cal_tc(int par1, int par2, int par3);
+static int msg_evt_tc(int par1, int par2, int par3);
+static int chip_rst_tc(int par1, int par2, int par3);
+static int mailbox_tc(int par1, int par2, int par3);
+static int emi_tc(int par1, int par2, int par3);
+static int log_tc(int par1, int par2, int par3);
+static int thermal_tc(int par1, int par2, int par3);
+static int step_tc(int par1, int par2, int par3);
+static int bus_hang_tc(int par1, int par2, int par3);
+static int dump_tc(int par1, int par2, int par3);
+static int is_bus_hang_tc(int par1, int par2, int par3);
+static int ap_resume_tc(int par1, int par2, int par3);
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+static struct proc_dir_entry *gConninfraTestEntry;
+
+static const CONNINFRA_TEST_FUNC conninfra_test_func[] = {
+ [0x01] = core_tc,
+ [0x02] = conf_tc,
+ [0x03] = msg_evt_tc,
+ [0x04] = chip_rst_tc,
+ [0x05] = cal_tc,
+ [0x06] = mailbox_tc,
+ [0x07] = emi_tc,
+ [0x08] = log_tc,
+ [0x09] = thermal_tc,
+ [0x0a] = step_tc,
+ [0x0b] = bus_hang_tc,
+ [0x0c] = dump_tc,
+ [0x0d] = is_bus_hang_tc,
+ [0x0e] = ap_resume_tc,
+};
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+int core_tc_pwr_on(void)
+{
+ int iret = 0;
+
+ pr_info("Power on test start");
+ iret = conninfra_core_power_on(CONNDRV_TYPE_BT);
+ pr_info("BT power on %s (result = %d)", iret? "fail" : "pass", iret);
+ osal_sleep_ms(100);
+ iret = conninfra_core_power_on(CONNDRV_TYPE_FM);
+ pr_info("FM power on %s (result = %d)", iret? "fail" : "pass", iret);
+ osal_sleep_ms(100);
+ iret = conninfra_core_power_on(CONNDRV_TYPE_GPS);
+ pr_info("GPS power on %s (result = %d)", iret? "fail" : "pass", iret);
+ osal_sleep_ms(100);
+ iret = conninfra_core_power_on(CONNDRV_TYPE_WIFI);
+ pr_info("Wi-Fi power on %s (result = %d)", iret? "fail" : "pass", iret);
+ osal_sleep_ms(200);
+
+ return iret;
+}
+
+int core_tc_pwr_off(void)
+{
+ int iret = 0;
+
+ iret = conninfra_core_power_off(CONNDRV_TYPE_WIFI);
+ pr_info("Wi-Fi power off %s (result = %d)", iret? "fail" : "pass", iret);
+ osal_sleep_ms(100);
+ iret = conninfra_core_power_off(CONNDRV_TYPE_GPS);
+ pr_info("GPS power off %s (result = %d)", iret? "fail" : "pass", iret);
+ osal_sleep_ms(100);
+ iret = conninfra_core_power_off(CONNDRV_TYPE_BT);
+ pr_info("BT power off %s (result = %d)", iret? "fail" : "pass", iret);
+ osal_sleep_ms(100);
+ iret = conninfra_core_power_off(CONNDRV_TYPE_FM);
+ pr_info("FM power off %s (result = %d)", iret? "fail" : "pass", iret);
+
+ return iret;
+}
+
+
+int core_tc(int par1, int par2, int par3)
+{
+ int iret = 0;
+ char* driver_name[CONNDRV_TYPE_MAX] = {
+ "BT",
+ "FM",
+ "GPS",
+ "Wi-Fi",
+ };
+
+ if (par2 == 0) {
+ iret = core_tc_pwr_on();
+ iret = core_tc_pwr_off();
+ } else if (par2 == 1) {
+ if (par3 == 15) {
+ iret = core_tc_pwr_on();
+ } else if (par3 >= CONNDRV_TYPE_BT && par3 <= CONNDRV_TYPE_WIFI) {
+ pr_info("Power on %s test start\n", driver_name[par3]);
+ iret = conninfra_core_power_on(par3);
+ pr_info("Power on %s test, return = %d\n", driver_name[par3], iret);
+ } else {
+ pr_info("No support parameter\n");
+ }
+ } else if (par2 == 2) {
+ if (par3 == 15) {
+ iret = core_tc_pwr_off();
+ } else if (par3 >= CONNDRV_TYPE_BT && par3 <= CONNDRV_TYPE_WIFI) {
+ pr_info("Power off %s test start\n", driver_name[par3]);
+ iret = conninfra_core_power_off(par3);
+ pr_info("Power off %s test, return = %d\n", driver_name[par3], iret);
+ } else {
+ pr_info("No support parameter\n");
+ }
+ } else if (par2 == 3) {
+ if (par3 == 1) {
+ iret = conninfra_core_adie_top_ck_en_on(CONNSYS_ADIE_CTL_FW_WIFI);
+ pr_info(
+ "Turn on adie top ck en (ret=%d), please check 0x1805_2830[6] should be 1\n",
+ iret);
+ } else if (par3 == 0) {
+ iret = conninfra_core_adie_top_ck_en_off(CONNSYS_ADIE_CTL_FW_WIFI);
+ pr_info(
+ "Turn off adie top ck en (ret=%d), please check 0x1805_2830[6] should be 1\n",
+ iret);
+ }
+ }
+ //pr_info("core_tc %s (result = %d)", iret? "fail" : "pass", iret);
+ return 0;
+}
+
+static int conf_tc(int par1, int par2, int par3)
+{
+ return conninfra_conf_test();
+}
+
+static int msg_evt_tc(int par1, int par2, int par3)
+{
+ return msg_evt_test();
+}
+
+static int chip_rst_tc(int par1, int par2, int par3)
+{
+ pr_info("test start");
+ return chip_rst_test();
+}
+
+static int cal_tc(int par1, int par2, int par3)
+{
+ pr_info("test start");
+ return calibration_test();
+}
+
+
+static int mailbox_tc(int par1, int par2, int par3)
+{
+ return mailbox_test();
+}
+
+static int emi_tc(int par1, int par2, int par3)
+{
+#if CFG_CONNINFRA_EMI_SUPPORT
+ unsigned int addr = 0;
+ unsigned int size = 0;
+ int ret = 0;
+
+ pr_info("[%s] start", __func__);
+ conninfra_get_phy_addr(&addr, &size);
+ if (addr == 0 || size == 0) {
+ pr_err("[%s] fail! addr=[0x%x] size=[%u]", __func__, addr, size);
+ ret = -1;
+ } else
+ pr_info("[%s] pass. addr=[0x%x] size=[%u]", __func__, addr, size);
+
+ pr_info("[%s] end", __func__);
+
+ return ret;
+#else
+ pr_info("[%s] EMI function is not supported", __func__);
+ return 0;
+#endif
+}
+
+static int thermal_tc(int par1, int par2, int par3)
+{
+#if CFG_CONNINFRA_THERMAL_SUPPORT
+ int ret, temp;
+
+ ret = core_tc_pwr_on();
+ if (ret) {
+ pr_err("pwr on fail");
+ return -1;
+ }
+ ret = conninfra_core_thermal_query(&temp);
+ pr_info("[%s] thermal res=[%d][%d]", __func__, ret, temp);
+
+ return ret;
+#else
+ pr_info("[%s] Thermal function is not supported", __func__);
+ return 0;
+#endif
+}
+
+static int step_tc(int par1, int par2, int par3)
+{
+#if CFG_CONNINFRA_STEP_SUPPORT
+ int ret;
+
+ ret = core_tc_pwr_on();
+ if (ret) {
+ pr_err("pwr on fail");
+ return -1;
+ }
+
+ conninfra_core_force_conninfra_wakeup();
+ conninfra_step_test_all();
+ conninfra_core_force_conninfra_sleep();
+#else
+ pr_info("[%s] function not support", __func__);
+#endif
+ return 0;
+}
+
+static int log_tc(int par1, int par2, int par3)
+{
+#if CFG_CONNINFRA_FW_LOG_SUPPORT
+ /* 0: initial state
+ * 1: log has been init.
+ */
+ static int log_status = 0;
+ int ret = 0;
+
+ if (par2 == 0) {
+ if (log_status != 0) {
+ pr_info("log has been init.\n");
+ return 0;
+ }
+ /* init */
+ ret = connlog_test_init();
+ if (ret)
+ pr_err("FW log init fail! ret=%d\n", ret);
+ else {
+ log_status = 1;
+ pr_info("FW log init finish. Check result on EMI.\n");
+ }
+ } else if (par2 == 1) {
+ /* add fake log */
+ /* read log */
+ connlog_test_read();
+ } else if (par2 == 2) {
+ /* deinit */
+ if (log_status == 0) {
+ pr_info("log didn't init\n");
+ return 0;
+ }
+ ret = connlog_test_deinit();
+ if (ret)
+ pr_err("FW log deinit fail! ret=%d\n", ret);
+ else
+ log_status = 0;
+ }
+ return ret;
+#else
+ pr_info("[%s] function not support", __func__);
+ return 0;
+#endif
+}
+
+
+static int bus_hang_tc(int par1, int par2, int par3)
+{
+#if CFG_CONNINFRA_BUS_HANG_DEBUG_SUPPORT
+ int r;
+ r = conninfra_core_is_bus_hang();
+
+ pr_info("[%s] r=[%d]\n", __func__, r);
+#else
+ pr_info("[%s] function not support", __func__);
+#endif
+ return 0;
+}
+
+static int dump_tc(int par1, int par2, int par3)
+{
+#if CFG_CONNINFRA_COREDUMP_SUPPORT
+ return coredump_test(par1, par2, par3);
+#else
+ pr_info("[%s] function not support", __func__);
+ return 0;
+#endif
+}
+
+static int is_bus_hang_tc(int par1, int par2, int par3)
+{
+#if CFG_CONNINFRA_BUS_HANG_DEBUG_SUPPORT
+ int r;
+
+ r = consys_reg_mng_reg_readable();
+ pr_info("[%s] r=[%d]", __func__, r);
+ r = consys_reg_mng_is_bus_hang();
+ pr_info("[%s] r=[%d]", __func__, r);
+#else
+ pr_info("[%s] function not support", __func__);
+#endif
+ return 0;
+}
+
+static int ap_resume_tc(int par1, int par2, int par3)
+{
+ return 0;
+}
+
+ssize_t conninfra_test_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ return 0;
+}
+
+ssize_t conninfra_test_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos)
+{
+ size_t len = count;
+ char buf[256];
+ char *pBuf;
+ char *pDelimiter = " \t";
+ int x = 0, y = 0, z = 0;
+ char *pToken = NULL;
+ long res = 0;
+ static bool test_enabled = false;
+
+ pr_info("write parameter len = %d\n\r", (int) len);
+ if (len >= osal_sizeof(buf)) {
+ pr_err("input handling fail!\n");
+ len = osal_sizeof(buf) - 1;
+ return -1;
+ }
+
+ if (copy_from_user(buf, buffer, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+ pr_info("write parameter data = %s\n\r", buf);
+
+ pBuf = buf;
+ pToken = osal_strsep(&pBuf, pDelimiter);
+ if (pToken != NULL) {
+ osal_strtol(pToken, 16, &res);
+ x = (int)res;
+ } else {
+ x = 0;
+ }
+
+ pToken = osal_strsep(&pBuf, "\t\n ");
+ if (pToken != NULL) {
+ osal_strtol(pToken, 16, &res);
+ y = (int)res;
+ pr_info("y = 0x%08x\n\r", y);
+ } else {
+ y = 3000;
+ /*efuse, register read write default value */
+ if (0x11 == x || 0x12 == x || 0x13 == x)
+ y = 0x80000000;
+ }
+
+ pToken = osal_strsep(&pBuf, "\t\n ");
+ if (pToken != NULL) {
+ osal_strtol(pToken, 16, &res);
+ z = (int)res;
+ } else {
+ z = 10;
+ /*efuse, register read write default value */
+ if (0x11 == x || 0x12 == x || 0x13 == x)
+ z = 0xffffffff;
+ }
+
+ pr_info("x(0x%08x), y(0x%08x), z(0x%08x)\n\r", x, y, z);
+
+ /* For eng and userdebug load, have to enable conninfra_test by
+ * writing 0xDB9DB9 to * "/proc/driver/conninfra_test" to avoid
+ * some malicious use
+ */
+ if (x == 0xDB9DB9) {
+ test_enabled = true;
+ return len;
+ }
+
+ if (!test_enabled) {
+ pr_err("Please enable conninfra test first");
+ return len;
+ }
+
+ if (osal_array_size(conninfra_test_func) > x &&
+ NULL != conninfra_test_func[x])
+ (*conninfra_test_func[x]) (x, y, z);
+ else
+ pr_warn("no handler defined for command id(0x%08x)\n\r", x);
+
+ return len;
+
+}
+
+
+int conninfra_test_setup(void)
+{
+ static const struct file_operations conninfra_test_fops = {
+ .owner = THIS_MODULE,
+ .read = conninfra_test_read,
+ .write = conninfra_test_write,
+ };
+ int i_ret = 0;
+
+ gConninfraTestEntry = proc_create(CONNINFRA_TEST_PROCNAME,
+ 0664, NULL, &conninfra_test_fops);
+ if (gConninfraTestEntry == NULL) {
+ pr_err("Unable to create / wmt_aee proc entry\n\r");
+ i_ret = -1;
+ }
+
+ return i_ret;
+}
+
+int conninfra_test_remove(void)
+{
+ if (gConninfraTestEntry != NULL)
+ proc_remove(gConninfraTestEntry);
+ return 0;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/connsyslog_test.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/connsyslog_test.c
new file mode 100644
index 0000000..eabcdc3
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/connsyslog_test.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+#define pr_fmt(fmt) "connlog_test@(%s:%d) " fmt, __func__, __LINE__
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+#include <linux/printk.h>
+
+#include "conninfra.h"
+#include "connsys_debug_utility.h"
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+static void connlog_test_event_handler(void);
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+#define TEST_LOG_BUF_SIZE 1*2014
+
+static char test_buf[TEST_LOG_BUF_SIZE];
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+static void connlog_test_event_handler(void)
+{
+ ssize_t read = 0;
+ pr_info("connlog_test_event_handler\n");
+
+ read = connsys_log_read(CONN_DEBUG_TYPE_WIFI, test_buf, TEST_LOG_BUF_SIZE);
+ pr_info("Read %u:\n", read);
+ connsys_log_dump_buf("log_test", test_buf, read);
+ pr_info("============================================\n");
+}
+
+int connlog_test_init(void)
+{
+ unsigned int emi_addr = 0;
+ unsigned int emi_size = 0;
+ int ret;
+
+ conninfra_get_phy_addr(&emi_addr, &emi_size);
+ if (!emi_addr || !emi_size) {
+ pr_err("EMI init fail.\n");
+ return 1;
+ }
+
+ ret = connsys_dedicated_log_path_apsoc_init(emi_addr);
+ if (ret) {
+ pr_err("connsys_dedicated_log_path_apsoc_init should fail\n");
+ return 2;
+ } else {
+ pr_info("connsys_dedicated_log_path_apsoc_init return fail as expection\n");
+ }
+
+ ret = connsys_log_init(CONN_DEBUG_TYPE_WIFI);
+ if (ret) {
+ pr_err("Init connsys log failed\n");
+ return 3;
+ }
+ connsys_log_register_event_cb(CONN_DEBUG_TYPE_WIFI, connlog_test_event_handler);
+ return 0;
+}
+
+int connlog_test_read(void)
+{
+ connsys_log_irq_handler(CONN_DEBUG_TYPE_WIFI);
+ return 0;
+}
+
+int connlog_test_deinit(void)
+{
+ connsys_log_deinit(CONN_DEBUG_TYPE_WIFI);
+ return 0;
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/dump_test.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/dump_test.c
new file mode 100755
index 0000000..c1719f7
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/dump_test.c
@@ -0,0 +1,290 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+#define pr_fmt(fmt) "dump_test@(%s:%d) " fmt, __func__, __LINE__
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+#include <linux/delay.h>
+#include <linux/printk.h>
+
+#include "conninfra.h"
+#include "connsys_debug_utility.h"
+
+#include "coredump_test.h"
+#include "coredump/conndump_netlink.h"
+
+#include "msg_thread.h"
+
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+
+static int coredump_test_init(void);
+static int coredump_test_start(void);
+static int coredump_test_deinit(void);
+
+static int dump_test_reg_readable(void);
+static void dump_test_poll_cpu_pcr(unsigned int times, unsigned int sleep);
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+static void* g_dumpCtx = 0;
+static int nl_init = 0;
+struct msg_thread_ctx g_msg_ctx;
+
+static int init = 0;
+
+typedef enum {
+ DUMP_TEST_OPID_1 = 0,
+ DUMP_TEST_OPID_2 = 1,
+ DUMP_TEST_OPID_MAX
+} test_opid;
+
+
+static int opfunc_test_1(struct msg_op_data *op);
+static int opfunc_test_2(struct msg_op_data *op);
+
+static const msg_opid_func test_op_func[] = {
+ [DUMP_TEST_OPID_1] = opfunc_test_1,
+ [DUMP_TEST_OPID_2] = opfunc_test_2,
+};
+
+struct coredump_event_cb g_cb = {
+ .reg_readable = dump_test_reg_readable,
+ .poll_cpupcr = dump_test_poll_cpu_pcr,
+};
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+static int dump_test_reg_readable(void)
+{
+ return 1;
+}
+
+static void dump_test_poll_cpu_pcr(unsigned int times, unsigned int sleep)
+{
+ pr_info("[%s]\n", __func__);
+}
+
+#define TEST_STRING "this is coredump test"
+
+static int coredump_test_start(void)
+{
+
+ if (!g_dumpCtx) {
+ pr_err("coredump contxt is not init\n");
+ return 1;
+ }
+#if 0
+ pr_info("[%s] tc[0] test case\n", __func__);
+ /* Trigger interrupt */
+ connsys_coredump_setup_tc(g_dumpCtx, 0);
+
+ /* Start to dump */
+ connsys_coredump_start(g_dumpCtx, 0);
+
+ pr_info("[%s] sleep\n", __func__);
+ msleep(5000);
+
+ pr_info("[%s] tc[1] test case\n", __func__);
+ /* Trigger interrupt */
+ connsys_coredump_setup_tc(g_dumpCtx, 1);
+ /* Start to dump */
+ connsys_coredump_start(g_dumpCtx, 0);
+
+ pr_info("[%s] tc[2] test case\n", __func__);
+ /* Trigger interrupt */
+ connsys_coredump_setup_tc(g_dumpCtx, 2);
+ /* Start to dump */
+ connsys_coredump_start(g_dumpCtx, 0);
+#endif
+
+ pr_info("[%s] end\n", __func__);
+ return 0;
+
+}
+
+static int coredump_nl_start(void)
+{
+ int ret;
+
+
+ ret = conndump_netlink_send_to_native(CONN_DEBUG_TYPE_WIFI, "[M]", TEST_STRING, osal_strlen(TEST_STRING));
+ pr_info("send ret=%d", ret);
+ ret = conndump_netlink_send_to_native(CONN_DEBUG_TYPE_WIFI, "[EMI]", NULL, 0);
+ pr_info("send emi dump ret=%d", ret);
+ return 0;
+}
+
+static int coredump_test_init(void)
+{
+ unsigned int emi_addr = 0;
+ unsigned int emi_size = 0;
+
+ if (g_dumpCtx) {
+ pr_err("log handler has been init. Need to deinit.\n");
+ return 1;
+ }
+
+ conninfra_get_phy_addr(&emi_addr, &emi_size);
+ if (!emi_addr || !emi_size) {
+ pr_err("EMI init fail.\n");
+ return 2;
+ }
+
+ pr_info("emi_addr=0x%08x, size=%d", emi_addr, emi_size);
+
+ g_dumpCtx = connsys_coredump_init(
+ CONN_DEBUG_TYPE_WIFI, &g_cb);
+
+ if (!g_dumpCtx) {
+ pr_err("Coredump init fail.\n");
+ return 3;
+ }
+
+ return 0;
+
+}
+
+static void coredump_end_cb(void* ctx) {
+ pr_info("Get dump end");
+}
+
+static int coredump_nl_init(void)
+{
+ int ret;
+ struct netlink_event_cb nl_cb;
+
+ if (!nl_init) {
+ nl_cb.coredump_end = coredump_end_cb;
+ ret = conndump_netlink_init(CONN_DEBUG_TYPE_WIFI, NULL, &nl_cb);
+ pr_info("init get %d", ret);
+ nl_init = 1;
+ }
+ return 0;
+}
+
+static int coredump_test_deinit(void)
+{
+ if (!g_dumpCtx) {
+ pr_err("coredump contxt is not init\n");
+ return 1;
+ }
+
+ connsys_coredump_deinit(g_dumpCtx);
+ return 0;
+}
+
+static int coredump_nl_deinit(void)
+{
+ nl_init = 0;
+ return 0;
+}
+
+int opfunc_test_1(struct msg_op_data *op)
+{
+ int tc = op->op_data[0];
+ int ret = 0;
+
+ pr_info("[%s] param=[%d]", __func__, tc);
+ switch (tc) {
+ case 0:
+ ret = coredump_test_init();
+ break;
+ case 1:
+ ret = coredump_test_start();
+ break;
+ case 2:
+ ret = coredump_test_deinit();
+ break;
+ }
+ pr_info("ret = %d", ret);
+ return 0;
+}
+
+int opfunc_test_2(struct msg_op_data *op)
+{
+ int tc = op->op_data[0];
+ int ret = 0;
+
+ pr_info("[%s] param=[%d]", __func__, tc);
+
+ switch (tc) {
+ case 0:
+ ret = coredump_nl_init();
+ break;
+ case 1:
+ ret = coredump_nl_start();
+ break;
+ case 2:
+ ret = coredump_nl_deinit();
+ break;
+ }
+ pr_info("ret = %d", ret);
+ return 0;
+}
+
+int coredump_test(int par1, int par2, int par3)
+{
+ pr_info("Disable coredump test in SQC\n");
+ init = 1;
+ return 0;
+#if 0
+ int ret = 0;
+
+ if (init == 0) {
+ ret = msg_thread_init(
+ &g_msg_ctx, "DumptestThread", test_op_func, DUMP_TEST_OPID_MAX);
+ init = 1;
+ }
+ if (par2 == 0xff && par3 == 0xff && init) {
+ pr_info("End test");
+ msg_thread_deinit(&g_msg_ctx);
+ init = 0;
+ }
+
+ msg_thread_send_1(&g_msg_ctx, par2, par3);
+
+ return 0;
+#endif
+}
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/cal_test.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/cal_test.h
new file mode 100755
index 0000000..da917ca
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/cal_test.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _CAL_TEST_H_
+#define _CAL_TEST_H_
+
+#include "osal.h"
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+
+int calibration_test(void);
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _CAL_TEST_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/chip_rst_test.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/chip_rst_test.h
new file mode 100755
index 0000000..b9b413a
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/chip_rst_test.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _CHIP_RST_TEST_H_
+#define _CHIP_RST_TEST_H_
+
+#include "osal.h"
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+
+int chip_rst_test(void);
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _CHIP_RST_TEST_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/conf_test.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/conf_test.h
new file mode 100755
index 0000000..a5aa7bd
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/conf_test.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _CONF_TEST_H_
+#define _CONF_TEST_H_
+
+#include "osal.h"
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+
+int conninfra_conf_test(void);
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _CONF_TEST_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/conninfra_core_test.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/conninfra_core_test.h
new file mode 100755
index 0000000..fcc964a
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/conninfra_core_test.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _CONNINFRA_CORE_TEST_H_
+#define _CONNINFRA_CORE_TEST_H_
+
+#include "osal.h"
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+#define WMT_FUNC_CTRL_ON (MTK_WCN_BOOL_TRUE)
+#define WMT_FUNC_CTRL_OFF (MTK_WCN_BOOL_FALSE)
+
+#define INIT_CMD(c, e, s) {.cmd = c, .cmdSz = sizeof(c), .evt = e, .evtSz = sizeof(e), .str = s}
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _CONNINFRA_CORE_TEST_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/conninfra_step_test.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/conninfra_step_test.h
new file mode 100755
index 0000000..43d1ea3
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/conninfra_step_test.h
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _CONNINFRA_STEP_TEST_H_
+#define _CONNINFRA_STEP_TEST_H_
+
+#include "osal.h"
+#include "conninfra_step.h"
+
+#define STEP_TEST_CONSYS_EMI_WMT_OFFSET 0x68000
+
+#define TEST_FAIL -1
+#define TEST_PASS 0
+#define TEST_CHECK 1
+#define STEP_TEST_ACTION_NUMBER 30
+
+extern struct step_env_struct g_infra_step_env;
+extern struct platform_device *g_pdev;
+
+struct step_test_report {
+ unsigned int pass;
+ unsigned int fail;
+ unsigned int check;
+};
+
+struct step_test_scn_tp_act {
+ int tp_id;
+ int act_id;
+ int param_num;
+ const char* params[STEP_PARAMETER_SIZE];
+};
+struct step_test_scenario {
+ const char* title;
+ int test_idx;
+ int total_test_sz;
+ struct step_test_scn_tp_act pt_acts[STEP_TEST_ACTION_NUMBER];
+};
+
+struct step_test_check {
+ unsigned int step_check_total;
+ int step_check_test_tp_id[STEP_TEST_ACTION_NUMBER];
+ int step_check_test_act_id[STEP_TEST_ACTION_NUMBER];
+ char *step_check_params[STEP_TEST_ACTION_NUMBER][STEP_PARAMETER_SIZE];
+ int step_check_params_num[STEP_TEST_ACTION_NUMBER];
+ unsigned int step_check_index;
+ int step_check_result;
+ char *step_check_result_string;
+ int step_check_result_value;
+ unsigned int step_check_emi_offset[STEP_TEST_ACTION_NUMBER];
+ size_t step_check_register_addr;
+ size_t step_check_write_value;
+ unsigned int step_test_mask;
+ unsigned int step_recovery_value;
+ int step_check_temp_register_id;
+
+ struct step_test_scenario* cur_test_scn;
+};
+
+
+
+/* step test utility ++++ */
+
+void conninfra_step_test_show_result_report(char *test_name, struct step_test_report *p_report, int sec_begin, int usec_begin,
+ int sec_end, int usec_end);
+void conninfra_step_test_update_result_report(struct step_test_report *p_dest_report,
+ struct step_test_report *p_src_report);
+
+void conninfra_step_test_create_action(enum step_action_id act_id, int param_num, char *params[], int result_of_action,
+ int check_params[], struct step_test_report *p_report, char *err_result);
+
+void conninfra_step_test_update_result(int result, struct step_test_report *p_report, char *err_result);
+/* step test utility ---- */
+
+void conninfra_step_test_all(void);
+void conninfra_step_test_read_file(struct step_test_report *p_report);
+//void conninfra_step_test_parse_data1(struct step_test_report *p_report);
+//void conninfra_step_test_parse_data1(struct step_test_report *p_report);
+
+/* EMI test utility */
+int conninfra_step_test_get_emi_offset(unsigned char buf[], int offset);
+unsigned char* conninfra_step_test_get_emi_virt_offset(unsigned int offset);
+void conninfra_step_test_put_emi_virt_offset(void);
+
+/* reg test utility */
+//int conninfra_step_test_find_can_write_register(void);
+//int conninfra_step_test_get_reg_base_phy_addr(unsigned char buf[], unsigned int index);
+
+/* unchecked ++++ */
+//void wmt_step_test_create_emi_action(struct step_test_report *p_report);
+//void wmt_step_test_create_cond_emi_action(struct step_test_report *p_report);
+//void wmt_step_test_create_register_action(struct step_test_report *p_report);
+//void wmt_step_test_create_cond_register_action(struct step_test_report *p_report);
+//void wmt_step_test_check_register_symbol(struct step_test_report *p_report);
+//void wmt_step_test_create_other_action(struct step_test_report *p_report);
+//void wmt_step_test_do_emi_action(struct step_test_report *p_report);
+//void wmt_step_test_do_cond_emi_action(struct step_test_report *p_report);
+//void wmt_step_test_do_register_action(struct step_test_report *p_report);
+//void wmt_step_test_do_cond_register_action(struct step_test_report *p_report);
+//void conninfra_step_test_do_gpio_action(struct step_test_report *p_report);
+//void conninfra_step_test_do_chip_reset_action(struct step_test_report *p_report);
+//void conninfra_step_test_create_periodic_dump(struct step_test_report *p_report);
+//void conninfra_step_test_do_show_action(struct step_test_report *p_report);
+//void conninfra_step_test_do_sleep_action(struct step_test_report *p_report);
+//void conninfra_step_test_do_condition_action(struct step_test_report *p_report);
+//void conninfra_step_test_do_value_action(struct step_test_report *p_report);
+
+/* No need */
+//void wmt_step_test_do_disable_reset_action(struct step_test_report *p_report);
+//void wmt_step_test_do_wakeup_action(struct step_test_report *p_report);
+
+/* unchecked ---- */
+
+
+#endif /* end of _CONNINFRA_STEP_TEST_H_ */
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/conninfra_test.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/conninfra_test.h
new file mode 100755
index 0000000..4710e67
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/conninfra_test.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _CONNINFRA_TEST_H_
+#define _CONNINFRA_TEST_H_
+
+#include "osal.h"
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+#define INIT_CMD(c, e, s) {.cmd = c, .cmdSz = sizeof(c), .evt = e, .evtSz = sizeof(e), .str = s}
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+typedef int(*CONNINFRA_TEST_FUNC) (int par1, int par2, int par3);
+
+int conninfra_test_setup(void);
+int conninfra_test_remove(void);
+
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _CONNINFRA_CORE_TEST_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/connsyslog_test.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/connsyslog_test.h
new file mode 100644
index 0000000..f6e6988
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/connsyslog_test.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef _CONNLOG_TEST_H_
+#define _CONNLOG_TEST_H_
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+
+int connlog_test_init(void);
+int connlog_test_read(void);
+int connlog_test_deinit(void);
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _CONNLOG_TEST_H_ */
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/coredump_test.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/coredump_test.h
new file mode 100755
index 0000000..3934ca7
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/coredump_test.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _COREDUMP_TEST_H_
+#define _COREDUMP_TEST_H_
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+int coredump_test(int par1, int par2, int par3);
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _COREDUMP_TEST_H_ */
+
+
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/mailbox_test.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/mailbox_test.h
new file mode 100755
index 0000000..9935352
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/mailbox_test.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _MAILBOX_TEST_H_
+#define _MAILBOX_TEST_H_
+
+#include "osal.h"
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+int mailbox_test(void);
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _MAILBOX_TEST_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/msg_evt_test.h b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/msg_evt_test.h
new file mode 100755
index 0000000..617c657
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/include/msg_evt_test.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#ifndef _MSG_EVT_TEST_H_
+#define _MSG_EVT_TEST_H_
+
+#include "osal.h"
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+
+int msg_evt_test(void);
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+#endif /* _MSG_EVT_TEST_H_ */
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/mailbox_test.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/mailbox_test.c
new file mode 100755
index 0000000..38c48d2
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/mailbox_test.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/slab.h>
+#include <linux/mailbox_client.h>
+#include "consys_hw.h"
+#include "conninfra_core_test.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+struct demo_client {
+ struct mbox_client cl;
+ struct mbox_chan *mbox;
+ struct completion c;
+ bool async;
+};
+
+
+static void message_from_remote(struct mbox_client *cl, void *msg)
+{
+ struct demo_client *dc = container_of(cl, struct demo_client, cl);
+ if (dc->async) {
+ pr_info("AAAAsync");
+ } else {
+ pr_info("SSSSSSSync");
+ }
+}
+
+static void sample_sent(struct mbox_client *cl, void *msg, int r)
+{
+ struct demo_client *dc = container_of(cl, struct demo_client, cl);
+ complete(&dc->c);
+}
+
+int mailbox_test(void)
+{
+ struct demo_client *dc_sync;
+ struct platform_device *pdev = get_consys_device();
+
+ dc_sync = kzalloc(sizeof(*dc_sync), GFP_KERNEL);
+ dc_sync->cl.dev = &pdev->dev;
+ dc_sync->cl.rx_callback = message_from_remote;
+ dc_sync->cl.tx_done = sample_sent;
+ dc_sync->cl.tx_block = true;
+ dc_sync->cl.tx_tout = 500;
+ dc_sync->cl.knows_txdone = false;
+ dc_sync->async = false;
+
+ dc_sync->mbox = mbox_request_channel(&dc_sync->cl, 0);
+
+ if (IS_ERR(dc_sync->mbox)) {
+ kfree(dc_sync);
+ pr_err("request channel fail [%ld]", PTR_ERR(dc_sync->mbox));
+ return -1;
+ }
+ mbox_send_message(dc_sync->mbox, 0);
+
+ wait_for_completion(&dc_sync->c);
+ kfree(dc_sync);
+
+ return 0;
+}
diff --git a/src/kernel/modules/connectivity/2.0/conninfra_driver/test/msg_evt_test.c b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/msg_evt_test.c
new file mode 100755
index 0000000..6efd310
--- /dev/null
+++ b/src/kernel/modules/connectivity/2.0/conninfra_driver/test/msg_evt_test.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+/*! \file
+* \brief Declaration of library functions
+*
+* Any definitions in this file will be shared among GLUE Layer and internal Driver Stack.
+*/
+
+#define pr_fmt(fmt) "msg_evt_test@(%s:%d) " fmt, __func__, __LINE__
+
+#include <linux/slab.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include "msg_thread.h"
+#include "msg_evt_test.h"
+
+/*******************************************************************************
+* C O M P I L E R F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* M A C R O S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* E X T E R N A L R E F E R E N C E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* D A T A T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+* F U N C T I O N D E C L A R A T I O N S
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P U B L I C D A T A
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* P R I V A T E D A T A
+********************************************************************************
+*/
+
+
+/*******************************************************************************
+* F U N C T I O N S
+********************************************************************************
+*/
+
+struct work_struct rst_worker;
+struct msg_thread_ctx g_ctx;
+
+typedef enum {
+ INFRA_TEST_OPID_1 = 0,
+ INFRA_TEST_OPID_2 = 1,
+ INFRA_TEST_OPID_MAX
+} test_opid;
+
+
+static int opfunc_test_1(struct msg_op_data *op);
+static int opfunc_test_2(struct msg_op_data *op);
+
+static const msg_opid_func test_op_func[] = {
+ [INFRA_TEST_OPID_1] = opfunc_test_1,
+ [INFRA_TEST_OPID_2] = opfunc_test_2,
+};
+
+int opfunc_test_1(struct msg_op_data *op)
+{
+ pr_info("[%s]", __func__);
+ return 0;
+}
+
+int opfunc_test_2(struct msg_op_data *op)
+{
+ unsigned int drv_type = op->op_data[0];
+
+ pr_info("[%s] param=[%d]", __func__, drv_type);
+ return 0;
+}
+
+
+static void msg_thrd_handler(struct work_struct *work)
+{
+ msg_thread_send_1(&g_ctx, INFRA_TEST_OPID_2, 2011);
+ osal_sleep_ms(5);
+ msg_thread_send_wait_1(&g_ctx, INFRA_TEST_OPID_2, 0, 2022);
+ msg_thread_send_wait_1(&g_ctx, INFRA_TEST_OPID_2, 0, 2033);
+}
+
+int msg_evt_test(void)
+{
+ int ret;
+
+ INIT_WORK(&rst_worker, msg_thrd_handler);
+
+ ret = msg_thread_init(&g_ctx, "TestThread",
+ test_op_func, INFRA_TEST_OPID_MAX);
+ if (ret) {
+ pr_err("inti msg_thread fail ret=[%d]\n", ret);
+ return -2;
+ }
+
+ schedule_work(&rst_worker);
+
+ msg_thread_send_wait_1(&g_ctx, INFRA_TEST_OPID_2, 0, 1011);
+ //osal_sleep_ms(10);
+ msg_thread_send_1(&g_ctx, INFRA_TEST_OPID_2, 1022);
+ osal_sleep_ms(10);
+ msg_thread_send_wait_1(&g_ctx, INFRA_TEST_OPID_2, 0, 1033);
+
+ osal_sleep_ms(1000);
+
+ pr_info("<<<<<>>>>>>> freeOpq=[%u][%u] ActiveQ=[%u][%u]",
+ g_ctx.free_op_q.write, g_ctx.free_op_q.read,
+ g_ctx.active_op_q.write, g_ctx.active_op_q.read);
+ osal_sleep_ms(500);
+
+ ret = msg_thread_deinit(&g_ctx);
+ pr_info("[%s] msg_thread_deinit\n", __func__);
+
+ pr_info("[%s] test PASS\n", __func__);
+ return 0;
+}
+
+
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
+