diff --git a/package/wwan/driver/quectel_SRPD_PCIE/Makefile b/package/wwan/driver/quectel_SRPD_PCIE/Makefile deleted file mode 100755 index 7e0f6b572..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/Makefile +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright (C) 2015 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=sprd_pcie -PKG_VERSION:=1.6 -PKG_RELEASE:=1 - -include $(INCLUDE_DIR)/kernel.mk -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/sprd_pcie - SUBMENU:=WWAN Support - TITLE:=Kernel pcie driver for SPRD device - FILES:=$(PKG_BUILD_DIR)/sprd_pcie.ko - AUTOLOAD:=$(call AutoLoad,41,sprd_pcie) -endef - -define KernelPackage/sprd_pcie/description - Kernel module for register a custom pcispd platform device. -endef - -MAKE_OPTS:= \ - ARCH="$(LINUX_KARCH)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - CXXFLAGS="$(TARGET_CXXFLAGS)" \ - M="$(PKG_BUILD_DIR)" \ - $(EXTRA_KCONFIG) - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Build/Compile - $(MAKE) -C "$(LINUX_DIR)" \ - $(MAKE_OPTS) \ - modules -endef - -$(eval $(call KernelPackage,sprd_pcie)) diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/Makefile b/package/wwan/driver/quectel_SRPD_PCIE/src/Makefile deleted file mode 100644 index 8fc450fe6..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# -# Makefile for the sprd staging modem files -# -EXTRA_CFLAGS += -Wno-error -Wno-packed-bitfield-compat -ccflags-y += -DCONFIG_SPRD_PCIE_EP_DEVICE -DCONFIG_SPRD_SIPA -DCONFIG_SPRD_ETHERNET -obj-m += sprd_pcie.o -sprd_pcie-objs := pcie/sprd_pcie_ep_device.o pcie/pcie_host_resource.o pcie/sprd_pcie_quirks.o sipc/sipc.o sipc/sblock.o sipc/sbuf.o \ - sipc/sipc_debugfs.o sipc/smem.o sipc/smsg.o sipc/spipe.o sipc/spool.o power_manager/power_manager.o \ - sipa/sipa_core.o sipa/sipa_eth.o sipa/sipa_nic.o sipa/sipa_skb_send.o sipa/sipa_skb_recv.o sipa/sipa_dummy.o sipa/sipa_debugfs.o sipa/sipa_dele_cmn.o \ - sipa/sipa_phy_v0/sipa_fifo_irq_hal.o sipa/sipa_phy_v0/sipa_common_fifo_hal.o - -PWD := $(shell pwd) -ifeq ($(ARCH),) -ARCH := $(shell uname -m) -endif -ifeq ($(CROSS_COMPILE),) -CROSS_COMPILE := -endif -ifeq ($(KDIR),) -KDIR := /lib/modules/$(shell uname -r)/build -endif - -sprd_pcie: clean - $(MAKE) ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} -C $(KDIR) M=$(PWD) modules - #cp sprd_pcie.ko /tftpboot/ - -clean: - $(MAKE) ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} -C $(KDIR) M=$(PWD) clean - find . -name *.o.ur-safe | xargs rm -f - -install: sprd_pcie - sudo cp sprd_pcie.ko /lib/modules/${shell uname -r}/kernel/drivers/pci/ - sudo depmod diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/include/mdm_ctrl.h b/package/wwan/driver/quectel_SRPD_PCIE/src/include/mdm_ctrl.h deleted file mode 100644 index 677b8379d..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/include/mdm_ctrl.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef _MDM_CTRL_H -#define _MDM_CTRL_H -/* - * For mcd driver,it offer modem_ctrl_send_abnormal_to_ap - * function for others. It means you can use this function to notify ap, - * some errors has been catched,by this way,ap will triger this error - * and to do something for recovery. - */ - -#include - -enum { - MDM_CTRL_POWER_OFF = 0, - MDM_CTRL_POWER_ON, - MDM_CTRL_WARM_RESET, - MDM_CTRL_COLD_RESET, - MDM_WATCHDOG_RESET, - MDM_ASSERT, - MDM_PANIC, - MDM_CTRL_PCIE_RECOVERY, - MDM_POWER_OFF, - MDM_CTRL_SET_CFG -}; - -void modem_ctrl_send_abnormal_to_ap(int status); -void modem_ctrl_poweron_modem(int on); -void modem_ctrl_enable_cp_event(void); -int modem_ctrl_register_notifier(struct notifier_block *nb); -void modem_ctrl_unregister_notifier(struct notifier_block *nb); - -#endif diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/include/pcie-rc-sprd.h b/package/wwan/driver/quectel_SRPD_PCIE/src/include/pcie-rc-sprd.h deleted file mode 100644 index 4a42963d3..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/include/pcie-rc-sprd.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _PCIE_RC_SPRD_H -#define _PCIE_RC_SPRD_H - -#include - -enum sprd_pcie_event { - SPRD_PCIE_EVENT_INVALID = 0, - SPRD_PCIE_EVENT_LINKDOWN = 0x1, - SPRD_PCIE_EVENT_LINKUP = 0x2, - SPRD_PCIE_EVENT_WAKEUP = 0x4, -}; - -struct sprd_pcie_register_event { - u32 events; - struct platform_device *pdev; - void (*callback)(enum sprd_pcie_event event, void *data); - void *data; -}; - -/* - * SPRD PCIe root complex (e.g. UD710 SoC) can't support PCI hotplug - * capability. Therefore, the standard hotplug driver can't be used. - * - * Whenever one endpoint is plugged or powered on, the EP driver must - * call sprd_pcie_configure_device() in order to add EP device to system - * and probe EP driver. If one endpoint is unplugged or powered off, - * the EP driver must call sprd_pcie_unconfigure_device() in order to - * remove all PCI devices on PCI bus. - * - * return 0 on success, otherwise return a negative number. - */ -/* dumy sprd api */ -static inline int sprd_pcie_configure_device(struct platform_device *pdev) { return 0; } -static inline int sprd_pcie_unconfigure_device(struct platform_device *pdev) { return 0; } -static inline void sprd_pcie_teardown_msi_irq(unsigned int irq) { } -static inline void sprd_pcie_dump_rc_regs(struct platform_device *pdev) { } -static inline int sprd_pcie_register_event(struct sprd_pcie_register_event *reg) { return 0; } -static inline int sprd_pcie_deregister_event(struct sprd_pcie_register_event *reg) { return 0; } - -#ifdef CONFIG_SPRD_PCIE_AER -void sprd_pcie_alloc_irq_vectors(struct pci_dev *dev, int *irqs, int services) { } -#else -static inline void sprd_pcie_alloc_irq_vectors(struct pci_dev *dev, int *irqs, - int services) -{ -} -#endif - -#endif diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/include/sipa.h b/package/wwan/driver/quectel_SRPD_PCIE/src/include/sipa.h deleted file mode 100644 index 9e4c66413..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/include/sipa.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef _SIPA_H_ -#define _SIPA_H_ - -#include -#include -#include - -enum sipa_evt_type { - SIPA_RECEIVE, - SIPA_ENTER_FLOWCTRL, - SIPA_LEAVE_FLOWCTRL, - SIPA_ERROR, -}; - -typedef void (*sipa_notify_cb)(void *priv, enum sipa_evt_type evt, - unsigned int data); - -enum sipa_term_type { - SIPA_TERM_PCIE0 = 0x10, - SIPA_TERM_PCIE1 = 0x11, - SIPA_TERM_PCIE2 = 0x12, - SIPA_TERM_CP0 = 0x4, - SIPA_TERM_CP1 = 0x5, - SIPA_TERM_VCP = 0x6, - - SIPA_TERM_MAX = 0x20, /* max 5-bit register */ -}; - -enum sipa_nic_id { - SIPA_NIC_BB0, - SIPA_NIC_BB1, - SIPA_NIC_BB2, - SIPA_NIC_BB3, - SIPA_NIC_BB4, - SIPA_NIC_BB5, - SIPA_NIC_BB6, - SIPA_NIC_BB7, - SIPA_NIC_BB8, - SIPA_NIC_BB9, - SIPA_NIC_BB10, - SIPA_NIC_BB11, - SIPA_NIC_MAX, -}; - -struct sk_buff *sipa_recv_skb(int *netid, int index); -bool sipa_check_recv_tx_fifo_empty(void); -int sipa_nic_open(enum sipa_term_type src, int netid, - sipa_notify_cb cb, void *priv); -void sipa_nic_close(enum sipa_nic_id nic_id); -int sipa_nic_tx(enum sipa_nic_id nic_id, enum sipa_term_type dst, - int netid, struct sk_buff *skb); -int sipa_nic_rx(int *netid, struct sk_buff **out_skb, int index); -int sipa_nic_rx_has_data(enum sipa_nic_id nic_id); -int sipa_nic_trigger_flow_ctrl_work(enum sipa_nic_id nic_id, int err); - -u32 sipa_nic_get_filled_num(void); -void sipa_nic_restore_irq(void); -void sipa_nic_set_tx_fifo_rp(u32 rptr); -#endif diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/include/sipc.h b/package/wwan/driver/quectel_SRPD_PCIE/src/include/sipc.h deleted file mode 100644 index fe01b6463..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/include/sipc.h +++ /dev/null @@ -1,1154 +0,0 @@ -/* - * Copyright (C) 2012-2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#ifndef __SIPC_H -#define __SIPC_H - -#include - -/* ****************************************************************** */ -/* SMSG interfaces */ - -/* sipc processor ID definition */ -enum { - SIPC_ID_AP = 0, /* Application Processor */ - SIPC_ID_MINIAP, /* mini AP processor */ - SIPC_ID_CPW, /* WCDMA processor */ - SIPC_ID_WCN, /* Wireless Connectivity */ - SIPC_ID_GNSS, /* Gps processor(gnss) */ - SIPC_ID_PSCP, /* Protocol stack processor */ - SIPC_ID_PM_SYS, /* Power management processor */ - SIPC_ID_NR_PHY, /* New Radio PHY processor */ - SIPC_ID_V3_PHY, /* MODEM v3 PHY processor */ - SIPC_ID_NR, /* Max processor number */ -}; - -#define SIPC_ID_LTE SIPC_ID_PSCP - -/* share-mem ring buffer short message */ -struct smsg { - u8 channel; /* channel index */ - u8 type; /* msg type */ - u16 flag; /* msg flag */ - u32 value; /* msg value */ -}; - -/* smsg channel definition */ -enum { - SMSG_CH_CTRL = 0, /* some emergency control */ - SMSG_CH_COMM, /* general communication channel */ - SMSG_CH_IMSBR_DATA, /* ims bridge data channel */ - SMSG_CH_IMSBR_CTRL, /* ims bridge control channel */ - SMSG_CH_PIPE, /* general pipe channel */ - SMSG_CH_PLOG, /* pipe for debug log/dump */ - SMSG_CH_TTY, /* virtual serial for telephony */ - SMSG_CH_DATA0, /* 2G/3G wirleless data */ - SMSG_CH_DATA1, /* 2G/3G wirleless data */ - SMSG_CH_DATA2, /* 2G/3G wirleless data */ - SMSG_CH_VBC, /* audio conrol channel */ - SMSG_CH_PLAYBACK, /* audio playback channel */ - SMSG_CH_CAPTURE, /* audio capture channel */ - SMSG_CH_MONITOR_AUDIO, /* audio monitor channel */ - SMSG_CH_CTRL_VOIP, /* audio voip conrol channel */ - SMSG_CH_PLAYBACK_VOIP, /* audio voip playback channel */ - SMSG_CH_CAPTURE_VOIP, /* audio voip capture channel */ - SMSG_CH_MONITOR_VOIP, /* audio voip monitor channel */ - SMSG_CH_DATA3, /* 2G/3G wirleless data */ - SMSG_CH_DATA4, /* 2G/3G wirleless data */ - SMSG_CH_DATA5, /* 2G/3G wirleless data */ - SMSG_CH_DIAG, /* pipe for debug log/dump */ - SMSG_CH_PM_CTRL, /* power management control */ - SMSG_CH_DUAL_SIM_PLUG, /* dual sim plug channel */ - SMSG_CH_END /* will not allow add channel in here */ -}; - -/* smsg channel definition */ -enum { - /* 2G/3G wirleless data, channel 24~39 */ - SMSG_CH_DATA_BASE = 24, - SMSG_CH_DATA6 = SMSG_CH_DATA_BASE, - SMSG_CH_DATA7, - SMSG_CH_DATA8, - SMSG_CH_DATA9, - SMSG_CH_DATA10, - SMSG_CH_DATA11, - SMSG_CH_DATA12, - SMSG_CH_DATA13, - - /* general pipe channel, channel 40~59 */ - SMSG_CH_PIPE_BASE = 40, - SMSG_CH_NV = SMSG_CH_PIPE_BASE, - SMSG_CH_DVFS, - SMSG_CH_PIPE2, - SMSG_CH_PIPE3, - - /* pipe for debug log/dump channel 60~79 */ - SMSG_CH_PLOG_BASE = 60, - SMSG_CH_PLOG0 = SMSG_CH_PLOG_BASE, - SMSG_CH_PLOG1, - SMSG_CH_PLOG2, - SMSG_CH_PLOG3, - - /* virtual serial for telephony, channel 80~99*/ - SMSG_CH_TTY_BASE = 80, - SMSG_CH_TTY0 = SMSG_CH_TTY_BASE, - SMSG_CH_TTY1, - SMSG_CH_TTY2, - SMSG_CH_TTY3, - - /* some emergency control, channel 100~119 */ - SMSG_CH_CTRL_BASE = 100, - SMSG_CH_PMSYS_DBG = SMSG_CH_CTRL_BASE, - SMSG_CH_CTRL1, - SMSG_CH_CTRL2, - SMSG_CH_CTRL3, - - /* general communication, channel 120~129 */ - SMSG_CH_COMM_BASE = 120, - SMSG_CH_COMM_SIPA = SMSG_CH_COMM_BASE, - SMSG_CH_COMM1, - SMSG_CH_COMM2, - SMSG_CH_COMM3, - - /* audio channel, channel 130 ~149 */ - SMSG_CH_AUDIO_BASE = 130, - SMSG_CH_AGDSP_ACCESS = SMSG_CH_AUDIO_BASE,/* audio conrol channel */ - SMSG_CH_PLAYBACK_DEEP, - SMSG_CH_AUDIO2, - SMSG_CH_AUDIO3, - - /* VOIP channel, channel 150 ~169 */ - SMSG_CH_VOIP_BASE = 150, - SMSG_CH_VOIP0 = SMSG_CH_VOIP_BASE,/* audio voip conrol channel */ - SMSG_CH_VOIP_DEEP, /* audio voip playback channel */ - SMSG_CH_VOIP2, /* audio voip capture channel */ - SMSG_CH_VOIP3, /* audio voip monitor channel */ - - /* RPC server channel, channel 170~189 */ - SMSG_CH_RPC_BASE = 170, - SMSG_CH_RPC0 = SMSG_CH_RPC_BASE, - SMSG_CH_RPC1, - SMSG_CH_RPC2, - SMSG_CH_RPC3, - - /* RESERVE group 1, channel 190 ~209 */ - SMSG_CH_RESERVE1_BASE = 190, - - /* RESERVE group 2, channel 210 ~129 */ - SMSG_CH_RESERVE2_BASE = 210, - - /* RESERVE group 3, channel 230 ~244 */ - SMSG_CH_RESERVE3_BASE = 230, - - /* RESERVE group 4, channel 245 ~254 */ - SMSG_CH_RESERVE4_BASE = 245, - - /* total channel number 255, the max chanel number is 254*/ - SMSG_CH_NR = 255 -}; -#define INVALID_CHANEL_INDEX SMSG_CH_NR - -/* modem type */ -enum { - SOC_MODEM = 0, - PCIE_MODEM, -}; - -/* only be configed in sipc_config is valid channel */ -struct sipc_config { - u8 channel; - char *name; -}; - -static const struct sipc_config sipc_cfg[] = { - {SMSG_CH_CTRL, "com control"}, /* chanel 0 */ - {SMSG_CH_COMM, "com communication"}, /* chanel 1 */ - {SMSG_CH_PM_CTRL, "pm contrl"}, /* chanel 22 */ - {SMSG_CH_PMSYS_DBG, "pm debug contrl"}, /* chanel 100 */ - {SMSG_CH_DUAL_SIM_PLUG, "dual sim plug"}, /* chanel 23 */ - {SMSG_CH_PIPE, "pipe0"}, /* chanel 4 */ - {SMSG_CH_PLOG, "plog"}, /* chanel 5 */ - {SMSG_CH_DIAG, "diag"}, /* chanel 21 */ - {SMSG_CH_TTY, "stty chanel"}, /* chanel 6 */ - {SMSG_CH_DATA0, "seth0"}, /* chanel 7 */ - {SMSG_CH_DATA1, "seth1"}, /* chanel 8 */ - {SMSG_CH_DATA2, "seth2"}, /* chanel 9 */ - {SMSG_CH_DATA3, "seth3"}, /* chanel 18 */ - {SMSG_CH_DATA4, "seth4"}, /* chanel 19 */ - {SMSG_CH_DATA5, "seth5"}, /* chanel 20 */ - {SMSG_CH_DATA6, "seth6"}, /* chanel 24 */ - {SMSG_CH_DATA7, "seth7"}, /* chanel 25 */ - {SMSG_CH_DATA8, "seth8"}, /* chanel 26 */ - {SMSG_CH_DATA9, "seth9"}, /* chanel 27 */ - {SMSG_CH_DATA10, "seth10"}, /* chanel 28 */ - {SMSG_CH_DATA11, "seth11"}, /* chanel 29 */ - {SMSG_CH_DATA12, "seth12"}, /* chanel 30 */ - {SMSG_CH_DATA13, "seth13"}, /* chanel 31 */ - {SMSG_CH_VBC, "audio control"}, /* chanel 10 */ - {SMSG_CH_PLAYBACK, "audio playback"}, /* chanel 11 */ - {SMSG_CH_CAPTURE, "audio capture"}, /* chanel 12 */ - {SMSG_CH_MONITOR_AUDIO, "audio monitor"}, /* chanel 13 */ - {SMSG_CH_AGDSP_ACCESS, "agdsp access"}, /* chanel 13 */ - {SMSG_CH_CTRL_VOIP, "VOIP conrol"}, /* chanel 14 */ - {SMSG_CH_PLAYBACK_VOIP, "VOIP playback"}, /* chanel 15 */ - {SMSG_CH_CAPTURE_VOIP, "VOIP capture"}, /* chanel 16 */ - {SMSG_CH_MONITOR_VOIP, "VOIP monitor"}, /* chanel 17 */ - {SMSG_CH_PLAYBACK_DEEP, "audio playback deep"}, /*channel 131*/ - {SMSG_CH_IMSBR_DATA, "imsbr data"}, /* chanel 2 */ - {SMSG_CH_IMSBR_CTRL, "imsbr control"}, /* channel 3 */ - {SMSG_CH_VOIP_DEEP, "audio voip deep"}, /*channel 151*/ - {SMSG_CH_DVFS, "dvfs"}, /* channel 41 */ - {SMSG_CH_COMM_SIPA, "sipa"}, /* channel 120 */ - {SMSG_CH_NV, "nvsync"}, /* channel 40 */ -}; - -#define SMSG_VALID_CH_NR (sizeof(sipc_cfg)/sizeof(struct sipc_config)) - - -/* smsg type definition */ -enum { - SMSG_TYPE_NONE = 0, - SMSG_TYPE_OPEN, /* first msg to open a channel */ - SMSG_TYPE_CLOSE, /* last msg to close a channel */ - SMSG_TYPE_DATA, /* data, value=addr, no ack */ - SMSG_TYPE_EVENT, /* event with value, no ack */ - SMSG_TYPE_CMD, /* command, value=cmd */ - SMSG_TYPE_DONE, /* return of command */ - SMSG_TYPE_SMEM_ALLOC, /* allocate smem, flag=order */ - SMSG_TYPE_SMEM_FREE, /* free smem, flag=order, value=addr */ - SMSG_TYPE_SMEM_DONE, /* return of alloc/free smem */ - SMSG_TYPE_FUNC_CALL, /* RPC func, value=addr */ - SMSG_TYPE_FUNC_RETURN, /* return of RPC func */ - SMSG_TYPE_DIE, - SMSG_TYPE_DFS, - SMSG_TYPE_DFS_RSP, - SMSG_TYPE_ASS_TRG, - SMSG_TYPE_HIGH_OFFSET, /* client sipc get high offset from host */ - SMSG_TYPE_NR, /* total type number */ -}; - -/* flag for OPEN/CLOSE msg type */ -#define SMSG_OPEN_MAGIC 0xBEEE -#define SMSG_CLOSE_MAGIC 0xEDDD - -/** -* sipc_get_wakeup_flag -* after the wakeup flag be set, the fist smsg will be print -* @parameters: void -* @return: int -*/ -int sipc_get_wakeup_flag(void); - -/** -* sipc_set_wakeup_flag -* after the wakeup flag be set, the fist smsg will be print -* @parameters: void -* @return: no return value -*/ -void sipc_set_wakeup_flag(void); - -/** -* sipc_clear_wakeup_flag -* clear the wake up flag -* @parameters: void -* @return: no return value -*/ -void sipc_clear_wakeup_flag(void); - -/** - * smsg_ch_open -- open a channel for smsg - * - * @dst: dest processor ID - * @channel: channel ID - * @timeout: milliseconds, 0 means no wait, -1 means unlimited - * @return: 0 on success, <0 on failure - */ -int smsg_ch_open(u8 dst, u8 channel, int timeout); - -/** - * smsg_ch_close -- close a channel for smsg - * - * @dst: dest processor ID - * @channel: channel ID - * @timeout: milliseconds, 0 means no wait, -1 means unlimited - * @return: 0 on success, <0 on failure - */ -int smsg_ch_close(u8 dst, u8 channel, int timeout); - - /** - * smsg_senddie -- send a MSG_TYPE_DIE message to pubcp - * - * @dst: dest processor ID - * @return: 0 on success, <0 on failure - */ -int smsg_senddie(u8 dst); - -/** - * smsg_send -- send smsg - * - * @dst: dest processor ID - * @msg: smsg body to be sent - * @timeout: milliseconds, 0 means no wait, -1 means unlimited - * @return: 0 on success, <0 on failure - */ -int smsg_send(u8 dst, struct smsg *msg, int timeout); - -/** - * smsg_recv -- poll and recv smsg - * - * @dst: dest processor ID - * @msg: smsg body to be received, channel should be filled as input - * @timeout: milliseconds, 0 means no wait, -1 means unlimited - * @return: 0 on success, <0 on failure - */ -int smsg_recv(u8 dst, struct smsg *msg, int timeout); - -/** - * sipc_channel2index - * - * only be configed in sipc_config is valid channel - * @ch: channel number - * @return: channel index ,if return index is INVALID_CHANEL_INDEX , - * it indicate it is a invalid chanel - */ -u8 sipc_channel2index(u8 ch); - -int smsg_ch_wake_unlock(u8 dst, u8 channel); - -#if defined(CONFIG_DEBUG_FS) -void sipc_debug_putline(struct seq_file *m, char c, int n); -#endif - -/* quickly fill a smsg body */ -static inline void smsg_set(struct smsg *msg, u8 channel, - u8 type, u16 flag, u32 value) -{ - msg->channel = channel; - msg->type = type; - msg->flag = flag; - msg->value = value; -} - -/* ack an open msg for modem recovery */ -static inline void smsg_open_ack(u8 dst, u16 channel) -{ - struct smsg mopen; - - pr_info("%s: channel %d-%d!\n", __func__, dst, channel); - smsg_set(&mopen, channel, SMSG_TYPE_OPEN, SMSG_OPEN_MAGIC, 0); - smsg_send(dst, &mopen, -1); -} - -/* ack an close msg for modem recovery */ -static inline void smsg_close_ack(u8 dst, u16 channel) -{ - struct smsg mclose; - - pr_info("%s: channel %d-%d!\n", __func__, dst, channel); - smsg_set(&mclose, channel, SMSG_TYPE_CLOSE, SMSG_CLOSE_MAGIC, 0); - smsg_send(dst, &mclose, -1); -} - -/* ****************************************************************** */ -/* SMEM interfaces */ -/** - * smem_get_area -- get sipc smem - * - * @dst: dest processor ID - * @base: base pointer - * @size: size pointer - * @return: 0 success, < 0 failed - */ -int smem_get_area(u8 dst, u32 *base, u32 *size); - -/** - * smem_alloc -- allocate shared memory block - * - * @dst: dest processor ID - * @size: size to be allocated, page-aligned - * @return: phys addr or 0 if failed - */ -u32 smem_alloc(u8 dst, u32 size); - -/** - * smem_free -- free shared memory block - * - * @dst: dest processor ID - * @addr: smem phys addr to be freed - * @order: size to be freed - */ -void smem_free(u8 dst, u32 addr, u32 size); - -/** - * shmem_ram_unmap -- for sipc unmap ram address - * - * @mem: vir mem - */ -void shmem_ram_unmap(u8 dst, const void *mem); - -/** - * shmem_ram_vmap_nocache -- for sipc map ram address - * - * @start: start address - * @size: size to be allocated, page-aligned - * @return: phys addr or 0 if failed - */ -void *shmem_ram_vmap_nocache(u8 dst, phys_addr_t start, size_t size); - -/** - * shmem_ram_vmap_cache -- for sipc map ram address - * - * @start: start address - * @size: size to be allocated, page-aligned - * @return: phys addr or 0 if failed - */ -void *shmem_ram_vmap_cache(u8 dst, phys_addr_t start, size_t size); - -void smem_free(u8 dst, u32 addr, u32 size); - -/** - * modem_ram_unmap -- for modem unmap ram address - * - * @mem: vir mem - * @modem_type: soc modem, pcie modem - */ -void modem_ram_unmap(u32 modem_type, const void *mem); - -/** - * shmem_ram_vmap_nocache -- for modem map ram address - * - * @modem_type: soc modem, pcie modem - * @start: start address - * @size: size to be allocated, page-aligned - * @return: phys addr or 0 if failed - */ -void *modem_ram_vmap_nocache(u32 modem_type, phys_addr_t start, size_t size); - -/** - * modem_ram_vmap_cache -- for modem map ram address - * - * @modem_type: soc modem, pcie modem - * @start: start address - * @size: size to be allocated, page-aligned - * @return: phys addr or 0 if failed - */ -void *modem_ram_vmap_cache(u32 modem_type, phys_addr_t start, size_t size); -/** - * sbuf_set_no_need_wake_lock - * - * @dst: dest processor ID - * @bufnum: which buffer to be set - * @return: none - */ - -void sbuf_set_no_need_wake_lock(u8 dst, u8 channel, u32 bufnum); - -/** - * sbuf_create -- create pipe ring buffers on a channel - * - * @dst: dest processor ID - * @channel: channel ID - * @txbufsize: tx buffer size - * @rxbufsize: rx buffer size - * @bufnum: how many buffers to be created - * @return: 0 on success, <0 on failure - */ - -int sbuf_create(u8 dst, u8 channel, u32 bufnum, - u32 txbufsize, u32 rxbufsize); - -/** - * sbuf_destroy -- destroy the pipe ring buffers on a channel - * - * @dst: dest processor ID - * @channel: channel ID - * @return: 0 on success, <0 on failure - */ -void sbuf_destroy(u8 dst, u8 channel); -void sbuf_down(u8 dst, u8 channel); - -/** - * sbuf_write -- write data to a sbuf - * - * @dst: dest processor ID - * @channel: channel ID - * @bufid: buffer ID - * @buf: data to be written - * @len: data length - * @timeout: milliseconds, 0 means no wait, -1 means unlimited - * @return: written bytes on success, <0 on failure - */ -int sbuf_write(u8 dst, u8 channel, u32 bufid, - void *buf, u32 len, int timeout); - -/** - * sbuf_read -- write data to a sbuf - * - * @dst: dest processor ID - * @channel: channel ID - * @bufid: buffer ID - * @buf: data to be written - * @len: data length - * @timeout: milliseconds, 0 means no wait, -1 means unlimited - * @return: read bytes on success, <0 on failure - */ -int sbuf_read(u8 dst, u8 channel, u32 bufid, - void *buf, u32 len, int timeout); - -/** - * sbuf_poll_wait -- poll sbuf read/write, used in spipe driver - * - * @dst: dest processor ID - * @channel: channel ID - * @bufid: buffer ID - * @file: struct file handler - * @wait: poll table - * @return: POLLIN or POLLOUT - */ -int sbuf_poll_wait(u8 dst, u8 channel, u32 bufid, - struct file *file, poll_table *wait); - -/** - * sbuf_status -- get sbuf status - * - * @dst: dest processor ID - * @channel: channel ID - * @return: 0 when ready, <0 when broken - */ -int sbuf_status(u8 dst, u8 channel); - -#define SBUF_NOTIFY_READY 0x00 -#define SBUF_NOTIFY_READ 0x01 -#define SBUF_NOTIFY_WRITE 0x02 -/** - * sbuf_register_notifier -- register a callback that's called - * when a tx sbuf is available or a rx sbuf is received. - * non-blocked sbuf_read can be called. - * - * @dst: dest processor ID - * @channel: channel ID - * @bufid: buf ID - * @handler: a callback handler - * @event: NOTIFY_READ, NOTIFY_WRITE, or both - * @data: opaque data passed to the receiver - * @return: 0 on success, <0 on failure - */ -int sbuf_register_notifier(u8 dst, u8 channel, u32 bufid, - void (*handler)(int event, void *data), void *data); - - -int sipc_init(void); -void sipc_exit(void); - -int spipe_init(void); -void spipe_exit(void); -void spipe_device_down(void); -void spool_device_down(void); - -int spool_init(void); -void spool_exit(void); - -int modem_power_manager_init(void); -void modem_power_manager_exit(void); - -#if 0 -int modem_ctrl_init(void); -void modem_ctrl_exit(void); -#endif - -int sipc_init_debugfs(void); - -/* ****************************************************************** */ -/* SBLOCK interfaces */ - -/* sblock structure: addr is the uncached virtual address */ -struct sblock { - void *addr; - u32 length; -#ifdef CONFIG_SPRD_SIPC_ZERO_COPY_SIPX - u16 index; - u16 offset; -#endif -}; - -/** - * sblock_create -- create sblock manager on a channel - * - * @dst: dest processor ID - * @channel: channel ID - * @txblocknum: tx block number - * @txblocksize: tx block size - * @rxblocknum: rx block number - * @rxblocksize: rx block size - * @return: 0 on success, <0 on failure - */ -int sblock_create(u8 dst, u8 channel, - u32 txblocknum, u32 txblocksize, - u32 rxblocknum, u32 rxblocksize); - -/** - * sblock_create_ex -- merge sblock_create and block_register_notifier - * in one function - * - * @dst: dest processor ID - * @channel: channel ID - * @txblocknum: tx block number - * @txblocksize: tx block size - * @rxblocknum: rx block number - * @rxblocksize: rx block size - * @event: SBLOCK_NOTIFY_GET, SBLOCK_NOTIFY_RECV, or both - * @data: opaque data passed to the receiver - * @return: 0 on success, <0 on failure - */ -int sblock_create_ex(u8 dst, u8 channel, - u32 txblocknum, u32 txblocksize, - u32 rxblocknum, u32 rxblocksize, - void (*handler)(int event, void *data), void *data); - -/* sblock_pcfg_create -- create preconfigured SBLOCK channel. - * - * @dst: dest processor ID - * @channel: channel ID - * @tx_blk_num: tx block number - * @tx_blk_sz: tx block size - * @rx_blk_num: rx block number - * @rx_blk_sz: rx block size - * @return: 0 on success, <0 on failure - * - * The function only allocates the memory for the channel, and will not - * open the channel. The client shall open the channel using - * sblock_pcfg_open and close the channel using sblock_close. - */ -int sblock_pcfg_create(u8 dst, u8 channel, - u32 tx_blk_num, u32 tx_blk_sz, - u32 rx_blk_num, u32 rx_blk_sz); - -/* sblock_pcfg_open -- request to open preconfigured SBLOCK channel. - * - * @dst: dest processor ID - * @channel: channel ID - * @notifier: the event notification callback function. This function can - * not sleep. If this parameter is NULL, no event will be - * reported. - * @event: SBLOCK_NOTIFY_GET, SBLOCK_NOTIFY_RECV, or both - * @client: opaque data passed to the receiver - * @return: if the channel is established, return 0; if the open procedure - * is started and not finished, return SIPC_ERR_IN_PROGRESS; - * otherwise return a negative error code. - * - * The function starts the open procedure. If the open procedure is not - * finished when the function returns, the SBLOCK system will report - * the open result later through the notifier callback. - */ -int sblock_pcfg_open(uint8_t dest, uint8_t channel, - void (*notifier)(int event, void *client), - void *client); - -/* sblock_close -- request to close SBLOCK channel. - * - * @dst: dest processor ID - * @channel: channel ID - * @return: if the channel is closed, return 0; if the close procedure - * is started and not finished, return SIPC_ERR_IN_PROGRESS; - * otherwise return a negative error code. - * - * The function starts the close procedure. If the close procedure is not - * finished when the function returns, the SBLOCK system will report - * the close result later through the notification callback that the - * client set by sblock_pcfg_open. - */ -int sblock_close(uint8_t dest, uint8_t channel); - -/* sblock_get_smem_cp_addr - get the shared memory CP address. - * @dest: destination ID - * @channel: channel number - * @paddr: pointer to the variable to receive the address. - */ -int sblock_get_smem_cp_addr(uint8_t dest, uint8_t channel, - uint32_t *paddr); -/** - * sblock_destroy -- destroy sblock manager on a channel - * - * @dst: dest processor ID - * @channel: channel ID - */ -void sblock_destroy(u8 dst, u8 channel); -void sblock_down(u8 dst, u8 channel); - -#define SBLOCK_NOTIFY_GET 0x01 -#define SBLOCK_NOTIFY_RECV 0x02 -#define SBLOCK_NOTIFY_STATUS 0x04 -#define SBLOCK_NOTIFY_OPEN 0x08 -#define SBLOCK_NOTIFY_CLOSE 0x10 -#define SBLOCK_NOTIFY_OPEN_FAILED 0x20 - -/** - * sblock_register_notifier -- register a callback that's called - * when a tx sblock is available or a rx block is received. - * non-blocked sblock_get or sblock_receive can be called. - * - * @dst: dest processor ID - * @channel: channel ID - * @handler: a callback handler - * @event: SBLOCK_NOTIFY_GET, SBLOCK_NOTIFY_RECV, or both - * @data: opaque data passed to the receiver - * @return: 0 on success, <0 on failure - */ -int sblock_register_notifier(u8 dst, u8 channel, - void (*handler)(int event, void *data), void *data); - -/** - * sblock_get -- get a free sblock for sender - * - * @dst: dest processor ID - * @channel: channel ID - * @blk: return a gotten sblock pointer - * @timeout: milliseconds, 0 means no wait, -1 means unlimited - * @return: 0 on success, <0 on failure - */ -int sblock_get(u8 dst, u8 channel, struct sblock *blk, int timeout); - -/** - * sblock_send -- send a sblock with smsg, it should be from sblock_get - * - * @dst: dest processor ID - * @channel: channel ID - * @blk: the sblock to be sent - * @return: 0 on success, <0 on failure - */ -int sblock_send(u8 dst, u8 channel, struct sblock *blk); - -/** - * sblock_send_prepare -- send a sblock without smsg, - * it should be from sblock_get - * - * @dst: dest processor ID - * @channel: channel ID - * @blk: the sblock to be sent - * @return: 0 on success, <0 on failure - */ -int sblock_send_prepare(u8 dst, u8 channel, struct sblock *blk); - -/** - * sblock_send_finish -- trigger an smsg to notify that sblock has been sent - * - * @dst: dest processor ID - * @channel: channel ID - * @return: 0 on success, <0 on failure - */ -int sblock_send_finish(u8 dst, u8 channel); - -/** - * sblock_receive -- receive a sblock, it should be released after it's handled - * - * @dst: dest processor ID - * @channel: channel ID - * @blk: return a received sblock pointer - * @timeout: milliseconds, 0 means no wait, -1 means unlimited - * @return: 0 on success, <0 on failure - */ -int sblock_receive(u8 dst, u8 channel, - struct sblock *blk, int timeout); - -/** - * sblock_release -- release a sblock from reveiver - * - * @dst: dest processor ID - * @channel: channel ID - * @return: 0 on success, <0 on failure - */ -int sblock_release(u8 dst, u8 channel, struct sblock *blk); - -/** - * sblock_get_arrived_count -- get the count of sblock(s) arrived at - * AP (sblock_send on CP) but not received (sblock_receive on AP). - * - * @dst: dest processor ID - * @channel: channel ID - * @return: >=0 the count of blocks - */ -int sblock_get_arrived_count(u8 dst, u8 channel); - - - -/** - * sblock_get_free_count -- get the count of available sblock(s) resident in - * sblock pool on AP. - * - * @dst: dest processor ID - * @channel: channel ID - * @return: >=0 the count of blocks - */ -int sblock_get_free_count(u8 dst, u8 channel); - - -/** - * sblock_put -- put a free sblock for sender - * - * @dst: dest processor ID - * @channel: channel ID - * @blk: sblock pointer - * @return: void - */ -void sblock_put(u8 dst, u8 channel, struct sblock *blk); - -/** - * sblock_poll_wait -- poll sblock read/write - * - * @dst: dest processor ID - * @channel: channel ID - * @filp: strcut file handle - * @wait: poll table - * @return: POLLIN or POLLOUT - */ -unsigned int sblock_poll_wait(u8 dst, u8 channel, struct file *filp, poll_table *wait); - -/** - * sblock_query -- sblock query status - * - * @dst: dest processor ID - * @channel: channel ID - * @return: 0 on success, <0 on failure - */ -int sblock_query(u8 dst, u8 channel); - - -/* ****************************************************************** */ - -#define SIPX_ACK_BLK_LEN (100) - -/** - * sipx_chan_create -- create a sipx channel - * - * @dst: dest processor ID - * @channel: channel ID - * @return: 0 on success, <0 on failure - */ -int sipx_chan_create(u8 dst, u8 channel); - -/** - * sipx_chan_destroy -- destroy seblock manager on a channel - * - * @dst: dest processor ID - * @channel: channel ID - */ -int sipx_chan_destroy(u8 dst, u8 channel); - -/** - * sipx_get_ack_blk_len -- get sipx ack block max length - * - * @dst: dest processor ID - * @return: length - */ -u32 sipx_get_ack_blk_len(u8 dst); - -/** - * sipx_get -- get a free sblock for sender - * - * @dst: dest processor ID - * @channel: channel ID - * @blk: return a gotten sblock pointer - * @is_ack: if want to get block for ack packet - * @return: 0 on success, <0 on failure - */ -int sipx_get(u8 dst, u8 channel, struct sblock *blk, int is_ack); - -/** - * sipx_chan_register_notifier -- register a callback that's called - * when a tx sblock is available or a rx block is received. - * on-blocked sblock_get or sblock_receive can be called. - * - * @dst: dest processor ID - * @channel: channel ID - * @handler: a callback handler - * @event: SBLOCK_NOTIFY_GET, SBLOCK_NOTIFY_RECV, or both - * @data: opaque data passed to the receiver - * @return: 0 on success, <0 on failure - */ -int sipx_chan_register_notifier(u8 dst, u8 channel, - void (*handler)(int event, void *data), void *data); - -/** - * sipx_send -- send a sblock with smsg, it should be from seblock_get - * - * @dst: dest processor ID - * @channel: channel ID - * @blk: the sblock to be sent - * @return: 0 on success, <0 on failure - */ -int sipx_send(u8 dst, u8 channel, struct sblock *blk); - -/** - * sipx_flush -- trigger an smsg to notify that sblock has been sent - * - * @dst: dest processor ID - * @channel: channel ID - * @return: 0 on success, <0 on failure - */ -int sipx_flush(u8 dst, u8 channel); - -/** - * sipx_receive -- receive a sblock, it should be released after it's handled - * - * @dst: dest processor ID - * @channel: channel ID - * @blk: return a received sblock pointer - * @return: 0 on success, <0 on failure - */ -int sipx_receive(u8 dst, u8 channel, struct sblock *blk); - -/** - * sipx_release -- release a sblock from reveiver - * - * @dst: dest processor ID - * @channel: channel ID - * @return: 0 on success, <0 on failure - */ -int sipx_release(u8 dst, u8 channel, struct sblock *blk); - -/** - * sipx_get_arrived_count -- get the count of sblock(s) arrived at - * AP (sblock_send on CP) but not received (sblock_receive on AP). - * - * @dst: dest processor ID - * @channel: channel ID - * @return: >=0 the count of blocks - */ -int sipx_get_arrived_count(u8 dst, u8 channel); - -/** - * sipx_get_free_count -- get the count of available sblock(s) resident in - * normal pool on AP. - * - * @dst: dest processor ID - * @channel: channel ID - * @return: >=0 the count of blocks - */ -int sipx_get_free_count(u8 dst, u8 channel); - -/** - * sipx_put -- put a free sblock for sender - * - * @dst: dest processor ID - * @channel: channel ID - * @blk: sblock pointer - * @return: void - */ -int sipx_put(u8 dst, u8 channel, struct sblock *blk); - -/* ****************************************************************** */ - -#ifdef CONFIG_SPRD_SIPC_ZERO_COPY_SIPX - -#define SBLOCK_CREATE(dst, channel,\ - txblocknum, txblocksize, txpoolsize, \ - rxblocknum, rxblocksize, rxpoolsize) \ -sipx_chan_create(dst, channel) - - -#define SBLOCK_DESTROY(dst, channel) \ - sipx_chan_destroy(dst, channel) - -#define SBLOCK_GET(dst, channel, blk, ack, timeout) \ - sipx_get(dst, channel, blk, ack) - -#define SBLOCK_REGISTER_NOTIFIER(dst, channel, handler, data) \ - sipx_chan_register_notifier(dst, channel, handler, data) - -#define SBLOCK_SEND(dst, channel, blk) \ - sipx_send(dst, channel, blk) - -#define SBLOCK_SEND_PREPARE(dst, channel, blk) \ - sipx_send(dst, channel, blk) - -#define SBLOCK_SEND_FINISH(dst, channel)\ - sipx_flush(dst, channel) - -#define SBLOCK_RECEIVE(dst, channel, blk, timeout) \ - sipx_receive(dst, channel, blk) - -#define SBLOCK_RELEASE(dst, channel, blk) \ - sipx_release(dst, channel, blk) - -#define SBLOCK_GET_ARRIVED_COUNT(dst, channel) \ - sipx_get_arrived_count(dst, channel) - -#define SBLOCK_GET_FREE_COUNT(dst, channel) \ - sipx_get_free_count(dst, channel) - -#define SBLOCK_PUT(dst, channel, blk) \ - sipx_put(dst, channel, blk) - - -#else /* CONFIG_SPRD_SIPC_ZERO_COPY_SIPX */ - -#define SBLOCK_CREATE(dst, channel,\ - txblocknum, txblocksize, txpoolsize, \ - rxblocknum, rxblocksize, rxpoolsize) \ -sblock_create(dst, channel,\ - txblocknum, txblocksize,\ - rxblocknum, rxblocksize) - -#define SBLOCK_DESTROY(dst, channel) \ - sblock_destroy(dst, channel) - -#define SBLOCK_GET(dst, channel, blk, ack, timeout) \ - sblock_get(dst, channel, blk, timeout) - -#define SBLOCK_REGISTER_NOTIFIER(dst, channel, handler, data) \ - sblock_register_notifier(dst, channel, handler, data) - -#define SBLOCK_SEND(dst, channel, blk) \ - sblock_send(dst, channel, blk) - -#define SBLOCK_SEND_PREPARE(dst, channel, blk) \ - sblock_send_prepare(dst, channel, blk) - -#define SBLOCK_SEND_FINISH(dst, channel)\ - sblock_send_finish(dst, channel) - -#define SBLOCK_RECEIVE(dst, channel, blk, timeout) \ - sblock_receive(dst, channel, blk, timeout) - -#define SBLOCK_RELEASE(dst, channel, blk) \ - sblock_release(dst, channel, blk) - -#define SBLOCK_GET_ARRIVED_COUNT(dst, channel) \ - sblock_get_arrived_count(dst, channel) - -#define SBLOCK_GET_FREE_COUNT(dst, channel) \ - sblock_get_free_count(dst, channel) - -#define SBLOCK_PUT(dst, channel, blk) \ - sblock_put(dst, channel, blk) - -#endif /* CONFIG_SPRD_SIPC_ZERO_COPY_SIPX */ - -#ifdef CONFIG_ARM64 -/** - * unalign_copy_from_user -- unaligned data accesses to addresses - * marked as device will always trigger an exception, this fuction - * can avoid this exception - * - * @to: dest, normal memory - * @from: src, device memory and alignment access must be considered - * @n: bytes - * @return: bytes not copied - */ -static inline unsigned long unalign_copy_to_user(void __user *to, - const void *from, - unsigned long n) -{ - /* from is not 8 byte aligned and n is less than 16 bytes */ - if (((unsigned long)from & 7) && (n < 16)) { - while (n) { - if (copy_to_user(to++, from++, 1)) - break; - n--; - } - return n; - } - - return copy_to_user(to, from, n); -} - -/** - * unalign_copy_from_user -- unaligned data accesses to addresses - * marked as device will always trigger an exception, this fuction - * can avoid this exception - * - * @to: dest, device memory and alignment access must be considered - * @from: src, normal memory - * @n: bytes - * @return: bytes not copied - */ -static inline unsigned long unalign_copy_from_user(void *to, - const void __user *from, - unsigned long n) -{ - unsigned c1, c2, c3; - - /* to is 8 byte aligned and n is less than 16 bytes */ - c1 = !((unsigned long)to & 0x7) && (n < 16); - if (c1) - return copy_from_user(to, from, n); - - /* to and from are 8 byte aligned */ - c2 = !((unsigned long)to & 0x7) && !((unsigned long)from & 0x7); - if (c2) - return copy_from_user(to, from, n); - - /* to and from are the same offset and n is more than 15 bytes */ - c3 = !(((unsigned long)to ^ (unsigned long)from) & 0x7) && (n > 15); - if (c3) - return copy_from_user(to, from, n); - - while (n) { - if (copy_from_user(to++, from++, 1)) - break; - n--; - } - - return n; -} - -static inline void unalign_memcpy(void *to, const void *from, size_t n) -{ - if (((unsigned long)to & 7) == ((unsigned long)from & 7)) { - while (((unsigned long)from & 7) && n) { - *(char *)(to++) = *(char *)(from++); - n--; - } - memcpy(to, from, n); - } else if (((unsigned long)to & 3) == ((unsigned long)from & 3)) { - while (((unsigned long)from & 3) && n) { - *(char *)(to++) = *(char *)(from++); - n--; - } - while (n >= 4) { - *(u32 *)(to) = *(u32 *)(from); - to += 4; - from += 4; - n -= 4; - } - while (n) { - *(char *)(to++) = *(char *)(from++); - n--; - } - } else { - while (n) { - *(char *)(to++) = *(char *)(from++); - n--; - } - } -} -#else -static inline unsigned long unalign_copy_to_user(void __user *to, - const void *from, - unsigned long n) -{ - return copy_to_user(to, from, n); -} -static inline unsigned long unalign_copy_from_user(void *to, - const void __user *from, - unsigned long n) -{ - return copy_from_user(to, from, n); -} -static inline void *unalign_memcpy(void *to, const void *from, size_t n) -{ - return memcpy(to, from, n); -} -#endif - -#endif diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/include/sipc_big_to_little.h b/package/wwan/driver/quectel_SRPD_PCIE/src/include/sipc_big_to_little.h deleted file mode 100644 index d70e61b0b..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/include/sipc_big_to_little.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#ifndef __SIPC_BIG_TO_LITTLE_H -#define __SIPC_BIG_TO_LITTLE_H -//#define CONFIG_SIPC_BIG_TO_LITTLE /* sipc little */ - -#define BL_READB(addr) \ - ({ unsigned char __v = (*(volatile unsigned char *) (addr)); __v; }) -#define BL_WRITEB(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b)) - -#define BL_GETB(v) ((v)) -#define BL_SETB(v, b) ((v) = (b)) - - -#ifdef CONFIG_SIPC_BIG_TO_LITTLE -/* little 0x78563412 - 0x12 - 0x34 - 0x56 - 0x78 - read: - big: 0x12345678==>0x78563412 - write: 0x78563412 ===> 0x12345678*/ -#define BL_READW(addr) \ - ({ unsigned short __t = (*(volatile unsigned short *) (addr)); \ - unsigned short __v = ((__t & 0x00ff) << 8) + ((__t & 0xff00) >> 8); \ - __v; }) -#define BL_READL(addr) \ - ({ unsigned int __t = (*(volatile unsigned int *) (addr)); \ - unsigned int __v = ((__t & 0x000000ff) << 24) + ((__t & 0x0000ff00) << 8) + \ - ((__t & 0x00ff0000) >> 8) + ((__t & 0xff000000) >> 24); \ - __v; }) - -#define BL_WRITEW(b,addr) \ - ({ unsigned short __v = (((b) & 0x00ff) << 8) + (((b) & 0xff00) >> 8); \ - (*(volatile unsigned short *) (addr)) = __v; }) - -#define BL_WRITEL(b,addr) \ - ({ unsigned int __v = (((b) & 0x000000ff) << 24) + (((b) & 0xff00) >> 8) + \ - (((b) & 0x00ff0000) >> 8) + (((b) & 0xff000000) >> 24); \ - (*(volatile unsigned int *) (addr)) = __v; }) - -#define BL_GETL(v) \ -({unsigned int __v = (((v) & 0x000000ff) << 24) + (((v) & 0x0000ff00) << 8) + \ - (((v) & 0x00ff0000) >> 8) + (((v) & 0xff000000) >> 24); \ - __v; }) -#define BL_SETL(v, b) \ - ((v) = (((b) & 0x000000ff) << 24) + (((b) & 0x0000ff00) << 8) + \ - (((b) & 0x00ff0000) >> 8) + (((b) & 0xff000000) >> 24)) -#define BL_GETW(v) \ - ({unsigned int __v = (((v) & 0x00ff) << 8) + (((v) & 0xff00) >> 8); \ - __v; }) -#define BL_SETW(v, b) \ - ((v) = (((b) & 0x00ff) << 8) + (((b) & 0xff00) >> 8)) - -#else -#define BL_GETW(v) v -#define BL_GETL(v) v - -#define BL_SETW(v, b) ((v) = (b)) -#define BL_SETL(v, b) ((v) = (b)) - -#define BL_READW(addr) \ - ({ unsigned short __v = (*(volatile unsigned short *) (addr)); __v; }) -#define BL_READL(addr) \ - ({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; }) - -#define BL_WRITEW(b,addr) (void)((*(volatile unsigned short *) (addr)) = (b)) -#define BL_WRITEL(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b)) - -#endif - -#endif - diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/include/sprd_mpm.h b/package/wwan/driver/quectel_SRPD_PCIE/src/include/sprd_mpm.h deleted file mode 100644 index f9ffe7457..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/include/sprd_mpm.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - - /* MPM: modem power manger - * PMS: power manage source which be used to request - * a modem power manage resource. - */ -#ifndef _SPRD_MPM_H -#define _SPRD_MPM_H -/* - * MPM modem powermanger source state define, - * if in idle state, we can release - * the related resources(such as pcie) of modem. - */ -enum { - SPRD_MPM_IDLE = 0, - SPRD_MPM_BUSY -}; - -/* - * @sprd_pms: the power manager source data struct, - * can usd it to request wake lock or request modem resource. - * - * @name: the name of a pms. - * @data: the point of MPM. - * @multitask: whether to support multitasking, default is false. - * false, the source can only be used in single task context. - * true, the source can be used multitask context. - * @awake: whether stay awake. - * @awake_cnt: total awake times. - * @pre_awake_cnt pre_awake_cnt. - * @active_cnt: the active counter of the pms. - * @expires: the timer expires value. - * @active_lock: use for protect the active_cnt member. - * @expires_lock: use for protect expires member. - * @entry: an entry of all pms list. - * @wake_timer: used for delay release wakelock. - */ -struct sprd_pms { - const char *name; - void *data; - bool multitask; - bool awake; - unsigned int awake_cnt; - unsigned int pre_awake_cnt; - unsigned int active_cnt; - unsigned long expires; - spinlock_t active_lock; - spinlock_t expires_lock; - struct list_head entry; - struct timer_list wake_timer; -}; - -/** - * sprd_mpm_create - create a modem powermanger source instacnce. - * - * @dst, which mpm (PSCP, SP, WCN, etc.) will be created. - * @later_idle, will release resource later (in ms). - */ -int sprd_mpm_create(unsigned int dst, - const char *name, - unsigned int later_idle); - -/** - * sprd_mpm_init_resource_ops - int resource ops for mpm. - * - * @wait_resource, used to wait request resource ready. - * @request_resource, used to request a resource - * @release_resource, used to release a resource - */ -int sprd_mpm_init_resource_ops(unsigned int dst, - int (*wait_resource)(unsigned int dst, - int timeout), - int (*request_resource)(unsigned int dst), - int (*release_resource)(unsigned int dst)); - -/** - * sprd_mpm_destroy - destroy a modem powermanger source instacnce. - * - * @dst, which mpm (PSCP, SP, WCN, etc.) will be destroyed. - */ -int sprd_mpm_destroy(unsigned int dst); - -/** - * sprd_pms_create - init a pms, - * a module which used it to request a modem power manage resource. - * All the pms interface are not safe in multi-thread or multi-cpu. - * if you want use in multi-thread, please use the pms_ext interface. - * - * @dst, the pms belong to which mpm. - * @name, the name of this pms. - * @pms, the point of this pms. - * @multitask: support multitask. - * - * Returns: NULL failed, > 0 succ. - */ -struct sprd_pms *sprd_pms_create(unsigned int dst, - const char *name, bool multitask); - -/** - * sprd_pms_destroy - destroy a pms. - * - * @pms, the point of this pms. - */ -void sprd_pms_destroy(struct sprd_pms *pms); - -/** - * sprd_pms_request_resource - request mpm resource - * - * @pms, the point of this pms. - * @timeout, in ms. - * - * Returns: - * 0 resource ready, - * < 0 resoure not ready, - * -%ERESTARTSYS if it was interrupted by a signal. - */ -int sprd_pms_request_resource(struct sprd_pms *pms, int timeout); - -/** - * sprd_pms_release_resource - release mpm resource. - * - * @pms, the point of this pms. - */ -void sprd_pms_release_resource(struct sprd_pms *pms); - -/** - * sprd_pms_request_wakelock - request wakelock - * - * @pms, the point of this pms. - */ -void sprd_pms_request_wakelock(struct sprd_pms *pms); - -/** - * sprd_pms_release_wakelock - release wakelock - * - * @pms, the point of this pms. - */ -void sprd_pms_release_wakelock(struct sprd_pms *pms); - -/** - * sprd_pms_request_wakelock_period - - * request wake lock, and will auto reaslse in msec ms. - * - * @pms, the point of this pms. - * @msec, will auto reaslse in msec ms - */ -void sprd_pms_request_wakelock_period(struct sprd_pms *pms, unsigned int msec); - -/** - * sprd_pms_release_wakelock_later - release wakelock later. - * - * @pms, the point of this pms. - * @msec, later time (in ms). - */ -void sprd_pms_release_wakelock_later(struct sprd_pms *pms, - unsigned int msec); - -/** - * sprd_pms_power_up - just powe up, not wait result. - * - * @pms, the point of this pms. - */ -void sprd_pms_power_up(struct sprd_pms *pms); - -/** - * sprd_pms_power_up - just power down,. - * - * @pms, the point of this pms. - * @immediately, whether immediately power down. - */ -void sprd_pms_power_down(struct sprd_pms *pms, bool immediately); - -#endif diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/include/sprd_pcie_ep_device.h b/package/wwan/driver/quectel_SRPD_PCIE/src/include/sprd_pcie_ep_device.h deleted file mode 100644 index 7b6245610..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/include/sprd_pcie_ep_device.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * SPRD ep device driver in host side for Spreadtrum SoCs - * - * Copyright (C) 2019 Spreadtrum Co., Ltd. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 of - * the License as published by the Free Software Foundation. - * - * This program is used to control ep device driver in host side for - * Spreadtrum SoCs. - */ - -#ifndef __SPRD_PCIE_EP_DEVICE_H -#define __SPRD_PCIE_EP_DEVICE_H - -#include - -/* host receive msi irq */ -enum { - PCIE_MSI_SIPC_IRQ = 0, - PCIE_MSI_REQUEST_RES, - PCIE_MSI_EP_READY_FOR_RESCAN, - PCIE_MSI_RELEASE_RES, - PCIE_MSI_SCANNED_RESPOND, - PCIE_MSI_REMOVE_RESPOND, - PCIE_MSI_IPA, - PCIE_MSI_MAX_IRQ -}; - -/* host send doorbell irq */ -enum { - PCIE_DBELL_SIPC_IRQ = 0, - PCIE_DBEL_EP_SCANNED, - PCIE_DBEL_EP_REMOVING, - PCIE_DBEL_IRQ_MAX -}; - -enum { - PCIE_EP_MODEM = 0, - /* PCIE_EP_WCN, */ - PCIE_EP_NR -}; - -enum { - PCIE_EP_PROBE = 0, - PCIE_EP_REMOVE, - PCIE_EP_PROBE_BEFORE_SPLIT_BAR -}; - -#ifdef CONFIG_SPRD_SIPA -enum { - PCIE_IPA_TYPE_MEM = 0, - PCIE_IPA_TYPE_REG -}; -#endif - -#define MINI_REGION_SIZE 0x10000 /*64 K default */ - -int sprd_ep_dev_register_notify(int ep, - void (*notify)(int event, void *data), - void *data); -int sprd_ep_dev_unregister_notify(int ep); -int sprd_ep_dev_register_irq_handler(int ep, - int irq, - irq_handler_t handler, - void *data); -int sprd_ep_dev_unregister_irq_handler(int ep, int irq); -int sprd_ep_dev_register_irq_handler_ex(int ep, - int from_irq, - int to_irq, - irq_handler_t handler, - void *data); -int sprd_ep_dev_unregister_irq_handler_ex(int ep, - int from_irq, - int to_irq); -int sprd_ep_dev_set_irq_addr(int ep, void __iomem *irq_addr); -int sprd_ep_dev_raise_irq(int ep, int irq); -int sprd_ep_dev_clear_doolbell_irq(int ep, int irq); -int sprd_ep_dev_set_backup(int ep); -int sprd_ep_dev_clear_backup(int ep); - -void __iomem *sprd_ep_map_memory(int ep, - phys_addr_t cpu_addr, - size_t size); -void sprd_ep_unmap_memory(int ep, const void __iomem *bar_addr); -int sprd_ep_dev_pass_smem(int ep, u32 base, u32 size); -int sipa_module_init(struct device *dev); -void sipa_module_exit(void); -int sipa_eth_init(void); -void sipa_eth_exit(void); -int sipa_dummy_init(void); -void sipa_dummy_exit(void); - -#ifdef CONFIG_SPRD_SIPA -phys_addr_t sprd_ep_ipa_map(int type, phys_addr_t target_addr, size_t size); -int sprd_ep_ipa_unmap(int type, phys_addr_t cpu_addr); -#endif -#endif diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/include/sprd_pcie_resource.h b/package/wwan/driver/quectel_SRPD_PCIE/src/include/sprd_pcie_resource.h deleted file mode 100644 index 902de45cf..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/include/sprd_pcie_resource.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - - /* mpms: modem powermanger source */ -#ifndef _SPRD_PCIE_RESOURCE_H -#define _SPRD_PCIE_RESOURCE_H - -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE -#include -#endif - -#if 0 -//#undef pr_debug -//#define pr_debug pr_emerg - -#undef pr_info -#define pr_info pr_emerg - -#undef pr_err -#define pr_err pr_emerg - -#undef dev_dbg -#define dev_dbg dev_emerg - -#undef dev_info -#define dev_info dev_emerg - -#undef dev_err -#define dev_err dev_emerg -#endif - -#if defined(CONFIG_SPRD_PCIE_EP_DEVICE) || defined(CONFIG_PCIE_EPF_SPRD) -/* - * sprd_pcie_wait_resource - * Returns: - * 0 resource ready, - * < 0 resoure not ready, - * -%ERESTARTSYS if it was interrupted by a signal. - */ -int sprd_pcie_wait_resource(u32 dst, int timeout); - -int sprd_pcie_request_resource(u32 dst); -int sprd_pcie_release_resource(u32 dst); -int sprd_pcie_resource_trash(u32 dst); -bool sprd_pcie_is_defective_chip(void); -#else -/* dummy functions */ -static inline int sprd_pcie_wait_resource(u32 dst, int timeout) {return 0; } - -static inline int sprd_pcie_request_resource(u32 dst) {return 0; } -static inline int sprd_pcie_release_resource(u32 dst) {return 0; } -static inline int sprd_pcie_resource_trash(u32 dst) {return 0; } -static inline bool sprd_pcie_is_defective_chip(void) {return false; } -#endif - -#ifdef CONFIG_PCIE_EPF_SPRD -int sprd_pcie_resource_client_init(u32 dst, u32 ep_fun); -int sprd_register_pcie_resource_first_ready(u32 dst, - void (*notify)(void *p), - void *data); -#endif - -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE -int sprd_pcie_resource_host_init(u32 dst, u32 ep_dev, - struct platform_device *pcie_dev); - -/* - * sprd_pcie_resource_reboot_ep - * reboot ep contains rescan ep device. - */ -void sprd_pcie_resource_reboot_ep(u32 dst); - -/* - * sprd_pcie_wait_load_resource - * In case of the open the feature CONFIG_PCIE_SPRD_SPLIT_BAR, - * It has 2 times pcie scan action in host side boot process. - * After the first scan, the ep only have 2 bar can be used for - * memory map, the pcie resource is not completely ready, - * but the host can load images for ep, so we add the special api - * sprd_pcie_wait_load_resource, this api will return after - * the first scan action. - * Returns: - * 0 resource ready, - * < 0 resoure not ready, - * -%ERESTARTSYS if it was interrupted by a signal. - */ -int sprd_pcie_wait_load_resource(u32 dst); - - -/* Because the ep bar can only be split by ep itself, - * After all modem images be loaded, notify pcie resource - * can rescan ep now. - */ -void sprd_pcie_resource_notify_load_done(u32 dst); -#endif /* CONFIG_SPRD_PCIE_EP_DEVICE */ - -#endif /* _SPRD_PCIE_RESOURCE_H */ diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/mcd/Kconfig b/package/wwan/driver/quectel_SRPD_PCIE/src/mcd/Kconfig deleted file mode 100644 index a7f3db524..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/mcd/Kconfig +++ /dev/null @@ -1,7 +0,0 @@ -config SPRD_MCD - tristate "SPRD modem power control module" - default n - help - mcd is a module for spreadtrum AP/CP communicaiton control driver, - it can control modem power on/off,triger modem event of assert,watchdog - reset,panic. diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/mcd/Makefile b/package/wwan/driver/quectel_SRPD_PCIE/src/mcd/Makefile deleted file mode 100644 index 78cb07515..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/mcd/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y += modem_ctrl.o diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/mcd/modem_ctrl.c b/package/wwan/driver/quectel_SRPD_PCIE/src/mcd/modem_ctrl.c deleted file mode 100644 index 720b92340..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/mcd/modem_ctrl.c +++ /dev/null @@ -1,814 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_PCIE_PM_NOTIFY -#include -#endif - -#include "../include/sprd_pcie_resource.h" -#include "../include/sipc.h" -#include "../include/mdm_ctrl.h" - -enum { - ROC1_SOC = 0, - ORCA_SOC -}; - -static char *const mdm_stat[] = { - "mdm_power_off", "mdm_power_on", "mdm_warm_reset", "mdm_cold_reset", - "mdm_watchdog_reset", "mdm_assert", "mdm_panic" -}; - -#define REBOOT_MODEM_DELAY 1000 -#define POWERREST_MODEM_DELAY 2000 -#define RESET_MODEM_DELAY 50 - -char cdev_name[] = "mdm_ctrl"; - -struct modem_ctrl_init_data { - char *name; - struct gpio_desc *gpio_poweron; /* Poweron */ - struct gpio_desc *gpio_reset; /* Reset modem */ - struct gpio_desc *gpio_preset; /* Pcie reset */ - struct gpio_desc *gpio_cpwatchdog; - struct gpio_desc *gpio_cpassert; - struct gpio_desc *gpio_cppanic; - struct gpio_desc *gpio_cppoweroff; - u32 irq_cpwatchdog; - u32 irq_cpassert; - u32 irq_cppanic; - u32 irq_cppoweroff; - u32 modem_status; - bool enable_cp_event; -}; - -struct modem_ctrl_device { - struct modem_ctrl_init_data *init; - int major; - int minor; - struct cdev cdev; - struct device *dev; - int soc_type; -}; - -static struct class *modem_ctrl_class; -static struct modem_ctrl_device *mcd_dev; - -/* modem control evnet notify */ -static ATOMIC_NOTIFIER_HEAD(modem_ctrl_chain); - -int modem_ctrl_register_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_register(&modem_ctrl_chain, nb); -} -EXPORT_SYMBOL(modem_ctrl_register_notifier); - -void modem_ctrl_unregister_notifier(struct notifier_block *nb) -{ - atomic_notifier_chain_unregister(&modem_ctrl_chain, nb); -} -EXPORT_SYMBOL(modem_ctrl_unregister_notifier); - -static void send_event_msg(struct kobject *kobj) -{ - char *msg[3]; - char buff[100]; - char mbuff[100]; - - memset(mbuff, 0, sizeof(mbuff)); - if (!mcd_dev || !mcd_dev->init || !kobj) - return; - - snprintf(buff, sizeof(buff), "MODEM_STAT=%d", - mcd_dev->init->modem_status); - snprintf(mbuff, sizeof(mbuff), "MODEM_EVENT=%s", - mdm_stat[mcd_dev->init->modem_status]); - msg[0] = buff; - msg[1] = mbuff; - msg[2] = NULL; - kobject_uevent_env(kobj, KOBJ_CHANGE, msg); - dev_dbg(mcd_dev->dev, "send uevent to userspace\n"); -} - -static irqreturn_t cpwatchdogtriger_handler(int irq, void *dev_id) -{ - if (!mcd_dev || !mcd_dev->init || !mcd_dev->init->enable_cp_event) - return IRQ_NONE; - - mcd_dev->init->modem_status = MDM_WATCHDOG_RESET; - atomic_notifier_call_chain(&modem_ctrl_chain, MDM_WATCHDOG_RESET, NULL); - send_event_msg(&mcd_dev->dev->kobj); - return IRQ_HANDLED; -} - -static irqreturn_t cpasserttriger_handler(int irq, void *dev_id) -{ - if (!mcd_dev || !mcd_dev->init || !mcd_dev->init->enable_cp_event) - return IRQ_NONE; - - mcd_dev->init->modem_status = MDM_ASSERT; - atomic_notifier_call_chain(&modem_ctrl_chain, MDM_ASSERT, NULL); - send_event_msg(&mcd_dev->dev->kobj); - return IRQ_HANDLED; -} - -static irqreturn_t cppanictriger_handler(int irq, void *dev_id) -{ - if (!mcd_dev || !mcd_dev->init || !mcd_dev->init->enable_cp_event) - return IRQ_NONE; - - mcd_dev->init->modem_status = MDM_PANIC; - atomic_notifier_call_chain(&modem_ctrl_chain, MDM_PANIC, NULL); - send_event_msg(&mcd_dev->dev->kobj); - return IRQ_HANDLED; -} - -static irqreturn_t cppoweroff_handler(int irq, void *dev_id) -{ - if (!mcd_dev || !mcd_dev->init) - return IRQ_NONE; - /* To this reserve here for receve power off event from AP*/ - atomic_notifier_call_chain(&modem_ctrl_chain, - MDM_POWER_OFF, NULL); - kernel_power_off(); - return IRQ_HANDLED; -} - -static int request_gpio_to_irq(struct gpio_desc *cp_gpio, - struct modem_ctrl_device *mcd_dev) -{ - int ret = 0; - - if (!mcd_dev || !mcd_dev->init) - return -EINVAL; - - ret = gpiod_to_irq(cp_gpio); - if (ret < 0) { - dev_err(mcd_dev->dev, "requset irq %d failed\n", ret); - return ret; - } - dev_dbg(mcd_dev->dev, "gpio to irq %d\n", ret); - if (cp_gpio == mcd_dev->init->gpio_cpwatchdog) { - mcd_dev->init->irq_cpwatchdog = ret; - ret = devm_request_threaded_irq(mcd_dev->dev, - mcd_dev->init->irq_cpwatchdog, - NULL, cpwatchdogtriger_handler, - IRQF_ONESHOT | IRQF_TRIGGER_FALLING, - "cpwatchdog_irq", mcd_dev); - if (ret < 0) { - dev_err(mcd_dev->dev, "can not request irq for cp watchdog\n"); - return ret; - } - enable_irq_wake(mcd_dev->init->irq_cpwatchdog); - } else if (cp_gpio == mcd_dev->init->gpio_cpassert) { - mcd_dev->init->irq_cpassert = ret; - ret = devm_request_threaded_irq(mcd_dev->dev, - mcd_dev->init->irq_cpassert, - NULL, cpasserttriger_handler, - IRQF_ONESHOT | IRQF_TRIGGER_FALLING, - "cpassert_irq", mcd_dev); - if (ret < 0) { - dev_err(mcd_dev->dev, "can not request irq for cp assert\n"); - return ret; - } - enable_irq_wake(mcd_dev->init->irq_cpassert); - } else if (cp_gpio == mcd_dev->init->gpio_cppanic) { - mcd_dev->init->irq_cppanic = ret; - ret = devm_request_threaded_irq(mcd_dev->dev, - mcd_dev->init->irq_cppanic, - NULL, cppanictriger_handler, - IRQF_ONESHOT | IRQF_TRIGGER_FALLING, - "cppanic_irq", mcd_dev); - if (ret < 0) { - dev_err(mcd_dev->dev, - "can not request irq for panic\n"); - return ret; - } - enable_irq_wake(mcd_dev->init->irq_cppanic); - } else if (cp_gpio == mcd_dev->init->gpio_cppoweroff) { - mcd_dev->init->irq_cppoweroff = ret; - ret = devm_request_threaded_irq(mcd_dev->dev, - mcd_dev->init->irq_cppoweroff, - NULL, cppoweroff_handler, - IRQF_ONESHOT | IRQF_TRIGGER_LOW, - "cppoweroff_irq", mcd_dev); - if (ret < 0) { - dev_err(mcd_dev->dev, - "can not request irq for cppoweroff\n"); - return ret; - } - enable_irq_wake(mcd_dev->init->irq_cppoweroff); - } - return 0; -} - -static int modem_gpios_init(struct modem_ctrl_device *mcd_dev, int soc_type) -{ - int ret; - - if (!mcd_dev || !mcd_dev->init) - return -EINVAL; - if (soc_type == ROC1_SOC) { - gpiod_direction_input(mcd_dev->init->gpio_cpwatchdog); - gpiod_direction_input(mcd_dev->init->gpio_cpassert); - gpiod_direction_input(mcd_dev->init->gpio_cppanic); - - ret = request_gpio_to_irq(mcd_dev->init->gpio_cpwatchdog, - mcd_dev); - if (ret) - return ret; - ret = request_gpio_to_irq(mcd_dev->init->gpio_cpassert, - mcd_dev); - if (ret) - return ret; - ret = request_gpio_to_irq(mcd_dev->init->gpio_cppanic, - mcd_dev); - if (ret) - return ret; - - /* IRQF_TRIGGER_LOW, default must set to high */ - gpiod_set_value_cansleep(mcd_dev->init->gpio_cppoweroff, 1); - } else { - gpiod_direction_input(mcd_dev->init->gpio_cppoweroff); - ret = request_gpio_to_irq(mcd_dev->init->gpio_cppoweroff, - mcd_dev); - if (ret) - return ret; - - /* TRIGGER_FALLING, defaultmust set to high */ - gpiod_set_value_cansleep(mcd_dev->init->gpio_cpwatchdog, 1); - gpiod_set_value_cansleep(mcd_dev->init->gpio_cpassert, 1); - gpiod_set_value_cansleep(mcd_dev->init->gpio_cppanic, 1); - } - return 0; -} - -void modem_ctrl_enable_cp_event(void) -{ - if (mcd_dev && mcd_dev->init) - mcd_dev->init->enable_cp_event = true; -} -EXPORT_SYMBOL_GPL(modem_ctrl_enable_cp_event); - -void modem_ctrl_send_abnormal_to_ap(int status) -{ - struct gpio_desc *gpiodesc; - - if (!mcd_dev || !mcd_dev->init) - return; - if (mcd_dev->soc_type != ORCA_SOC) { - dev_err(mcd_dev->dev, "operation not be allowed for %d\n", - mcd_dev->soc_type); - return; - } - switch (status) { - case MDM_WATCHDOG_RESET: - gpiodesc = mcd_dev->init->gpio_cpwatchdog; - break; - case MDM_ASSERT: - gpiodesc = mcd_dev->init->gpio_cpassert; - break; - case MDM_PANIC: - gpiodesc = mcd_dev->init->gpio_cppanic; - break; - default: - dev_info(mcd_dev->dev, - "get status %d is not right for operation\n", status); - return; - } - mcd_dev->init->modem_status = status; - dev_info(mcd_dev->dev, - "operation unnormal status %d send to ap\n", - status); - if (!IS_ERR(gpiodesc)) - gpiod_set_value_cansleep(gpiodesc, 0); -} - -static void modem_ctrl_send_cmd_to_cp(int status) -{ - struct gpio_desc *gpiodesc = NULL; - - if (!mcd_dev || !mcd_dev->init) - return; - if (mcd_dev->soc_type != ROC1_SOC) { - dev_err(mcd_dev->dev, "operation not be allowed for %d\n", - mcd_dev->soc_type); - return; - } - if (status == MDM_POWER_OFF) - gpiodesc = mcd_dev->init->gpio_cppoweroff; - - mcd_dev->init->modem_status = status; - dev_info(mcd_dev->dev, - "operation cmd %d ms send to cp\n", - status); - if (!IS_ERR(gpiodesc)) { - gpiod_set_value_cansleep(gpiodesc, 0); - msleep(20); - gpiod_set_value_cansleep(gpiodesc, 20); - } -} - -static void modem_ctrl_notify_abnormal_status(int status) -{ - if (!mcd_dev || !mcd_dev->init) - return; - if (mcd_dev->soc_type != ORCA_SOC) { - dev_err(mcd_dev->dev, "operation not be allowed for %d\n", - mcd_dev->soc_type); - return; - } - if (status < MDM_WATCHDOG_RESET || status > MDM_PANIC) { - dev_err(mcd_dev->dev, - "operation not be allowed for status %d\n", status); - return; - } - modem_ctrl_send_abnormal_to_ap(status); -} - -void modem_ctrl_poweron_modem(int on) -{ - if (!mcd_dev || !mcd_dev->init) - return; - switch (on) { - case MDM_CTRL_POWER_ON: - if (!IS_ERR(mcd_dev->init->gpio_poweron)) { - atomic_notifier_call_chain(&modem_ctrl_chain, - MDM_CTRL_POWER_ON, NULL); - dev_info(mcd_dev->dev, "set modem_poweron: %d\n", on); - gpiod_set_value_cansleep(mcd_dev->init->gpio_poweron, - 1); - /* Base the spec modem boot flow that need to wait 1s */ - msleep(REBOOT_MODEM_DELAY); - mcd_dev->init->modem_status = MDM_CTRL_POWER_ON; - gpiod_set_value_cansleep(mcd_dev->init->gpio_poweron, - 0); - } - break; - case MDM_CTRL_POWER_OFF: - /* - *To do - */ - break; - case MDM_CTRL_SET_CFG: - /* - *To do - */ - break; - case MDM_CTRL_WARM_RESET: - if (!IS_ERR(mcd_dev->init->gpio_reset)) { - atomic_notifier_call_chain(&modem_ctrl_chain, - MDM_CTRL_WARM_RESET, NULL); - dev_dbg(mcd_dev->dev, "set warm reset: %d\n", on); - gpiod_set_value_cansleep(mcd_dev->init->gpio_reset, 1); - /* Base the spec modem that need to wait 50ms */ - msleep(RESET_MODEM_DELAY); - mcd_dev->init->modem_status = MDM_CTRL_WARM_RESET; - gpiod_set_value_cansleep(mcd_dev->init->gpio_reset, 0); - } - break; - case MDM_CTRL_COLD_RESET: - if (!IS_ERR(mcd_dev->init->gpio_poweron)) { - mcd_dev->init->enable_cp_event = false; - atomic_notifier_call_chain(&modem_ctrl_chain, - MDM_CTRL_COLD_RESET, NULL); - dev_info(mcd_dev->dev, "modem_power reset: %d\n", on); - gpiod_set_value_cansleep(mcd_dev->init->gpio_poweron, - 1); - /* Base the spec modem boot flow that need to wait 2s */ - msleep(POWERREST_MODEM_DELAY); - mcd_dev->init->modem_status = MDM_CTRL_COLD_RESET; - gpiod_set_value_cansleep(mcd_dev->init->gpio_poweron, - 0); - } - break; - case MDM_CTRL_PCIE_RECOVERY: -#ifdef CONFIG_PCIE_PM_NOTIFY - pcie_ep_pm_notify(PCIE_EP_POWER_OFF); - /* PCIE poweroff to poweron need 100ms*/ - msleep(100); - pcie_ep_pm_notify(PCIE_EP_POWER_ON); -#endif - break; - case MDM_POWER_OFF: - atomic_notifier_call_chain(&modem_ctrl_chain, - MDM_POWER_OFF, NULL); - modem_ctrl_send_cmd_to_cp(MDM_POWER_OFF); - break; - default: - dev_err(mcd_dev->dev, "cmd not support: %d\n", on); - } -} -EXPORT_SYMBOL_GPL(modem_ctrl_poweron_modem); - -#if defined(CONFIG_DEBUG_FS) -static int modem_ctrl_debug_show(struct seq_file *m, void *private) -{ - dev_dbg(mcd_dev->dev, "%s\n", __func__); - return 0; -} - -static int modem_ctrl_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, modem_ctrl_debug_show, inode->i_private); -} - -static const struct file_operations modem_ctrl_debug_fops = { - .open = modem_ctrl_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -#endif /* CONFIG_DEBUG_FS */ - -static int modem_ctrl_open(struct inode *inode, struct file *filp) -{ - struct modem_ctrl_device *modem_ctrl; - - modem_ctrl = container_of(inode->i_cdev, - struct modem_ctrl_device, cdev); - filp->private_data = modem_ctrl; - dev_dbg(modem_ctrl->dev, "modem_ctrl: %s\n", __func__); - return 0; -} - -static int modem_ctrl_release(struct inode *inode, struct file *filp) -{ - struct modem_ctrl_device *modem_ctrl; - - modem_ctrl = container_of(inode->i_cdev, - struct modem_ctrl_device, cdev); - dev_dbg(modem_ctrl->dev, "modem_ctrl: %s\n", __func__); - - return 0; -} - -static ssize_t modem_ctrl_read(struct file *filp, - char __user *buf, - size_t count, - loff_t *ppos) -{ - char tmpbuf[30]; - int r; - struct modem_ctrl_device *mcd_dev = filp->private_data; - - if (!mcd_dev || !mcd_dev->init) - return -EINVAL; - - r = snprintf(tmpbuf, sizeof(tmpbuf), "%s\n", - mdm_stat[mcd_dev->init->modem_status]); - - return simple_read_from_buffer(buf, count, ppos, tmpbuf, r); -} - -static ssize_t modem_ctrl_write(struct file *filp, - const char __user *buf, - size_t count, loff_t *ppos) -{ - char sbuf[100]; - int ret; - u32 mcd_cmd; - struct modem_ctrl_device *mcd_dev = filp->private_data; - - if (!mcd_dev) - return -EINVAL; - - if (unalign_copy_from_user((void *)sbuf, buf, count)) { - dev_err(mcd_dev->dev, "copy buf %s error\n", buf); - return -EFAULT; - } - dev_dbg(mcd_dev->dev, "get info:%s", sbuf); - sbuf[count - 1] = '\0'; - ret = kstrtouint(sbuf, 10, &mcd_cmd); - if (ret) { - dev_err(mcd_dev->dev, "Invalid input!\n"); - return ret; - } - if (mcd_dev->soc_type == ROC1_SOC) { - if (mcd_cmd >= MDM_CTRL_POWER_OFF && - mcd_cmd <= MDM_CTRL_SET_CFG) - modem_ctrl_poweron_modem(mcd_cmd); - else - dev_info(mcd_dev->dev, "cmd not support!\n"); - } else { - modem_ctrl_notify_abnormal_status(mcd_cmd); - } - return count; -} - -static long modem_ctrl_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - - if (!mcd_dev || mcd_dev->soc_type == ORCA_SOC) - return -EINVAL; - switch (cmd) { - case MDM_CTRL_POWER_OFF: - modem_ctrl_poweron_modem(MDM_CTRL_POWER_OFF); - break; - case MDM_CTRL_POWER_ON: - modem_ctrl_poweron_modem(MDM_CTRL_POWER_ON); - break; - case MDM_CTRL_WARM_RESET: - modem_ctrl_poweron_modem(MDM_CTRL_WARM_RESET); - break; - case MDM_CTRL_COLD_RESET: - modem_ctrl_poweron_modem(MDM_CTRL_COLD_RESET); - break; - case MDM_CTRL_PCIE_RECOVERY: - modem_ctrl_poweron_modem(MDM_CTRL_PCIE_RECOVERY); - break; - case MDM_CTRL_SET_CFG: - break; - default: - return -EINVAL; - } - return 0; -} - -static const struct file_operations modem_ctrl_fops = { - .open = modem_ctrl_open, - .release = modem_ctrl_release, - .read = modem_ctrl_read, - .write = modem_ctrl_write, - .unlocked_ioctl = modem_ctrl_ioctl, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -static int modem_ctrl_parse_modem_dt(struct modem_ctrl_init_data **init, - struct device *dev) -{ - struct modem_ctrl_init_data *pdata = NULL; - - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - pdata->name = cdev_name; - - /* Triger watchdog,assert,panic of orca */ - pdata->gpio_cpwatchdog = devm_gpiod_get(dev, - "cpwatchdog", - GPIOD_OUT_HIGH); - if (IS_ERR(pdata->gpio_cpwatchdog)) - return PTR_ERR(pdata->gpio_cpwatchdog); - - pdata->gpio_cpassert = devm_gpiod_get(dev, "cpassert", GPIOD_OUT_HIGH); - if (IS_ERR(pdata->gpio_cpassert)) - return PTR_ERR(pdata->gpio_cpassert); - - pdata->gpio_cppanic = devm_gpiod_get(dev, "cppanic", GPIOD_OUT_HIGH); - if (IS_ERR(pdata->gpio_cppanic)) - return PTR_ERR(pdata->gpio_cppanic); - - pdata->gpio_cppoweroff = devm_gpiod_get(dev, "cppoweroff", GPIOD_IN); - if (IS_ERR(pdata->gpio_cpassert)) - return PTR_ERR(pdata->gpio_cppoweroff); - - *init = pdata; - return 0; -} - -static int modem_ctrl_parse_dt(struct modem_ctrl_init_data **init, - struct device *dev) -{ - struct modem_ctrl_init_data *pdata; - - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - pdata->name = cdev_name; - pdata->gpio_poweron = devm_gpiod_get(dev, "poweron", GPIOD_OUT_LOW); - if (IS_ERR(pdata->gpio_poweron)) - return PTR_ERR(pdata->gpio_poweron); - - pdata->gpio_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(pdata->gpio_reset)) - return PTR_ERR(pdata->gpio_reset); - - /* Triger watchdog,assert,panic of orca */ - pdata->gpio_cpwatchdog = devm_gpiod_get(dev, "cpwatchdog", GPIOD_IN); - if (IS_ERR(pdata->gpio_cpwatchdog)) - return PTR_ERR(pdata->gpio_cpwatchdog); - - pdata->gpio_cpassert = devm_gpiod_get(dev, "cpassert", GPIOD_IN); - if (IS_ERR(pdata->gpio_cpassert)) - return PTR_ERR(pdata->gpio_cpassert); - - pdata->gpio_cppanic = devm_gpiod_get(dev, "cppanic", GPIOD_IN); - if (IS_ERR(pdata->gpio_cppanic)) - return PTR_ERR(pdata->gpio_cppanic); - - pdata->gpio_cppoweroff = devm_gpiod_get(dev, - "cppoweroff", GPIOD_OUT_HIGH); - if (IS_ERR(pdata->gpio_cpassert)) - return PTR_ERR(pdata->gpio_cppoweroff); - - pdata->modem_status = MDM_CTRL_POWER_OFF; - *init = pdata; - return 0; -} - -static inline void -modem_ctrl_destroy_pdata(struct modem_ctrl_init_data **init) -{ - struct modem_ctrl_init_data *pdata = *init; - - pdata = NULL; -} - -static int modem_ctrl_restart_handle(struct notifier_block *this, - unsigned long mode, void *cmd) -{ - if (!mcd_dev || mcd_dev->soc_type == ROC1_SOC) - return NOTIFY_DONE; - modem_ctrl_notify_abnormal_status(MDM_PANIC); - while (1) - ; - return NOTIFY_DONE; -} - -static struct notifier_block modem_ctrl_restart_handler = { - .notifier_call = modem_ctrl_restart_handle, - .priority = 150, -}; - -static int modem_ctrl_probe(struct platform_device *pdev) -{ - struct modem_ctrl_init_data *init = pdev->dev.platform_data; - struct modem_ctrl_device *modem_ctrl_dev; - dev_t devid; - int rval; - struct device *dev = &pdev->dev; - - modem_ctrl_dev = devm_kzalloc(dev, sizeof(*modem_ctrl_dev), GFP_KERNEL); - if (!modem_ctrl_dev) - return -ENOMEM; - mcd_dev = modem_ctrl_dev; - if (of_device_is_compatible(pdev->dev.of_node, "sprd,roc1-modem-ctrl")) - modem_ctrl_dev->soc_type = ROC1_SOC; - else - modem_ctrl_dev->soc_type = ORCA_SOC; - - if (modem_ctrl_dev->soc_type == ROC1_SOC) { - rval = modem_ctrl_parse_dt(&init, &pdev->dev); - if (rval) { - dev_err(dev, - "Failed to parse modem_ctrl device tree, ret=%d\n", - rval); - return rval; - } - } else { - rval = modem_ctrl_parse_modem_dt(&init, &pdev->dev); - if (rval) { - dev_err(dev, - "Failed to parse modem_ctrl device tree, ret=%d\n", - rval); - return rval; - } - } - - dev_dbg(dev, "after parse device tree, name=%s soctype=%d\n", - init->name, - modem_ctrl_dev->soc_type); - - rval = alloc_chrdev_region(&devid, 0, 1, init->name); - if (rval != 0) { - dev_err(dev, "Failed to alloc modem_ctrl chrdev\n"); - goto error3; - } - cdev_init(&modem_ctrl_dev->cdev, &modem_ctrl_fops); - rval = cdev_add(&modem_ctrl_dev->cdev, devid, 1); - if (rval != 0) { - dev_err(dev, "Failed to add modem_ctrl cdev\n"); - goto error2; - } - - modem_ctrl_dev->major = MAJOR(devid); - modem_ctrl_dev->minor = MINOR(devid); - modem_ctrl_dev->dev = device_create(modem_ctrl_class, NULL, - MKDEV(modem_ctrl_dev->major, - modem_ctrl_dev->minor), - NULL, "%s", init->name); - if (!modem_ctrl_dev->dev) { - dev_err(dev, "create dev failed\n"); - rval = -ENODEV; - goto error1; - } - modem_ctrl_dev->init = init; - platform_set_drvdata(pdev, modem_ctrl_dev); - rval = modem_gpios_init(modem_ctrl_dev, modem_ctrl_dev->soc_type); - if (rval) { - dev_err(dev, "request gpios error\n"); - goto error0; - } - - rval = register_restart_handler(&modem_ctrl_restart_handler); - if (rval) { - dev_err(dev, "cannot register restart handler err=%d\n", rval); - goto error0; - } - return 0; -error0: - device_destroy(modem_ctrl_class, - MKDEV(modem_ctrl_dev->major, - modem_ctrl_dev->minor)); -error1: - cdev_del(&modem_ctrl_dev->cdev); -error2: - unregister_chrdev_region(devid, 1); -error3: - modem_ctrl_destroy_pdata(&init); - return rval; -} - -static int modem_ctrl_remove(struct platform_device *pdev) -{ - struct modem_ctrl_device *modem_ctrl_dev = platform_get_drvdata(pdev); - - unregister_reboot_notifier(&modem_ctrl_restart_handler); - device_destroy(modem_ctrl_class, - MKDEV(modem_ctrl_dev->major, - modem_ctrl_dev->minor)); - cdev_del(&modem_ctrl_dev->cdev); - unregister_chrdev_region(MKDEV(modem_ctrl_dev->major, - modem_ctrl_dev->minor), 1); - modem_ctrl_destroy_pdata(&modem_ctrl_dev->init); - platform_set_drvdata(pdev, NULL); - return 0; -} - -static void modem_ctrl_shutdown(struct platform_device *pdev) -{ - if (mcd_dev->soc_type == ROC1_SOC) { - atomic_notifier_call_chain(&modem_ctrl_chain, - MDM_POWER_OFF, NULL); - /* - * sleep 50 ms for other module to do something - * before orca power down. - */ - msleep(50); - modem_ctrl_send_cmd_to_cp(MDM_POWER_OFF); - /* Sleep 500ms for cp to deal power down process otherwise - * cp will not power down clearly. - */ - msleep(500); - } -} - -static const struct of_device_id modem_ctrl_match_table[] = { - {.compatible = "sprd,roc1-modem-ctrl", }, - {.compatible = "sprd,orca-modem-ctrl", }, -}; - -static struct platform_driver modem_ctrl_driver = { - .driver = { - .name = "modem_ctrl", - .of_match_table = modem_ctrl_match_table, - }, - .probe = modem_ctrl_probe, - .remove = modem_ctrl_remove, - .shutdown = modem_ctrl_shutdown, -}; - -int modem_ctrl_init(void) -{ - modem_ctrl_class = class_create(THIS_MODULE, "modem_ctrl"); - if (IS_ERR(modem_ctrl_class)) - return PTR_ERR(modem_ctrl_class); - return platform_driver_register(&modem_ctrl_driver); -} -EXPORT_SYMBOL_GPL(modem_ctrl_init); - -void modem_ctrl_exit(void) -{ - class_destroy(modem_ctrl_class); - platform_driver_unregister(&modem_ctrl_driver); -} -EXPORT_SYMBOL_GPL(modem_ctrl_exit); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/Kconfig b/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/Kconfig deleted file mode 100644 index ac88510e7..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/Kconfig +++ /dev/null @@ -1,7 +0,0 @@ - -config SPRD_PCIE_EP_DEVICE - tristate "SPRD PCIE EP device" - default n - depends on PCI - help - SPRD pcie ep device driver in host side for Spreadtrum. \ No newline at end of file diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/Makefile b/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/Makefile deleted file mode 100644 index 0f62c8a12..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -ccflags-y += -DCONFIG_SPRD_PCIE_EP_DEVICE -DCONFIG_SPRD_SIPA -obj-y += sprd_pcie_ep_device.o -obj-y += pcie_host_resource.o -obj-y += sprd_pcie_quirks.o -obj-$(CONFIG_PCIE_EPF_SPRD) += pcie_client_resource.o -obj-$(CONFIG_SPRD_SIPA_RES) += pcie_sipa_res.o diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/pcie_client_resource.c b/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/pcie_client_resource.c deleted file mode 100644 index 74e5d72ff..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/pcie_client_resource.c +++ /dev/null @@ -1,528 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sprd_pcie_resource.h" -#ifdef CONFIG_SPRD_SIPA_RES -#include "pcie_sipa_res.h" -#endif - -enum ep_msg { - RC_SCANNED_MSG = 0, - RC_REMOVING_MSG, - EPC_UNLINK_MSG, - EPC_LINKUP_MSG -}; - -enum pcie_ep_state { - SPRD_PCIE_WAIT_FIRST_READY = 0, - SPRD_PCIE_WAIT_SCANNED, - SPRD_PCIE_SCANNED, - SPRD_PCIE_WAIT_REMOVED, - SPRD_PCIE_REMOVED, - SPRD_PCIE_WAIT_POWER_OFF -}; - -struct sprd_pci_res_notify { - void (*notify)(void *p); - void *data; -}; - -struct sprd_pcie_res { - u32 dst; - u32 ep_fun; - enum pcie_ep_state state; - bool msi_later; - bool wakeup_later; - -#ifdef CONFIG_SPRD_SIPA_RES - void *sipa_res; -#endif - - /* - * in client(Orca), The PCIE module wll blocks the chip Deep, - * so we must get a wake lock when pcie work to avoid this situation: - * the system is deep, but the PCIE is still working. - */ - struct wakeup_source ws; - wait_queue_head_t wait_pcie_ready; - struct sprd_pci_res_notify first_ready_notify; -}; - -static struct sprd_pcie_res *g_pcie_res[SIPC_ID_NR]; - -/* the state machine of ep, init SPRD_PCIE_WAIT_FIRST_READY. - * SPRD_PCIE_WAIT_FIRST_READY (receive RC scanned) ==> SPRD_PCIE_SCANNED - * SPRD_PCIE_SCANNED (receive RC removing)==> SPRD_PCIE_WAIT_REMOVED - * SPRD_PCIE_WAIT_REMOVED(receive epc unlink)==>SPRD_PCIE_REMOVED - * SPRD_PCIE_REMOVED(receive epc linkup)==>SPRD_PCIE_WAIT_SCANNED - * SPRD_PCIE_WAIT_SCANNED(receive RC scanned)==>SPRD_PCIE_SCANNED - * SPRD_PCIE_WAIT_POWER_OFF can do nothing, just wait shutdown. - */ -static const char *change_msg[EPC_LINKUP_MSG + 1] = { - "rc scanned", - "rc removing", - "epc unlink", - "epc linkup" -}; - -static const char *state_msg[SPRD_PCIE_REMOVED + 1] = { - "wait first ready", - "wait sacanned", - "scanned", - "wait remove", - "removed" -}; - -static void pcie_resource_client_change_state(struct sprd_pcie_res *res, - enum ep_msg msg) -{ - u32 old_state = res->state; - - if (old_state == SPRD_PCIE_WAIT_POWER_OFF) - return; - - pr_debug("pcie res: change state msg=%s, old_state=%s.\n", - change_msg[msg], state_msg[old_state]); - - switch (msg) { - case RC_SCANNED_MSG: - if (old_state != SPRD_PCIE_WAIT_FIRST_READY - && old_state != SPRD_PCIE_WAIT_SCANNED) { - pr_err("pcie res: %s msg err, old state=%s", - change_msg[msg], state_msg[old_state]); - return; - } - res->state = SPRD_PCIE_SCANNED; - break; - - case RC_REMOVING_MSG: - if (old_state != SPRD_PCIE_SCANNED) { - pr_err("pcie res: %s msg err, old state=%s", - change_msg[msg], state_msg[old_state]); - return; - } - res->state = SPRD_PCIE_WAIT_REMOVED; - break; - - case EPC_UNLINK_MSG: - if (old_state != SPRD_PCIE_WAIT_REMOVED) { - if (old_state != SPRD_PCIE_WAIT_FIRST_READY) - pr_err("pcie res: %s msg err, old state=%s", - change_msg[msg], state_msg[old_state]); - return; - } - res->state = SPRD_PCIE_REMOVED; - break; - - case EPC_LINKUP_MSG: - if (old_state != SPRD_PCIE_REMOVED) { - if (old_state != SPRD_PCIE_WAIT_FIRST_READY) - pr_err("pcie res: %s msg err, old state=%s", - change_msg[msg], state_msg[old_state]); - return; - } - res->state = SPRD_PCIE_WAIT_SCANNED; - break; - } - - pr_info("pcie res: change state from %s to %s.\n", - state_msg[old_state], state_msg[res->state]); -} - -static void sprd_pcie_resource_first_ready_notify(struct sprd_pcie_res *res) -{ - void (*notify)(void *p); - - pr_info("pcie res: first ready.\n"); - -#ifdef CONFIG_SPRD_SIPA_RES - /* - * in client side, producer res id is SIPA_RM_RES_PROD_PCIE_EP, - * consumer res id is SIPA_RM_RES_CONS_WWAN_DL. - */ - res->sipa_res = pcie_sipa_res_create(res->dst, - SIPA_RM_RES_PROD_PCIE_EP, - SIPA_RM_RES_CONS_WWAN_DL); - if (!res->sipa_res) - pr_err("pcie res:create ipa res failed.\n"); -#endif - - notify = res->first_ready_notify.notify; - if (notify) - notify(res->first_ready_notify.data); -} - -static void pcie_resource_client_epf_notify(int event, void *private) -{ - struct sprd_pcie_res *res = (struct sprd_pcie_res *)private; - - if (res->state == SPRD_PCIE_WAIT_POWER_OFF) - return; - - switch (event) { - case SPRD_EPF_BIND: - pr_info("pcie res: epf be binded.\n"); - if (sprd_pcie_is_defective_chip()) - sprd_pci_epf_raise_irq(res->ep_fun, - PCIE_MSI_EP_READY_FOR_RESCAN); - break; - - case SPRD_EPF_UNBIND: - pr_info("pcie res: epf be unbinded.\n"); - break; - - case SPRD_EPF_REMOVE: - pr_info("pcie res: epf be removed.\n"); - break; - - case SPRD_EPF_LINK_UP: - /* get a wakelock */ - __pm_stay_awake(&res->ws); - - pr_info("pcie res: epf linkup.\n"); - pcie_resource_client_change_state(res, EPC_LINKUP_MSG); - - /* first ready notify */ - if (res->state == SPRD_PCIE_WAIT_FIRST_READY) - sprd_pcie_resource_first_ready_notify(res); - - break; - - case SPRD_EPF_UNLINK: - /* Here need this log to debug pcie scan and remove */ - pr_info("pcie res: epf unlink.\n"); - pcie_resource_client_change_state(res, EPC_UNLINK_MSG); - - /* if has wakeup pending, send wakeup to rc */ - if (res->wakeup_later) { - res->wakeup_later = false; - pr_info("pcie res: send wakeup to rc.\n"); - if (sprd_pci_epf_start(res->ep_fun)) - pr_err("pcie res: send wakeup to rc failed.\n"); - } - - /* relax a wakelock */ - __pm_relax(&res->ws); - break; - - default: - break; - } -} - -static irqreturn_t pcie_resource_client_irq_handler(int irq, void *private) -{ - struct sprd_pcie_res *res = (struct sprd_pcie_res *)private; - - if (res->state == SPRD_PCIE_WAIT_POWER_OFF) - return IRQ_HANDLED; - - if (irq == PCIE_DBEL_EP_SCANNED) { - pcie_resource_client_change_state(res, RC_SCANNED_MSG); - - /* wakeup all blocked thread */ - pr_info("pcie res: scanned, wakup all.\n"); - wake_up_interruptible_all(&res->wait_pcie_ready); - - /* if has msi pending, send msi to rc */ - if (res->msi_later) { - res->msi_later = false; - pr_info("pcie res: request msi to rc.\n"); - sprd_pci_epf_raise_irq(res->ep_fun, - PCIE_MSI_REQUEST_RES); - } - } else if (irq == PCIE_DBEL_EP_REMOVING) { - pr_info("pcie res: removing.\n"); - pcie_resource_client_change_state(res, RC_REMOVING_MSG); - } - - return IRQ_HANDLED; -} - -static int sprd_pcie_resource_client_mcd(struct notifier_block *nb, - unsigned long mode, void *cmd) -{ - struct sprd_pcie_res *res; - int i; - - pr_info("pcie res: mcd event mode=%ld.\n", mode); - - if (mode != MDM_POWER_OFF) - return NOTIFY_DONE; - - for (i = 0; i < SIPC_ID_NR; i++) { - res = g_pcie_res[i]; - if (res) - res->state = SPRD_PCIE_WAIT_POWER_OFF; - } - - return NOTIFY_DONE; -} - -static struct notifier_block mcd_notify = { - .notifier_call = sprd_pcie_resource_client_mcd, - .priority = 149, -}; - -int sprd_pcie_resource_client_init(u32 dst, u32 ep_fun) -{ - struct sprd_pcie_res *res; - - if (dst >= SIPC_ID_NR) - return -EINVAL; - - res = kzalloc(sizeof(*res), GFP_KERNEL); - if (!res) - return -ENOMEM; - - res->dst = dst; - res->state = SPRD_PCIE_WAIT_FIRST_READY; - res->ep_fun = ep_fun; - - wakeup_source_init(&res->ws, "pcie_res"); - - init_waitqueue_head(&res->wait_pcie_ready); - sprd_pci_epf_register_irq_handler_ex(res->ep_fun, - PCIE_DBEL_EP_SCANNED, - PCIE_DBEL_EP_REMOVING, - pcie_resource_client_irq_handler, - res); - sprd_pci_epf_register_notify(res->ep_fun, - pcie_resource_client_epf_notify, - res); - - modem_ctrl_register_notifier(&mcd_notify); - - g_pcie_res[dst] = res; - - return 0; -} - -int sprd_pcie_resource_trash(u32 dst) -{ - struct sprd_pcie_res *res; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - -#ifdef CONFIG_SPRD_SIPA_RES - if (res->sipa_res) - pcie_sipa_res_destroy(res->sipa_res); -#endif - - sprd_pci_epf_unregister_irq_handler_ex(res->ep_fun, - PCIE_DBEL_EP_SCANNED, - PCIE_DBEL_EP_REMOVING); - sprd_pci_epf_unregister_notify(res->ep_fun); - modem_ctrl_unregister_notifier(&mcd_notify); - - kfree(res); - g_pcie_res[dst] = NULL; - - return 0; -} - -int sprd_pcie_wait_resource(u32 dst, int timeout) -{ - struct sprd_pcie_res *res; - int ret, wait; - unsigned long delay; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - - /* pcie ready, return succ immediately */ - if (res->state == SPRD_PCIE_SCANNED) - return 0; - - if (timeout == 0) - return -ETIME; - - if (timeout < 0) { - wait = wait_event_interruptible( - res->wait_pcie_ready, - res->state == SPRD_PCIE_SCANNED - ); - ret = wait; - } else { - /* - * timeout must add 1s, - * because the pcie rescan may took some time. - */ - delay = msecs_to_jiffies(timeout + 1000); - wait = wait_event_interruptible_timeout(res->wait_pcie_ready, - res->state == - SPRD_PCIE_SCANNED, - delay); - if (wait == 0) - ret = -ETIME; - else if (wait > 0) - ret = 0; - else - ret = wait; - } - - if (ret < 0 && ret != -ERESTARTSYS) - pr_err("pcie res: wait resource, val=%d.\n", ret); - - return ret; -} - -int sprd_pcie_request_resource(u32 dst) -{ - struct sprd_pcie_res *res; - int ret = 0; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - - if (res->state == SPRD_PCIE_WAIT_POWER_OFF) - return -EINVAL; - - pr_debug("pcie res: request res, state=%d.\n", res->state); - - switch (res->state) { - case SPRD_PCIE_WAIT_FIRST_READY: - case SPRD_PCIE_WAIT_SCANNED: - pr_info("pcie res: later send request msi to rc.\n"); - res->msi_later = true; - break; - - case SPRD_PCIE_WAIT_REMOVED: - pr_info("pcie res: later send wakeup to rc.\n"); - res->wakeup_later = true; - break; - - case SPRD_PCIE_SCANNED: - /* - * if pcie state is SCANNED, just send - * PCIE_MSI_REQUEST_RES to the host. - * After host receive res msi interrupt, - * it will increase one vote in modem power manger. - */ - pr_info("pcie res: send request msi to rc.\n"); - ret = sprd_pci_epf_raise_irq(res->ep_fun, - PCIE_MSI_REQUEST_RES); - break; - - case SPRD_PCIE_REMOVED: - /* - * if pcie state is removed, poll wake_up singnal - * to host, and he host will rescan the pcie. - */ - pr_info("pcie res: send wakeup to rc.\n"); - if (sprd_pci_epf_start(res->ep_fun) == 0) - break; - - /* may receive ep reset, wait linkup and scanned */ - pr_info("pcie res: later send request msi to rc.\n"); - res->msi_later = true; - break; - - default: - pr_err("pcie res: request res err, state=%d.\n", - res->state); - ret = -EPERM; - break; - } - - return ret; -} - -int sprd_pcie_release_resource(u32 dst) -{ - struct sprd_pcie_res *res; - int ret = 0; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - - if (res->state == SPRD_PCIE_WAIT_POWER_OFF) - return -EINVAL; - - switch (res->state) { - case SPRD_PCIE_SCANNED: - /* - * if pcie state is SCANNED, send PCIE_MSI_RELEASE_RES - * to the host, else, do nothing. After host receive res msi - * interrupt, it will decrease one vote in modem power manger, - * and if modem power manger is idle, the host will remove - * the pcie. - */ - pr_info("pcie res: send release msi to rc.\n"); - ret = sprd_pci_epf_raise_irq(res->ep_fun, - PCIE_MSI_RELEASE_RES); - break; - - case SPRD_PCIE_WAIT_FIRST_READY: - /* if has msi pending, remove it */ - if (res->msi_later) - res->msi_later = false; - break; - - default: - pr_err("pcie res: release res state=%d.\n", res->state); - ret = -EPERM; - break; - } - - return ret; -} - -int sprd_register_pcie_resource_first_ready(u32 dst, - void (*notify)(void *p), void *data) -{ - struct sprd_pcie_res *res; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - - res->first_ready_notify.data = data; - res->first_ready_notify.notify = notify; - - return 0; -} - -bool sprd_pcie_is_defective_chip(void) -{ - static bool first_read = true, defective; - - if (first_read) { - first_read = false; - defective = sprd_kproperty_chipid("UD710-AB") == 0; - } - - return defective; -} diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/pcie_host_resource.c b/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/pcie_host_resource.c deleted file mode 100644 index 5b753440d..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/pcie_host_resource.c +++ /dev/null @@ -1,720 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_SPRD_SIPA_RES -#include "pcie_sipa_res.h" -#endif - -#include "../include/pcie-rc-sprd.h" -#include "../include/sipc.h" -//#include "../include/mdm_ctrl.h" -#include "../include/sprd_pcie_ep_device.h" -#include "../include/sprd_mpm.h" -#include "../include/sprd_pcie_resource.h" - -#define PCIE_REMOVE_SCAN_GAP msecs_to_jiffies(200) -#define MAX_PMS_WAIT_TIME 5000 -#define MAX_PMS_DEFECTIVE_CHIP_FIRST_WAIT_TIME (55 * 1000) - -enum rc_state { - SPRD_PCIE_WAIT_FIRST_READY = 0, - SPRD_PCIE_WAIT_SCANNED, - SPRD_PCIE_SCANNED, - SPRD_PCIE_WAIT_REMOVED, - SPRD_PCIE_REMOVED, - SPRD_PCIE_SCANNED_2BAR, - SPRD_PCIE_WAIT_POWER_OFF -}; - -struct sprd_pcie_res { - u32 dst; - u32 ep_dev; - u32 state; - u32 scan_cnt; - u32 max_wait_time; - bool ep_power_on; - bool ep_dev_probe; - bool smem_send_to_ep; - unsigned long action_jiff; - - struct sprd_pms *pms; - char pms_name[20]; - - wait_queue_head_t wait_pcie_ready; - bool ep_ready_for_rescan; - wait_queue_head_t wait_load_ready; - wait_queue_head_t wait_first_rescan; - struct task_struct *thread; - -#ifdef CONFIG_SPRD_SIPA_RES - void *sipa_res; -#endif -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,18,0 )) - struct wakeup_source *ws; -#else - struct wakeup_source ws; -#endif - struct work_struct scan_work; - struct work_struct remove_work; - struct workqueue_struct *wq; - - struct platform_device *pcie_dev; - struct sprd_pcie_register_event reg_event; -}; - -static int sprd_pcie_resource_rescan(struct sprd_pcie_res *res); - -static struct sprd_pcie_res *g_pcie_res[SIPC_ID_NR]; - -static void sprd_pcie_resource_host_first_rescan_do(struct sprd_pcie_res *res) -{ - int ret = sprd_pcie_register_event(&res->reg_event); - - if (ret) - pr_err("pcie res: register pci ret=%d.\n", ret); - - /* power up for ep after the first scan. */ - res->ep_power_on = true; - sprd_pms_power_up(res->pms); - -#ifdef CONFIG_SPRD_SIPA_RES - /* - * in host side, producer res id is SIPA_RM_RES_PROD_PCIE3, - * consumer res id is SIPA_RM_RES_CONS_WWAN_UL. - */ - res->sipa_res = pcie_sipa_res_create(res->dst, - SIPA_RM_RES_PROD_PCIE3, - SIPA_RM_RES_CONS_WWAN_UL); - if (!res->sipa_res) - pr_err("pcie res:create ipa res failed.\n"); -#endif - -} - -static void sprd_pcie_resource_host_ep_notify(int event, void *data) -{ - struct sprd_pcie_res *res = (struct sprd_pcie_res *)data; - u32 base, size; - - /* wait power off, do nothing */ - if (res->state == SPRD_PCIE_WAIT_POWER_OFF) - return; - - switch (event) { - case PCIE_EP_PROBE: - /* set state to scanned */ - res->state = SPRD_PCIE_SCANNED; - res->scan_cnt++; - res->ep_dev_probe = true; - //modem_ctrl_enable_cp_event(); - - if (smem_get_area(SIPC_ID_MINIAP, &base, &size) == 0) - sprd_ep_dev_pass_smem(res->ep_dev, base, size); - - pr_info("pcie res: ep_notify, probed cnt=%d.\n", - res->scan_cnt); - - /* firsrt scan do somtehing */ - if (res->scan_cnt == 1) - sprd_pcie_resource_host_first_rescan_do(res); - - /* clear removed irq and notify ep scanned */ - sprd_ep_dev_clear_doolbell_irq(res->ep_dev, - PCIE_DBEL_EP_REMOVING); - sprd_ep_dev_raise_irq(res->ep_dev, PCIE_DBEL_EP_SCANNED); - - /* wakeup all blocked thread */ - wake_up_interruptible_all(&res->wait_pcie_ready); - break; - - case PCIE_EP_REMOVE: - pr_info("pcie res: ep_notify, removed.\n"); - res->state = SPRD_PCIE_REMOVED; - res->ep_dev_probe = false; - break; - - case PCIE_EP_PROBE_BEFORE_SPLIT_BAR: - res->state = SPRD_PCIE_SCANNED_2BAR; - res->ep_dev_probe = true; - pr_info("pcie res: probed before split bar.\n"); - if (!res->ep_ready_for_rescan) { - wake_up_interruptible_all(&res->wait_load_ready); - } else { - pr_info("pcie res: bar err, rescan.\n"); - sprd_pcie_resource_rescan(res); - } - break; - - default: - break; - } -} - -static irqreturn_t sprd_pcie_resource_host_irq_handler(int irq, void *private) -{ - struct sprd_pcie_res *res = (struct sprd_pcie_res *)private; - - if (irq == PCIE_MSI_REQUEST_RES) { - pr_info("pcie res: ep request res.\n"); - /* - * client modem power up, - * no need wake lock and no need wait resource. - */ - if (!res->ep_power_on) { - res->ep_power_on = true; - sprd_pms_power_up(res->pms); - } - - /* only after received ep request can backup the ep configs. */ - sprd_ep_dev_set_backup(res->ep_dev); - } else if (irq == PCIE_MSI_RELEASE_RES) { - pr_info("pcie res: ep release res.\n"); - /* - * client modem power down, - * no need wake lock. - */ - if (res->ep_power_on) { - res->ep_power_on = false; - sprd_pms_power_down(res->pms, false); - } - } else if (irq == PCIE_MSI_EP_READY_FOR_RESCAN) { - pr_info("pcie res: ep ready for rescan.\n"); - res->ep_ready_for_rescan = true; - wake_up_interruptible_all(&res->wait_first_rescan); - } - - return IRQ_HANDLED; -} - -static void sprd_pcie_resource_scan_fn(struct work_struct *work) -{ - unsigned long diff; - unsigned int delay; - int ret; - struct sprd_pcie_res *res = container_of(work, struct sprd_pcie_res, - scan_work); - - /* wait power off, do nothing */ - if (res->state == SPRD_PCIE_WAIT_POWER_OFF) - return; - - /* request wakelock */ - sprd_pms_request_wakelock(res->pms); - - diff = jiffies - res->action_jiff; - if (diff < PCIE_REMOVE_SCAN_GAP) { - /* must ensure that the scan starts after a period of remove. */ - delay = jiffies_to_msecs(PCIE_REMOVE_SCAN_GAP - diff); - msleep(delay); - } - - pr_info("pcie res: scan\n"); - - ret = sprd_pcie_configure_device(res->pcie_dev); - if (ret) - pr_err("pcie res: scan error = %d!\n", ret); - - /* record the last scan jiffies */ - res->action_jiff = jiffies; - - /* release wakelock */ - sprd_pms_release_wakelock(res->pms); -} - -static void sprd_pcie_resource_remove_fn(struct work_struct *work) -{ - unsigned long diff; - unsigned int delay; - int ret; - struct sprd_pcie_res *res = container_of(work, struct sprd_pcie_res, - remove_work); - /* request wakelock */ - sprd_pms_request_wakelock(res->pms); - - pr_info("pcie res: remove work!\n"); - - diff = jiffies - res->action_jiff; - if (diff < PCIE_REMOVE_SCAN_GAP) { - /* must ensure that the remove starts after a period of scan. */ - delay = jiffies_to_msecs(PCIE_REMOVE_SCAN_GAP - diff); - msleep(delay); - } - - /* - * in wait power off state, or ep device is not probing, - * can't access ep. - */ - if (res->state == SPRD_PCIE_WAIT_POWER_OFF || - !res->ep_dev_probe) { - /* release wakelock */ - sprd_pms_release_wakelock(res->pms); - return; - } - - /* notify ep removed, must before removed */ - sprd_ep_dev_clear_doolbell_irq(res->ep_dev, PCIE_DBEL_EP_SCANNED); - sprd_ep_dev_raise_irq(res->ep_dev, PCIE_DBEL_EP_REMOVING); - - /* waiting for the doorbell irq to ep */ - msleep(50); - - pr_info("pcie res: remove\n"); - - /* start removed ep*/ - ret = sprd_pcie_unconfigure_device(res->pcie_dev); - if (ret) - pr_err("pcie res: remove error = %d.\n!", ret); - - /* record the last remov jiffies */ - res->action_jiff = jiffies; - - /* release wakelock */ - sprd_pms_release_wakelock(res->pms); -} - -static void sprd_pcie_resource_start_scan(struct sprd_pcie_res *res) -{ - if (res->state == SPRD_PCIE_SCANNED || - res->state == SPRD_PCIE_WAIT_SCANNED) { - pr_info("pcie res: scanned, do nothing!\n"); - } else { - pr_info("pcie res: start scan!\n"); - queue_work(res->wq, &res->scan_work); - } -} - -static void sprd_pcie_resource_start_remove(struct sprd_pcie_res *res) -{ - /* wait power off, do nothing */ - if (res->state == SPRD_PCIE_WAIT_POWER_OFF) - return; - - if (res->state == SPRD_PCIE_SCANNED || - res->state == SPRD_PCIE_WAIT_FIRST_READY - || (res->state == SPRD_PCIE_SCANNED_2BAR) - ) { - res->state = SPRD_PCIE_WAIT_REMOVED; - pr_info("pcie res: start remove."); - queue_work(res->wq, &res->remove_work); - } else { - pr_err("pcie res: start remove, err=%d.", res->state); - } -} - -static void sprd_pcie_resource_event_process(enum sprd_pcie_event event, - void *data) -{ - struct sprd_pcie_res *res = data; - - if (event == SPRD_PCIE_EVENT_WAKEUP) { - pr_info("pcie res: wakeup by ep, event=%d.\n", event); - if (!res->ep_power_on) { - res->ep_power_on = true; - sprd_pms_power_up(res->pms); - } - } -} - -/* - * sprd_pcie_resource_rescan - * Because the ep bar can only be split by ep itself, - * After all modem images be loaded at the first time, - * the ep will run and split 2 64bit bar to 4 32bit bar. - * host must rescan the pcie ep device agian by this api, - * after receive ep driver ready for rescan msg and all - * modem images load done. - */ -static int sprd_pcie_resource_rescan(struct sprd_pcie_res *res) -{ - pr_info("pcie res: rescan.\n"); - - sprd_pcie_resource_start_remove(res); - sprd_pcie_resource_start_scan(res); - - return 0; -} - -static int sprd_pcie_resource_check_first_rescan(void *data) -{ - struct sprd_pcie_res *res = data; - int ret; - - pr_info("pcie res: check first rescan.\n"); - - while (!kthread_should_stop()) { - ret = wait_event_interruptible( - res->wait_first_rescan, - res->ep_ready_for_rescan); - if (!ret) { - pr_info("pcie res:first resacn ready.\n"); - sprd_pcie_resource_rescan(res); - break; - } - } - - /* After the first rescan, restore the normal wait time. */ - if (sprd_pcie_is_defective_chip()) - res->max_wait_time = MAX_PMS_WAIT_TIME; - - res->thread = NULL; - return 0; -} - -#if 0 -static int sprd_pcie_resource_host_mcd(struct notifier_block *nb, - unsigned long mode, void *cmd) -{ - struct sprd_pcie_res *res; - int i; - u32 state; - - pr_info("pcie res: mcd mode=%ld.\n", mode); - - switch (mode) { - case MDM_POWER_OFF: - state = SPRD_PCIE_WAIT_POWER_OFF; - break; - - default: - return NOTIFY_DONE; - } - - for (i = 0; i < SIPC_ID_NR; i++) { - res = g_pcie_res[i]; - - /* wait power off, do nothing */ - if (res->state == SPRD_PCIE_WAIT_POWER_OFF) - continue; - - if (res) { - res->state = state; - cancel_work_sync(&res->scan_work); - cancel_work_sync(&res->remove_work); - } - } - - return NOTIFY_DONE; -} - -static struct notifier_block mcd_notify = { - .notifier_call = sprd_pcie_resource_host_mcd, - .priority = 149, -}; -#endif - -/* Because the ep bar can only be split by ep itself, - * After all modem images be loaded, notify the pcie resource. - */ -void sprd_pcie_resource_notify_load_done(u32 dst) -{ - struct sprd_pcie_res *res; - - pr_info("pcie res: load done.\n"); - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return; - - res = g_pcie_res[dst]; - - res->thread = kthread_create(sprd_pcie_resource_check_first_rescan, res, - "first rescan"); - if (IS_ERR(res->thread)) - pr_err("pcie res: Failed to create rescan thread.\n"); - else - wake_up_process(res->thread); -} - -int sprd_pcie_wait_load_resource(u32 dst) -{ - struct sprd_pcie_res *res; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - - /* can load image, return immediately */ - if (res->state == SPRD_PCIE_SCANNED || - res->state == SPRD_PCIE_SCANNED_2BAR) - return 0; - - return wait_event_interruptible( - res->wait_load_ready, - (res->state == SPRD_PCIE_SCANNED || - res->state == SPRD_PCIE_SCANNED_2BAR)); -} - -void sprd_pcie_resource_reboot_ep(u32 dst) -{ - struct sprd_pcie_res *res; - - pr_info("pcie res: reboot ep.\n"); - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return; - - res = g_pcie_res[dst]; - - /* wait power off, do nothing */ - if (res->state == SPRD_PCIE_WAIT_POWER_OFF) - return; - - res->state = SPRD_PCIE_WAIT_FIRST_READY; - res->smem_send_to_ep = false; - res->ep_ready_for_rescan = false; - - /* The defective chip , the first wait time must be enough long. */ - if (sprd_pcie_is_defective_chip()) - res->max_wait_time = MAX_PMS_DEFECTIVE_CHIP_FIRST_WAIT_TIME; - else - res->max_wait_time = MAX_PMS_WAIT_TIME; - - /* after ep reboot, can't backup ep configs*/ - sprd_ep_dev_clear_backup(res->ep_dev); - - sprd_pcie_resource_start_remove(res); - //modem_ctrl_poweron_modem(MDM_CTRL_COLD_RESET); - sprd_pcie_resource_start_scan(res); -} - -int sprd_pcie_resource_host_init(u32 dst, u32 ep_dev, - struct platform_device *pcie_dev) -{ - struct sprd_pcie_res *res; - - if (dst >= SIPC_ID_NR) - return -EINVAL; - - res = kzalloc(sizeof(*res), GFP_KERNEL); - if (!res) - return -ENOMEM; - - res->wq = create_singlethread_workqueue("pcie_res"); - if (!res->wq) { - pr_err("pcie res:create wq failed.\n"); - kfree(res); - return -ENOMEM; - } - - init_waitqueue_head(&res->wait_load_ready); - init_waitqueue_head(&res->wait_first_rescan); - -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,18,0 )) - res->ws = wakeup_source_register(NULL, "pcie_res"); -#else - wakeup_source_init(&res->ws, "pcie_res"); -#endif - - res->dst = dst; - res->state = SPRD_PCIE_WAIT_FIRST_READY; - res->pcie_dev = pcie_dev; - - /* The defective chip , the first wait time must be enough long. */ - if (sprd_pcie_is_defective_chip()) - res->max_wait_time = MAX_PMS_DEFECTIVE_CHIP_FIRST_WAIT_TIME; - else - res->max_wait_time = MAX_PMS_WAIT_TIME; - - init_waitqueue_head(&res->wait_pcie_ready); - INIT_WORK(&res->scan_work, sprd_pcie_resource_scan_fn); - INIT_WORK(&res->remove_work, sprd_pcie_resource_remove_fn); - - sprintf(res->pms_name, "ep-request-%d", dst); - res->pms = sprd_pms_create(dst, res->pms_name, false); - if (!res->pms) - pr_err("pcie res:create pms failed.\n"); - - sprd_ep_dev_register_irq_handler_ex(res->ep_dev, - PCIE_MSI_REQUEST_RES, - PCIE_MSI_RELEASE_RES, - sprd_pcie_resource_host_irq_handler, res); - - sprd_ep_dev_register_notify(res->ep_dev, - sprd_pcie_resource_host_ep_notify, res); - - //modem_ctrl_register_notifier(&mcd_notify); - - /* init wake up event callback */ - res->reg_event.events = SPRD_PCIE_EVENT_WAKEUP; - res->reg_event.pdev = pcie_dev; - res->reg_event.callback = sprd_pcie_resource_event_process; - res->reg_event.data = res; - - g_pcie_res[dst] = res; - - return 0; -} - -int sprd_pcie_resource_trash(u32 dst) -{ - struct sprd_pcie_res *res; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - - if (!IS_ERR_OR_NULL(res->thread)) - kthread_stop(res->thread); - -#ifdef CONFIG_SPRD_SIPA_RES - if (res->sipa_res) - pcie_sipa_res_destroy(res->sipa_res); -#endif - - cancel_work_sync(&res->scan_work); - cancel_work_sync(&res->remove_work); - destroy_workqueue(res->wq); - - sprd_pcie_deregister_event(&res->reg_event); - - sprd_ep_dev_unregister_irq_handler_ex(res->ep_dev, - PCIE_MSI_REQUEST_RES, - PCIE_MSI_RELEASE_RES); - sprd_ep_dev_unregister_notify(res->ep_dev); - //modem_ctrl_unregister_notifier(&mcd_notify); - sprd_pms_destroy(res->pms); - - kfree(res); - g_pcie_res[dst] = NULL; - - return 0; -} - -int sprd_pcie_wait_resource(u32 dst, int timeout) -{ - struct sprd_pcie_res *res; - int ret, wait; - unsigned long delay; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - - /* pcie ready, return succ immediately. */ - if (res->state == SPRD_PCIE_SCANNED) - return 0; - - if (timeout == 0) - return -ETIME; - - /* - * In some case, orca may has an exception, And the pcie - * resource may never ready again. So we must set a - * maximum wait time for let user to know thereis an - * exception in pcie, and can return an error code to the user. - */ - if (timeout < 0 || timeout > res->max_wait_time) - timeout = res->max_wait_time; - - /* - * timeout must add 1s, - * because the pcie scan may took some time. - */ - delay = msecs_to_jiffies(timeout + 1000); - wait = wait_event_interruptible_timeout(res->wait_pcie_ready, - res->state == - SPRD_PCIE_SCANNED, - delay); - if (wait == 0) - ret = -ETIME; - else if (wait > 0) - ret = 0; - else - ret = wait; - - - if (ret < 0 && ret != -ERESTARTSYS) - pr_err("pcie res: wait resource, val=%d.\n", ret); - - return ret; -} - -int sprd_pcie_request_resource(u32 dst) -{ - struct sprd_pcie_res *res; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - - /* get a wakelock */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,18,0 )) - __pm_stay_awake(res->ws); -#else - __pm_stay_awake(&res->ws); -#endif - - pr_info("pcie res: request resource, state=%d.\n", res->state); - -#ifdef CONFIG_SPRD_PCIE - /* The first scan is start by pcie driver automatically. */ - if (res->state != SPRD_PCIE_WAIT_FIRST_READY) - sprd_pcie_resource_start_scan(res); -#endif - - return 0; -} - -int sprd_pcie_release_resource(u32 dst) -{ - struct sprd_pcie_res *res; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - - /* relax a wakelock */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,18,0 )) - __pm_relax(res->ws); -#else - __pm_relax(&res->ws); -#endif - -#ifdef CONFIG_SPRD_PCIE - pr_info("pcie res: release resource.\n"); - - sprd_pcie_resource_start_remove(res); -#endif - return 0; -} - -bool sprd_pcie_is_defective_chip(void) -{ -#ifndef CONFIG_SPRD_PCIE - return false; -#else - static bool first_read = true, defective; - - if (first_read) { - first_read = false; - defective = sprd_kproperty_chipid("UD710-AB") == 0; - } - - return defective; -#endif -} diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/pcie_sipa_res.c b/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/pcie_sipa_res.c deleted file mode 100644 index dea3da3f3..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/pcie_sipa_res.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2018-2019 Unisoc Corporation - * - * 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 the GNU - * General Public License for more details. - */ -#include -#include -#include -#include - -#include "pcie_sipa_res.h" -#include "../include/sprd_pcie_resource.h" - -struct pcie_sipa_res_prod { - u8 dst; - enum sipa_rm_res_id prod_id; /* producer res id */ - enum sipa_rm_res_id cons_id; /* consumer res id */ - struct sprd_pms *pms; - char pms_name[20]; - struct work_struct wait_work; - struct delayed_work rm_work; -}; - -static void pcie_sipa_res_wait_res_work_fn(struct work_struct *work) -{ - int ret; - struct pcie_sipa_res_prod *res = container_of(work, - struct pcie_sipa_res_prod, - wait_work); - - ret = sprd_pcie_wait_resource(res->dst, -1); - - /* pcie not ready, just return. */ - if (ret) { - pr_err("pcie_sipa_res: wait res error = %d!\n", ret); - return; - } - - /* notify ipa module that pcie is ready. */ - sipa_rm_notify_completion(SIPA_RM_EVT_GRANTED, - res->prod_id); -} - -static int pcie_sipa_res_request_resource(void *data) -{ - int ret; - struct pcie_sipa_res_prod *res = data; - - pr_info("pcie_sipa_res: request resource.\n"); - - sprd_pms_power_up(res->pms); - - /* - * when the resource is not ready, the IPA module doesn't want be - * blocked in here until the pcie ready, the IPA owner designed - * a notification api sipa_rm_notify_completion to notify the - * IPA module that the resource requested by IPA is ready. - * The designated error value is -EINPROGRESS, so we must override the - * return value -ETIME to -EINPROGRESS. - */ - ret = sprd_pcie_wait_resource(res->dst, 0); - - if (ret == -ETIME) { - /* add a work to wait pcie ready */ - schedule_work(&res->wait_work); - ret = -EINPROGRESS; - } - - return ret; -} - -static int pcie_sipa_res_release_resource(void *data) -{ - struct pcie_sipa_res_prod *res = data; - - pr_info("pcie_sipa_res: release resource.\n"); - - sprd_pms_release_resource(res->pms); - - return 0; -} - -static void pcie_sipa_res_create_rm_work_fn(struct work_struct *work) -{ - int ret; - struct sipa_rm_create_params rm_params; - struct pcie_sipa_res_prod *res = container_of(to_delayed_work(work), - struct pcie_sipa_res_prod, - rm_work); - - rm_params.name = res->prod_id; - rm_params.floor_voltage = 0; - rm_params.reg_params.notify_cb = NULL; - rm_params.reg_params.user_data = res; - rm_params.request_resource = pcie_sipa_res_request_resource; - rm_params.release_resource = pcie_sipa_res_release_resource; - ret = sipa_rm_create_resource(&rm_params); - - /* defer to create rm */ - if (ret == -EPROBE_DEFER) { - schedule_delayed_work(&res->rm_work, msecs_to_jiffies(1000)); - return; - } - - /* add dependencys */ - ret = sipa_rm_add_dependency(res->cons_id, res->prod_id); - if (ret < 0 && ret != -EINPROGRESS) { - pr_err("pcie_sipa_res: add_dependency error = %d!\n", ret); - sipa_rm_delete_resource(res->prod_id); - sprd_pms_destroy(res->pms); - kfree(res); - } -} - -void *pcie_sipa_res_create(u8 dst, enum sipa_rm_res_id prod_id, - enum sipa_rm_res_id cons_id) -{ - int ret; - struct sipa_rm_create_params rm_params; - struct pcie_sipa_res_prod *res; - - res = kzalloc(sizeof(*res), GFP_KERNEL); - if (!res) - return NULL; - - /* init wait pcie res work */ - INIT_WORK(&res->wait_work, pcie_sipa_res_wait_res_work_fn); - INIT_DELAYED_WORK(&res->rm_work, pcie_sipa_res_create_rm_work_fn); - - /* create pms */ - strncpy(res->pms_name, "sipa", sizeof(res->pms_name)); - res->pms = sprd_pms_create(dst, res->pms_name, false); - if (!res->pms) { - pr_err("pcie_sipa_res: create pms failed!\n"); - kfree(res); - return NULL; - } - - res->dst = dst; - res->prod_id = prod_id; - res->cons_id = cons_id; - - /* create prod */ - rm_params.name = prod_id; - rm_params.floor_voltage = 0; - rm_params.reg_params.notify_cb = NULL; - rm_params.reg_params.user_data = res; - rm_params.request_resource = pcie_sipa_res_request_resource; - rm_params.release_resource = pcie_sipa_res_release_resource; - ret = sipa_rm_create_resource(&rm_params); - - /* defer to create rm */ - if (ret == -EPROBE_DEFER) { - schedule_delayed_work(&res->rm_work, msecs_to_jiffies(1000)); - return res; - } else if (ret) { - pr_err("pcie_sipa_res: create rm error = %d!\n", ret); - sprd_pms_destroy(res->pms); - kfree(res); - return NULL; - } - - /* add dependencys */ - ret = sipa_rm_add_dependency(cons_id, prod_id); - if (ret < 0 && ret != -EINPROGRESS) { - pr_err("pcie_sipa_res: add_dependency error = %d!\n", ret); - sipa_rm_delete_resource(prod_id); - sprd_pms_destroy(res->pms); - kfree(res); - return NULL; - } - - return res; -} - -void pcie_sipa_res_destroy(void *data) -{ - struct pcie_sipa_res_prod *res = data; - - cancel_work_sync(&res->wait_work); - cancel_delayed_work_sync(&res->rm_work); - - sprd_pms_destroy(res->pms); - sipa_rm_delete_dependency(res->cons_id, res->prod_id); - sipa_rm_delete_resource(res->prod_id); - kfree(res); -} - diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/pcie_sipa_res.h b/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/pcie_sipa_res.h deleted file mode 100644 index 144bcc5b5..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/pcie_sipa_res.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2018-2019 Unisoc Corporation - * - * 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 the GNU - * General Public License for more details. - */ - -#ifndef PCIE_SIPA_RES_H -#define PCIE_SIPA_RES_H - -#include "../include/sipa.h" - -/* - * pcie_sipa_res_create - create pcie res for sipa module. - * @prod_id: which res is the producer. - * @cons_id: which res is the consumer. - * - * Returns: - * failed, return NULL, - * succ, return a void * pointer. - */ -void *pcie_sipa_res_create(u8 dst, enum sipa_rm_res_id prod_id, - enum sipa_rm_res_id cons_id); - -/* - * pcie_sipa_res_destroy -detroy pcie res for sipa module - * @res_id: the return point of call function pcie_sipa_res_create. - */ -void pcie_sipa_res_destroy(void *res); -#endif - diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/sprd_pcie_ep_device.c b/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/sprd_pcie_ep_device.c deleted file mode 100644 index 05275c6f9..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/sprd_pcie_ep_device.c +++ /dev/null @@ -1,1663 +0,0 @@ -/** - * SPRD ep device driver in host side for Spreadtrum SoCs - * - * Copyright (C) 2018 Spreadtrum Co., Ltd. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 of - * the License as published by the Free Software Foundation. - * - * This program is used to control ep device driver in host side for - * Spreadtrum SoCs. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "../include/pcie-rc-sprd.h" -#include "../include/sprd_pcie_ep_device.h" -#include "../include/sipc_big_to_little.h" -#include "../include/sprd_pcie_resource.h" -#include "../include/sipc.h" -#include "../include/sipa.h" -#include "../sipa/sipa_core.h" - -#define DRV_MODULE_NAME "sprd-pcie-ep-device" -#define CONFIG_SPRD_IPA_PCIE_WORKROUND - -enum dev_pci_barno { - BAR_0 = 0, - BAR_1, - BAR_2, - BAR_3, - BAR_4, - BAR_5, - BAR_CNT -}; - -#define MAX_SUPPORT_IRQ 32 -#define IPA_HW_IRQ_CNT 4 -#define IPA_HW_IRQ_BASE 16 -#define IPA_HW_IRQ_BASE_DEFECT 0 - -#define REQUEST_BASE_IRQ (IPA_HW_IRQ_BASE + IPA_HW_IRQ_CNT) -#define REQUEST_BASE_IRQ_DEFECT 16 - -#ifdef CONFIG_SPRD_IPA_PCIE_WORKROUND -/* the bar0 and the bar1 are used for ipa */ -#define IPA_MEM_BAR BAR_0 -#define IPA_REG_BAR BAR_1 -#define BAR_MIN BAR_2 -#else -#define BAR_MIN BAR_0 -#endif - -/* the bar4 and the bar5 are specail bars */ -#define BAR_MAX BAR_4 - -#define PCI_VENDOR_ID_SPRD 0x16c3 -#define PCI_DEVICE_ID_SPRD_ORCA 0xabcd -#define PCI_CLASS_ID_SPRD_ORCA 0x80d00 - -/* Parameters for the waiting for iATU enabled routine */ -#define LINK_WAIT_MAX_IATU_RETRIES 5 -#define LINK_WAIT_IATU_MIN 9000 -#define LINK_WAIT_IATU_MAX 10000 - -/* ep config bar bar4 , can config ep iatu reg and door bell reg */ -#define EP_CFG_BAR BAR_4 -#define DOOR_BELL_BASE 0x00000 -#define IATU_REG_BASE 0x10000 - -#define DOOR_BELL_ENABLE 0x10 -#define DOOR_BELL_STATUS 0x14 - -/* used 0x18 & 0x1c to save the smem base & size. */ -#define DOOR_BELL_SMEMBASE 0x18 -#define DOOR_BELL_SMEMSIZE 0x1C - -/* one bit can indicate one irq , if stauts[i] & enable[i] , irq = i */ -#define DOOR_BELL_IRQ_VALUE(irq) BIT((irq)) -#define DOOR_BELL_IRQ_CNT 32 -#define IATU_MAX_REGION 8 -#define PCIE_ATU_VIEWPORT 0x900 -#define PCIE_ATU_CR1 0x904 -#define PCIE_ATU_CR2 0x908 -#define PCIE_ATU_LOWER_BASE 0x90c -#define PCIE_ATU_UPPER_BASE 0x910 -#define PCIE_ATU_LIMIT 0x914 -#define PCIE_ATU_LOWER_TARGET 0x918 -#define PCIE_ATU_UPPER_TARGET 0x91c - -#define PCIE_ATU_REGION_INBOUND BIT(31) -#define PCIE_ATU_ENABLE BIT(31) -#define PCIE_ATU_BAR_MODE_ENABLE BIT(30) -#define PCIE_ATU_TYPE_MEM 0x0 - -#define PCIE_ATU_UNR_REGION_CTRL1 0x00 -#define PCIE_ATU_UNR_REGION_CTRL2 0x04 -#define PCIE_ATU_UNR_LOWER_BASE 0x08 -#define PCIE_ATU_UNR_UPPER_BASE 0x0c -#define PCIE_ATU_UNR_LIMIT 0x10 -#define PCIE_ATU_UNR_LOWER_TARGET 0x14 -#define PCIE_ATU_UNR_UPPER_TARGET 0x18 - -/* bar4 + 0x10000 has map to ep base + 0x18000 ((0x3 << 15)) */ -#define PCIE_ATU_IB_REGION(region) (((region) << 9) | (0x1 << 8)) -#define PCIE_ATU_OB_REGION(region) ((region) << 9) - -#define PCIE_SAVE_REGION_NUM (IATU_MAX_REGION * 2) -#define PCIE_SAVE_REG_NUM 8 - -#define PCIE_LEGACY_CLEAR_BASE 0x29000000 -#define PCIE_LEGACY_CLEAR_REG 0x2c -#define PCIE_LEGACY_CLEAR_MASK BIT(0) -#define BIT_SET_OFFSET 0x1000 -#define BIT_CLR_OFFSET 0x2000 - -struct sprd_ep_dev_notify { - void (*notify)(int event, void *data); - void *data; -}; - -struct sprd_pci_ep_dev { - struct pci_dev *pdev; - void __iomem *cfg_base; /* ep config bar base in rc */ - spinlock_t irq_lock; /* irq spinlock */ - spinlock_t bar_lock; /* bar spinlock */ - spinlock_t set_irq_lock; /* set irq spinlock */ - spinlock_t set_bar_lock; /* set bar spinlock */ - unsigned long bar_res; - - u32 base_irq; - u32 ipa_base_irq; - u32 bak_irq_status; - u8 iatu_unroll_enabled; - u8 ep; - u8 irq_cnt; - bool no_msi; - bool need_backup; - void __iomem *legacy_addr; - - struct resource *bar[BAR_CNT]; - void __iomem *bar_vir[BAR_MAX]; - void __iomem *cpu_vir[BAR_MAX]; - dma_addr_t src_addr[BAR_MAX]; - dma_addr_t target_addr[BAR_MAX]; - size_t map_size[BAR_MAX]; - int event; - struct work_struct notify_work; -}; - -struct sprd_pci_ep_dev_save { - bool save_succ; - unsigned long bar_res; - void __iomem *bar_vir[BAR_MAX]; - void __iomem *cpu_vir[BAR_MAX]; - dma_addr_t src_addr[BAR_MAX]; - dma_addr_t target_addr[BAR_MAX]; - size_t map_size[BAR_MAX]; - u32 doorbell_enable; - u32 doorbell_status; - void __iomem *cfg_base; - u32 save_reg[PCIE_SAVE_REGION_NUM][PCIE_SAVE_REG_NUM]; -}; - -#define VERSION_NUMBER "V1.1.6" -#define QUECTEL_SPRD_PCIE_VERSION "Quectel_Linux&Android_SPRD_PCIE_Driver_"VERSION_NUMBER - -static void __iomem *g_irq_addr[PCIE_EP_NR]; -static struct sprd_pci_ep_dev_save g_ep_save[PCIE_EP_NR]; -static struct sprd_pci_ep_dev *g_ep_dev[PCIE_EP_NR]; -static irq_handler_t ep_dev_handler[PCIE_EP_NR][PCIE_MSI_MAX_IRQ]; -static void *ep_dev_handler_data[PCIE_EP_NR][PCIE_MSI_MAX_IRQ]; -static struct sprd_ep_dev_notify g_ep_dev_notify[PCIE_EP_NR]; - -static int sprd_ep_dev_get_bar(int ep); -static int sprd_ep_dev_put_bar(int ep, int bar); -static int sprd_ep_dev_adjust_region(struct sprd_pci_ep_dev *ep_dev, - int bar, dma_addr_t *cpu_addr_ptr, - size_t *size_ptr, dma_addr_t *offset_ptr); -static int sprd_ep_dev_just_map_bar(struct sprd_pci_ep_dev *ep_dev, int bar, - dma_addr_t cpu_addr, size_t size); -static int sprd_ep_dev_just_unmap_bar(struct sprd_pci_ep_dev *ep_dev, int bar); -static void __iomem *sprd_ep_dev_map_bar(int ep, int bar, - dma_addr_t cpu_addr, - size_t size); -static int sprd_ep_dev_unmap_bar(int ep, int bar); -static void sprd_pci_ep_dev_backup(struct sprd_pci_ep_dev *ep_dev); - -static void sprd_pcie_iommu_init(struct device *dev) -{ - struct iommu_domain *domain = NULL; - unsigned long pg_size; - dma_addr_t start, end, addr; - u32 base, size; - int ret = 0; - - domain = iommu_get_domain_for_dev(dev); - if(!domain) { - dev_info(dev, "sprd_pcie_iommu_init domian null"); - return; - } - - pg_size = 1UL << __ffs(domain->pgsize_bitmap); - smem_get_area(SIPC_ID_MINIAP, &base, &size); - start = ALIGN(base, pg_size); - end = ALIGN(base + size, pg_size); - - for (addr = start; addr < end; addr += pg_size) { - phys_addr_t phys_addr; - - phys_addr = iommu_iova_to_phys(domain, addr); - if (phys_addr) { - dev_info(dev, "sprd_pcie_iommu_init iova:%d have been used", (u32)addr); - continue; - } - ret = iommu_map(domain, addr, addr, pg_size, IOMMU_READ | IOMMU_WRITE); - if (ret) { - dev_info(dev, "sprd_pcie_iommu_init iommu_map failed"); - return; - } - } -} - - - -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 3,11,0 )) -int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec) -{ - int nvec = maxvec; - int rc; - - if (maxvec < minvec) - return -ERANGE; - - do { - rc = pci_enable_msi_block(dev, nvec); - if (rc < 0) { - return rc; - } else if (rc > 0) { - if (rc < minvec) - return -ENOSPC; - nvec = rc; - } - } while (rc); - - return nvec; -} -#endif - -int sprd_ep_dev_register_notify(int ep, - void (*notify)(int event, void *data), - void *data) -{ - struct sprd_ep_dev_notify *dev_notify; - - if (ep >= PCIE_EP_NR) - return -EINVAL; - - dev_notify = &g_ep_dev_notify[ep]; - dev_notify->notify = notify; - dev_notify->data = data; - - return 0; -} -EXPORT_SYMBOL_GPL(sprd_ep_dev_register_notify); - -int sprd_ep_dev_unregister_notify(int ep) -{ - struct sprd_ep_dev_notify *notify; - - if (ep >= PCIE_EP_NR) - return -EINVAL; - - notify = &g_ep_dev_notify[ep]; - notify->notify = NULL; - notify->data = NULL; - - return 0; -} -EXPORT_SYMBOL_GPL(sprd_ep_dev_unregister_notify); - -int sprd_ep_dev_set_irq_addr(int ep, void __iomem *irq_addr) -{ - if (ep >= PCIE_EP_NR) - return -EINVAL; - - g_irq_addr[ep] = irq_addr; - - return 0; -} -EXPORT_SYMBOL_GPL(sprd_ep_dev_set_irq_addr); - -int sprd_ep_dev_register_irq_handler(int ep, int irq, - irq_handler_t handler, void *data) -{ - struct sprd_pci_ep_dev *ep_dev; - - if (ep >= PCIE_EP_NR || irq >= PCIE_MSI_MAX_IRQ) - return -EINVAL; - - ep_dev_handler[ep][irq] = handler; - ep_dev_handler_data[ep][irq] = data; - ep_dev = g_ep_dev[ep]; - - if (handler && ep_dev && - (BIT(irq) & ep_dev->bak_irq_status)) { - ep_dev->bak_irq_status &= ~BIT(irq); - handler(irq, data); - } - - return 0; -} -EXPORT_SYMBOL_GPL(sprd_ep_dev_register_irq_handler); - -int sprd_ep_dev_unregister_irq_handler(int ep, int irq) -{ - if (ep < PCIE_EP_NR && irq < PCIE_MSI_MAX_IRQ) { - ep_dev_handler[ep][irq] = NULL; - ep_dev_handler_data[ep][irq] = NULL; - return 0; - } - - return -EINVAL; -} -EXPORT_SYMBOL_GPL(sprd_ep_dev_unregister_irq_handler); - -int sprd_ep_dev_register_irq_handler_ex(int ep, - int from_irq, - int to_irq, - irq_handler_t handler, - void *data) -{ - int i, ret; - - for (i = from_irq; i < to_irq + 1; i++) { - ret = sprd_ep_dev_register_irq_handler(ep, - i, handler, data); - if (ret) - return ret; - } - - return 0; -} - -int sprd_ep_dev_unregister_irq_handler_ex(int ep, - int from_irq, - int to_irq) -{ - int i, ret; - - for (i = from_irq; i < to_irq + 1; i++) { - ret = sprd_ep_dev_unregister_irq_handler(ep, i); - if (ret) - return ret; - } - - return 0; -} - -void __iomem *sprd_ep_map_memory(int ep, - phys_addr_t cpu_addr, - size_t size) -{ - int bar; - void __iomem *bar_addr; - - bar = sprd_ep_dev_get_bar(ep); - if (bar < 0) { - pr_err("%s: get bar err = %d\n", __func__, bar); - return NULL; - } - - bar_addr = sprd_ep_dev_map_bar(ep, bar, cpu_addr, size); - if (!bar_addr) { - pr_err("%s: map bar = %d err!\n", __func__, bar); - sprd_ep_dev_put_bar(ep, bar); - return NULL; - } - - return bar_addr; -} -EXPORT_SYMBOL_GPL(sprd_ep_map_memory); - -void sprd_ep_unmap_memory(int ep, const void __iomem *bar_addr) -{ - int bar; - struct sprd_pci_ep_dev *ep_dev; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return; - - ep_dev = g_ep_dev[ep]; - - for (bar = 0; bar < BAR_MAX; bar++) { - if (bar_addr == ep_dev->cpu_vir[bar]) { - sprd_ep_dev_unmap_bar(ep, bar); - sprd_ep_dev_put_bar(ep, bar); - break; - } - } -} -EXPORT_SYMBOL_GPL(sprd_ep_unmap_memory); - -#ifdef CONFIG_SPRD_SIPA -phys_addr_t sprd_ep_ipa_map(int type, phys_addr_t target_addr, size_t size) -{ - int bar, ep = PCIE_EP_MODEM; - dma_addr_t offset; - struct sprd_pci_ep_dev *ep_dev; - struct pci_dev *pdev; - struct device *dev; - struct resource *res; - - ep_dev = g_ep_dev[ep]; - if (!ep_dev) - return 0; - - ep_dev = g_ep_dev[ep]; - pdev = ep_dev->pdev; - dev = &pdev->dev; -#ifdef CONFIG_SPRD_IPA_PCIE_WORKROUND - bar = type == PCIE_IPA_TYPE_MEM ? IPA_MEM_BAR : IPA_REG_BAR; -#else - bar = sprd_ep_dev_get_bar(ep); - if (bar < 0) { - dev_err(dev, "ep: ipa map, get bar err = %d\n", bar); - return 0; - } -#endif - res = &pdev->resource[bar]; - - dev_info(dev, "ep: ipa map type=%d, addr=0x%lx, size=0x%lx\n", - type, - (unsigned long)target_addr, - (unsigned long)size); - - /* 1st, adjust the map region */ - if (sprd_ep_dev_adjust_region(ep_dev, bar, &target_addr, - &size, &offset)) - return 0; - - /* than, map bar */ - if (sprd_ep_dev_just_map_bar(ep_dev, bar, target_addr, size)) - return 0; - - /* save for unmap */ - ep_dev->src_addr[bar] = res->start + offset; - ep_dev->target_addr[bar] = target_addr; - ep_dev->map_size[bar] = size; - - /* return the cpu phy address */ - return res->start + offset; -} - -int sprd_ep_ipa_unmap(int type, const phys_addr_t cpu_addr) -{ - int bar, ep = PCIE_EP_MODEM; - bool find_bar = false; - struct sprd_pci_ep_dev *ep_dev; - struct pci_dev *pdev; - struct resource *res; - - ep_dev = g_ep_dev[ep]; - if (!ep_dev) - return -EINVAL; - - pdev = ep_dev->pdev; - res = &pdev->resource[bar]; - - dev_info(&pdev->dev, "ep: ipa unmap cpu_addr=0x%lx\n", - (unsigned long)cpu_addr); - -#ifdef CONFIG_SPRD_IPA_PCIE_WORKROUND - bar = type == PCIE_IPA_TYPE_MEM ? IPA_MEM_BAR : IPA_REG_BAR; - if (ep_dev->src_addr[bar] == cpu_addr) - find_bar = true; -#else - for (bar = 0; bar < BAR_MAX; bar++) { - if (cpu_addr == ep_dev->src_addr[bar]) { - find_bar = true; - break; - } - } -#endif - - if (!find_bar) { - dev_err(&pdev->dev, "ep: ipa unmap can't find bar!"); - return -EINVAL; - } - - ep_dev->target_addr[bar] = 0; - ep_dev->target_addr[bar] = 0; - ep_dev->map_size[bar] = 0; - return sprd_ep_dev_just_unmap_bar(ep_dev, bar); -} -#endif - -int sprd_ep_dev_raise_irq(int ep, int irq) -{ - struct pci_dev *pdev; - struct device *dev; - struct sprd_pci_ep_dev *ep_dev; - void __iomem *base; - u32 value; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return -ENODEV; - - ep_dev = g_ep_dev[ep]; - pdev = ep_dev->pdev; - dev = &pdev->dev; - - dev_dbg(dev, "ep: raise, ep=%d, irq=%d\n", ep, irq); - - if (irq >= DOOR_BELL_IRQ_CNT) { - dev_err(&pdev->dev, "raise err, irq=%d\n", irq); - return -EINVAL; - } - - spin_lock(&ep_dev->set_irq_lock); - base = ep_dev->cfg_base + DOOR_BELL_BASE; - value = readl_relaxed(base + DOOR_BELL_STATUS); - writel_relaxed(value | DOOR_BELL_IRQ_VALUE(irq), - base + DOOR_BELL_STATUS); - spin_unlock(&ep_dev->set_irq_lock); - - return 0; -} -EXPORT_SYMBOL_GPL(sprd_ep_dev_raise_irq); - -int sprd_ep_dev_clear_doolbell_irq(int ep, int irq) -{ - struct pci_dev *pdev; - struct device *dev; - struct sprd_pci_ep_dev *ep_dev; - void __iomem *base; - u32 value; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return -ENODEV; - - ep_dev = g_ep_dev[ep]; - pdev = ep_dev->pdev; - dev = &pdev->dev; - - dev_dbg(dev, "ep: clear doorbell, ep=%d, irq=%d\n", ep, irq); - - if (irq >= DOOR_BELL_IRQ_CNT) - return -EINVAL; - - spin_lock(&ep_dev->set_irq_lock); - base = ep_dev->cfg_base + DOOR_BELL_BASE; - value = readl_relaxed(base + DOOR_BELL_STATUS); - if (value & DOOR_BELL_IRQ_VALUE(irq)) - writel_relaxed(value & (~DOOR_BELL_IRQ_VALUE(irq)), - base + DOOR_BELL_STATUS); - spin_unlock(&ep_dev->set_irq_lock); - - return 0; -} - -int sprd_ep_dev_set_backup(int ep) -{ - struct sprd_pci_ep_dev *ep_dev; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return -ENODEV; - - ep_dev = g_ep_dev[ep]; - ep_dev->need_backup = true; - - /* backup once immediately. */ - sprd_pci_ep_dev_backup(ep_dev); - - return 0; -} - -int sprd_ep_dev_clear_backup(int ep) -{ - struct sprd_pci_ep_dev *ep_dev; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return -ENODEV; - - ep_dev = g_ep_dev[ep]; - ep_dev->need_backup = false; - - return 0; -} - -int sprd_ep_dev_pass_smem(int ep, u32 base, u32 size) -{ - struct sprd_pci_ep_dev *ep_dev; - void __iomem *reg_base; - struct pci_dev *pdev; - struct device *dev; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return -ENODEV; - - ep_dev = g_ep_dev[ep]; - pdev = ep_dev->pdev; - dev = &pdev->dev; - dev_info(&pdev->dev, - "pass_smem, base=0x%x,size=0x%x\n", - base, size); - - reg_base = ep_dev->cfg_base + DOOR_BELL_BASE; - - writel_relaxed(base, reg_base + DOOR_BELL_SMEMBASE); - writel_relaxed(size, reg_base + DOOR_BELL_SMEMSIZE); - - return 0; -} - -static inline u32 sprd_pci_ep_iatu_readl(struct sprd_pci_ep_dev *ep_dev, - u32 offset) -{ - return readl_relaxed(ep_dev->cfg_base + IATU_REG_BASE + offset); -} - -static inline void sprd_pci_ep_iatu_writel(struct sprd_pci_ep_dev *ep_dev, - u32 offset, u32 value) -{ - writel_relaxed(value, ep_dev->cfg_base + IATU_REG_BASE + offset); -} - -static int sprd_ep_dev_get_bar(int ep) -{ - int bar; - int ret = -EBUSY; - struct sprd_pci_ep_dev *ep_dev; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return -ENODEV; - - ep_dev = g_ep_dev[ep]; - spin_lock(&ep_dev->bar_lock); - for (bar = BAR_MIN; bar < BAR_MAX; bar++) { - if (ep_dev->bar[bar] && !test_bit(bar, &ep_dev->bar_res)) { - set_bit(bar, &ep_dev->bar_res); - ret = bar; - break; - } - } - spin_unlock(&ep_dev->bar_lock); - - return ret; -} - -static int sprd_ep_dev_put_bar(int ep, int bar) -{ - int ret = -ENODEV; - struct sprd_pci_ep_dev *ep_dev; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return -ENODEV; - - ep_dev = g_ep_dev[ep]; - spin_lock(&ep_dev->bar_lock); - if (test_and_clear_bit(bar, &ep_dev->bar_res)) - ret = bar; - spin_unlock(&ep_dev->bar_lock); - - return ret; -} - -static int sprd_ep_dev_unr_set_bar(struct sprd_pci_ep_dev *ep_dev, - int bar, - dma_addr_t cpu_addr, size_t size) -{ - u32 retries, val; - struct pci_dev *pdev = ep_dev->pdev; - - spin_lock(&ep_dev->set_bar_lock); - - /* bar n use region n to map, map to bar match mode */ - sprd_pci_ep_iatu_writel(ep_dev, - PCIE_ATU_IB_REGION(bar) + - PCIE_ATU_UNR_LOWER_TARGET, - lower_32_bits(cpu_addr)); - sprd_pci_ep_iatu_writel(ep_dev, - PCIE_ATU_IB_REGION(bar) + - PCIE_ATU_UNR_UPPER_TARGET, - upper_32_bits(cpu_addr)); - - sprd_pci_ep_iatu_writel(ep_dev, - PCIE_ATU_IB_REGION(bar) + - PCIE_ATU_UNR_REGION_CTRL1, - PCIE_ATU_TYPE_MEM); - sprd_pci_ep_iatu_writel(ep_dev, - PCIE_ATU_IB_REGION(bar) + - PCIE_ATU_UNR_REGION_CTRL2, - PCIE_ATU_ENABLE | - PCIE_ATU_BAR_MODE_ENABLE | (bar << 8)); - - spin_unlock(&ep_dev->set_bar_lock); - - /* - * Make sure ATU enable takes effect before any subsequent config - * and I/O accesses. - */ - for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) { - val = sprd_pci_ep_iatu_readl(ep_dev, - PCIE_ATU_IB_REGION(bar) + - PCIE_ATU_UNR_REGION_CTRL2); - if (val & PCIE_ATU_ENABLE) - return 0; - - dev_dbg(&pdev->dev, - "ep: unr set bar[%d], var = 0x%x\n", - bar, - val); - /* wait a moment for polling ep atu enable bit */ - usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX); - } - - return -EINVAL; -} - -static int sprd_ep_dev_unr_clear_bar(struct sprd_pci_ep_dev *ep_dev, int bar) -{ - struct pci_dev *pdev = ep_dev->pdev; - - dev_dbg(&pdev->dev, "ep: unr clear map bar=%d\n", bar); - - spin_lock(&ep_dev->set_bar_lock); - - sprd_pci_ep_iatu_writel(ep_dev, - PCIE_ATU_IB_REGION(bar) + - PCIE_ATU_UNR_REGION_CTRL2, - (u32)(~PCIE_ATU_ENABLE)); - spin_unlock(&ep_dev->set_bar_lock); - - return 0; -} - -static int sprd_ep_dev_adjust_region(struct sprd_pci_ep_dev *ep_dev, int bar, - dma_addr_t *cpu_addr_ptr, - size_t *size_ptr, - dma_addr_t *offset_ptr) -{ - dma_addr_t cpu_addr, base, offset; - resource_size_t bar_size, size; - struct pci_dev *pdev = ep_dev->pdev; - struct resource *res = &pdev->resource[bar]; - - size = (resource_size_t)*size_ptr; - cpu_addr = *cpu_addr_ptr; - bar_size = resource_size(res); - - /* size must align with page */ - size = PAGE_ALIGN(size); - - /* base must be divisible by bar size for bar match mode */ - base = cpu_addr / bar_size * bar_size; - offset = cpu_addr - base; - size += PAGE_ALIGN(offset); - - /* size must < bar size */ - if (size > bar_size) { - dev_err(&pdev->dev, - "bar[%d]:size=0x%lx > 0x%lx\n", - bar, - (unsigned long)size, - (unsigned long)bar_size); - return -EINVAL; - } - - dev_dbg(&pdev->dev, - "bar[%d]: base=0x%lx,size=0x%lx,offset=0x%lx\n", - bar, (unsigned long)base, - (unsigned long)size, - (unsigned long)offset); - - *size_ptr = (size_t)size; - *offset_ptr = offset; - *cpu_addr_ptr = base; - - return 0; -} - -static int sprd_ep_dev_just_map_bar(struct sprd_pci_ep_dev *ep_dev, int bar, - dma_addr_t cpu_addr, size_t size) -{ - u32 retries, val; - struct pci_dev *pdev; - struct device *dev; - - pdev = ep_dev->pdev; - dev = &pdev->dev; - - dev_dbg(dev, "ep: map bar=%d, addr=0x%lx, size=0x%lx\n", - bar, - (unsigned long)cpu_addr, - (unsigned long)size); - - if (ep_dev->iatu_unroll_enabled) - return sprd_ep_dev_unr_set_bar(ep_dev, bar, cpu_addr, size); - - spin_lock(&ep_dev->set_bar_lock); - - /* bar n use region n to map, map to bar match mode */ - sprd_pci_ep_iatu_writel(ep_dev, - PCIE_ATU_VIEWPORT, - PCIE_ATU_REGION_INBOUND | bar); - sprd_pci_ep_iatu_writel(ep_dev, PCIE_ATU_LOWER_TARGET, - lower_32_bits(cpu_addr)); - sprd_pci_ep_iatu_writel(ep_dev, PCIE_ATU_UPPER_TARGET, - upper_32_bits(cpu_addr)); - sprd_pci_ep_iatu_writel(ep_dev, - PCIE_ATU_CR1, - PCIE_ATU_TYPE_MEM); - sprd_pci_ep_iatu_writel(ep_dev, - PCIE_ATU_CR2, - PCIE_ATU_ENABLE | - PCIE_ATU_BAR_MODE_ENABLE | (bar << 8)); - - spin_unlock(&ep_dev->set_bar_lock); - - /* - * Make sure ATU enable takes effect - * before any subsequent config and I/O accesses. - */ - for (retries = 0; - retries < LINK_WAIT_MAX_IATU_RETRIES; - retries++) { - val = sprd_pci_ep_iatu_readl(ep_dev, PCIE_ATU_CR2); - if (val & PCIE_ATU_ENABLE) - return 0; - - /* wait a moment for polling ep atu enable bit */ - usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX); - } - - return -EINVAL; -} - -static int sprd_ep_dev_just_unmap_bar(struct sprd_pci_ep_dev *ep_dev, int bar) -{ - struct pci_dev *pdev; - struct device *dev; - - pdev = ep_dev->pdev; - dev = &pdev->dev; - - dev_dbg(dev, "ep: unmap bar = %d\n", bar); - - if (ep_dev->iatu_unroll_enabled) - return sprd_ep_dev_unr_clear_bar(ep_dev, bar); - - spin_lock(&ep_dev->set_bar_lock); - - sprd_pci_ep_iatu_writel(ep_dev, PCIE_ATU_VIEWPORT, - PCIE_ATU_REGION_INBOUND | bar); - sprd_pci_ep_iatu_writel(ep_dev, PCIE_ATU_CR2, - (u32)(~PCIE_ATU_ENABLE)); - - spin_unlock(&ep_dev->set_bar_lock); - - return 0; -} - -static void __iomem *sprd_ep_dev_map_bar(int ep, int bar, - dma_addr_t cpu_addr, size_t size) -{ - resource_size_t offset; - struct pci_dev *pdev; - struct device *dev; - struct sprd_pci_ep_dev *ep_dev; - void __iomem *bar_vir; - struct resource *res; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return NULL; - - ep_dev = g_ep_dev[ep]; - pdev = ep_dev->pdev; - dev = &pdev->dev; - - /* bar is be used */ - if (ep_dev->bar_vir[bar]) { - dev_err(dev, "ep: bar[%d] is used!", bar); - return NULL; - } - - /* 1st, adjust the map region */ - if (sprd_ep_dev_adjust_region(ep_dev, bar, &cpu_addr, &size, &offset)) - return NULL; - - /* than, ioremap, if map failed, no need to set bar */ - res = &pdev->resource[bar]; -#ifndef ioremap_nocache -#define ioremap_nocache ioremap -#endif - bar_vir = ioremap_nocache(res->start, size); - if (!bar_vir) { - dev_err(dev, "ep: map error, bar=%d, addr=0x%lx, size=0x%lx\n", - bar, - (unsigned long)cpu_addr, - (unsigned long)size); - return NULL; - } - - if (sprd_ep_dev_just_map_bar(ep_dev, bar, cpu_addr, size)) { - dev_err(dev, "ep: map bar =%d\n", bar); - iounmap(ep_dev->bar_vir[bar]); - return NULL; - } - - ep_dev->bar_vir[bar] = (void __iomem *)bar_vir; - ep_dev->cpu_vir[bar] = (void __iomem *)(bar_vir + offset); - ep_dev->src_addr[bar] = res->start + offset; - ep_dev->target_addr[bar] = cpu_addr; - ep_dev->map_size[bar] = size; - - return ep_dev->cpu_vir[bar]; -} - -static int sprd_ep_dev_unmap_bar(int ep, int bar) -{ - struct pci_dev *pdev; - struct device *dev; - struct sprd_pci_ep_dev *ep_dev; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return -ENODEV; - - ep_dev = g_ep_dev[ep]; - pdev = ep_dev->pdev; - dev = &pdev->dev; - - dev_info(dev, "ep: unmap bar = %d\n", bar); - - if (!ep_dev->bar_vir[bar]) - return -ENODEV; - - sprd_ep_dev_just_unmap_bar(ep_dev, bar); - - iounmap(ep_dev->bar_vir[bar]); - ep_dev->bar_vir[bar] = NULL; - ep_dev->cpu_vir[bar] = NULL; - ep_dev->src_addr[bar] = 0; - ep_dev->target_addr[bar] = 0; - ep_dev->map_size[bar] = 0; - - return 0; -} - -static void sprd_pci_ep_dev_clear_legacy_irq(struct sprd_pci_ep_dev *ep_dev) -{ - if (!ep_dev->legacy_addr) - return; - - writel_relaxed(PCIE_LEGACY_CLEAR_MASK, - ep_dev->legacy_addr + BIT_CLR_OFFSET + PCIE_LEGACY_CLEAR_REG); -} - -static irqreturn_t sprd_pci_ep_dev_irqhandler(int irq, void *dev_ptr) -{ - struct sprd_pci_ep_dev *ep_dev = dev_ptr; - struct pci_dev *pdev = ep_dev->pdev; - struct device *dev = &pdev->dev; - irq_handler_t handler; - u32 i, j, value; - int ipa_irq; - - if (ep_dev->no_msi) { - /* clear irq */ - sprd_pci_ep_dev_clear_legacy_irq(ep_dev); - - /* workaroud for IPA */ - handler = ep_dev_handler[ep_dev->ep][PCIE_MSI_IPA]; - if (handler) - handler(irq, ep_dev_handler_data[ep_dev->ep][PCIE_MSI_IPA]); - - - value = BL_READL(g_irq_addr[ep_dev->ep]); - dev_dbg(dev, "ep: irq handler. irq = 0x%x, base=%d\n", value, ep_dev->base_irq); - for (i = 0; i < 32; i++) { - if (value & BIT(i)) { - /* clear iqr bit*/ - value = BL_READL(g_irq_addr[ep_dev->ep]); - value &= ~(BIT(i)); - BL_WRITEL(value,g_irq_addr[ep_dev->ep]); - j = i - ep_dev->base_irq; - if (j >= PCIE_MSI_MAX_IRQ) - continue; - - handler = ep_dev_handler[ep_dev->ep][j]; - if (handler) - handler(irq, ep_dev_handler_data[ep_dev->ep][j]); - else - ep_dev->bak_irq_status |= BIT(j); - } - } - return IRQ_HANDLED; - } - - dev_dbg(dev, "ep: irq handler. irq = %d\n", irq); - /* for ipa hw irq. */ - ipa_irq = irq - (pdev->irq + ep_dev->ipa_base_irq); - if (ipa_irq >= 0 && ipa_irq < IPA_HW_IRQ_CNT) { - handler = ep_dev_handler[ep_dev->ep][PCIE_MSI_IPA]; - if (handler) - handler(ipa_irq, ep_dev_handler_data[ep_dev->ep][PCIE_MSI_IPA]); - else - ep_dev->bak_irq_status |= BIT(PCIE_MSI_IPA); - - return IRQ_HANDLED; - } - - - irq -= (pdev->irq + ep_dev->base_irq); - if (irq >= PCIE_MSI_MAX_IRQ || irq < 0) { - dev_err(dev, "ep: error, irq = %d", irq); - return IRQ_HANDLED; - } - - handler = ep_dev_handler[ep_dev->ep][irq]; - if (handler) - handler(irq, ep_dev_handler_data[ep_dev->ep][irq]); - else - ep_dev->bak_irq_status |= BIT(irq); - - return IRQ_HANDLED; -} - -static void sprd_pci_ep_save_reg(struct sprd_pci_ep_dev *ep_dev) -{ - int i, j; - u32 (*save_reg)[PCIE_SAVE_REG_NUM]; - static struct sprd_pci_ep_dev_save *ep_save; - - ep_save = &g_ep_save[ep_dev->ep]; - save_reg = ep_save->save_reg; - - for (i = 0; i < PCIE_SAVE_REGION_NUM; i += 2) { - for (j = 0; j < PCIE_SAVE_REG_NUM; j++) { - save_reg[i][j] = - sprd_pci_ep_iatu_readl(ep_dev, - PCIE_ATU_OB_REGION(i) + - j * sizeof(u32)); - save_reg[i + 1][j] = - sprd_pci_ep_iatu_readl(ep_dev, - PCIE_ATU_IB_REGION(i) + - j * sizeof(u32)); - } - } - - ep_save->doorbell_enable = sprd_pci_ep_iatu_readl(ep_dev, - DOOR_BELL_BASE + - DOOR_BELL_ENABLE); - ep_save->doorbell_status = sprd_pci_ep_iatu_readl(ep_dev, - DOOR_BELL_BASE + - DOOR_BELL_STATUS); - ep_save->cfg_base = ep_dev->cfg_base; - - ep_save->save_succ = true; -} - -static void sprd_pci_ep_dev_backup(struct sprd_pci_ep_dev *ep_dev) -{ - struct pci_dev *pdev = ep_dev->pdev; - struct device *dev = &pdev->dev; - struct sprd_pci_ep_dev_save *ep_save; - int i; - - ep_save = &g_ep_save[ep_dev->ep]; - - /* save some member */ - ep_save->bar_res = ep_dev->bar_res; - for (i = 0; i < BAR_MAX; i++) { - if (!ep_dev->src_addr[i]) - continue; - - dev_info(dev, "ep: backup bar=%d, addr=0x%lx, size=0x%lx\n", - i, - (unsigned long)ep_save->target_addr[i], - (unsigned long)ep_save->map_size[i]); - - ep_save->bar_vir[i] = ep_dev->bar_vir[i]; - ep_save->cpu_vir[i] = ep_dev->cpu_vir[i]; - ep_save->src_addr[i] = ep_dev->src_addr[i]; - ep_save->target_addr[i] = ep_dev->target_addr[i]; - ep_save->map_size[i] = ep_dev->map_size[i]; - } - - /* save ep reg */ - sprd_pci_ep_save_reg(ep_dev); -} - -static void sprd_pci_ep_dev_restore(struct sprd_pci_ep_dev *ep_dev) -{ - struct pci_dev *pdev = ep_dev->pdev; - struct device *dev = &pdev->dev; - struct sprd_pci_ep_dev_save *ep_save; - int i; - - ep_save = &g_ep_save[ep_dev->ep]; - - /* save some member */ - ep_dev->bar_res = ep_save->bar_res; - for (i = 0; i < BAR_MAX; i++) { - if (!ep_save->src_addr[i]) - continue; - - ep_dev->bar_vir[i] = ep_save->bar_vir[i]; - ep_dev->cpu_vir[i] = ep_save->cpu_vir[i]; - ep_dev->src_addr[i] = ep_save->src_addr[i]; - ep_dev->target_addr[i] = ep_save->target_addr[i]; - ep_dev->map_size[i] = ep_save->map_size[i]; - - dev_info(dev, "ep: restore bar=%d, addr=0x%lx, size=0x%lx\n", - i, - (unsigned long)ep_dev->target_addr[i], - (unsigned long)ep_dev->map_size[i]); - - if (sprd_ep_dev_just_map_bar(ep_dev, - i, - ep_dev->target_addr[i], - ep_dev->map_size[i])) - dev_err(dev, "ep: restore map err i = %d.\n", i); - } -} - -static void sprd_pci_ep_notify_fn(struct work_struct *work) -{ - struct sprd_ep_dev_notify *notify; - struct sprd_pci_ep_dev *ep_dev = container_of(work, - struct sprd_pci_ep_dev, - notify_work); - - notify = &g_ep_dev_notify[ep_dev->ep]; - if (notify->notify) - notify->notify(ep_dev->event, notify->data); -} - -static int sprd_pci_ep_dev_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - int i, err, irq_cnt = 0; - u32 val; - enum dev_pci_barno bar; - struct device *dev = &pdev->dev; - struct sprd_pci_ep_dev *ep_dev; - struct resource *res; - - dev_info(dev, "ep: probe\n"); - - sprd_pcie_iommu_init(dev); - - ep_dev = devm_kzalloc(dev, sizeof(*ep_dev), GFP_KERNEL); - if (!ep_dev) - return -ENOMEM; - - ep_dev->pdev = pdev; - - if (ent->device == PCI_DEVICE_ID_SPRD_ORCA) - ep_dev->ep = PCIE_EP_MODEM; - else { - dev_err(dev, "ep: Cannot support ep device = 0x%x\n", - ent->device); - return -EINVAL; - } - - err = pci_enable_device(pdev); - if (err) { - dev_err(dev, "ep: Cannot enable PCI device\n"); - return err; - } - - err = pci_request_regions(pdev, DRV_MODULE_NAME); - if (err) { - dev_err(dev, "ep: Cannot obtain PCI resources\n"); - goto err_disable_pdev; - } - - pci_set_master(pdev); - -#ifdef PCI_IRQ_MSI - irq_cnt = pci_alloc_irq_vectors(pdev, - 1, - MAX_SUPPORT_IRQ, - PCI_IRQ_MSI); -#else - irq_cnt = pci_enable_msi_range(pdev, 1, MAX_SUPPORT_IRQ); -#endif - - if (sprd_pcie_is_defective_chip()) { - ep_dev->base_irq = REQUEST_BASE_IRQ_DEFECT; - ep_dev->ipa_base_irq = IPA_HW_IRQ_BASE_DEFECT; - } else { - ep_dev->base_irq = REQUEST_BASE_IRQ; - ep_dev->ipa_base_irq = IPA_HW_IRQ_BASE; - } - - for (bar = BAR_0; bar <= BAR_5; bar++) { - res = &pdev->resource[bar]; - dev_info(dev, "ep: BAR[%d] %pR\n", bar, res); - /* only save mem bar */ - if (resource_type(res) == IORESOURCE_MEM) - ep_dev->bar[bar] = res; - } - - ep_dev->cfg_base = pci_ioremap_bar(pdev, EP_CFG_BAR); - if (!ep_dev->cfg_base) { - dev_err(dev, "ep: failed to map cfg bar.\n"); - err = -ENOMEM; - goto err_disable_msi; - } - - /* clear all 32 bit door bell */ - writel_relaxed(0x0, - ep_dev->cfg_base + DOOR_BELL_BASE + DOOR_BELL_STATUS); - - pci_set_drvdata(pdev, ep_dev); - pci_read_config_dword(ep_dev->pdev, PCIE_ATU_VIEWPORT, &val); - /* - * this atu view port reg is 0xffffffff means that the ep device - * doesn't support atu view port, we need unroll iatu registers - */ - dev_info(dev, "ep: atu_view_port val = 0x%x", val); - ep_dev->iatu_unroll_enabled = val == 0xffffffff; - - /* default , PCIE_EP_PROBE */ - ep_dev->event = PCIE_EP_PROBE; - g_ep_dev[ep_dev->ep] = ep_dev; - - if (!ep_dev->bar[BAR_1] || !ep_dev->bar[BAR_3]) { - /* only 2 bar, set PCIE_EP_PROBE_BEFORE_SPLIT_BAR */ - ep_dev->event = PCIE_EP_PROBE_BEFORE_SPLIT_BAR; - dev_info(dev, "ep:bar not ready, wait the next probe!"); - } - - /* restore all the config */ - if (ep_dev->event == PCIE_EP_PROBE) - sprd_pci_ep_dev_restore(ep_dev); - - /* start notify work */ - INIT_WORK(&ep_dev->notify_work, sprd_pci_ep_notify_fn); - schedule_work(&ep_dev->notify_work); - - if (irq_cnt < MAX_SUPPORT_IRQ) { - err = irq_cnt < 0 ? irq_cnt : -EINVAL; - ep_dev->no_msi = true; - dev_info(dev, "ep: failed to get MSI, err=%d, irq=%d\n", err, pdev->irq); - - ep_dev->legacy_addr = sprd_ep_map_memory(ep_dev->ep, PCIE_LEGACY_CLEAR_BASE, 0x4000); - /* request legacy irq */ - err = devm_request_irq(dev, pdev->irq, sprd_pci_ep_dev_irqhandler, - IRQF_SHARED, DRV_MODULE_NAME, ep_dev); - if (err) - dev_warn(dev, - "ep: failed to request legacy %d\n", - pdev->irq); - - } else { - ep_dev->irq_cnt = irq_cnt; - dev_info(dev, "ep: request IRQ = %d, cnt =%d\n", - pdev->irq, - ep_dev->irq_cnt); - - /* request msi irq */ - for (i = ep_dev->base_irq; - i < ep_dev->base_irq + PCIE_MSI_MAX_IRQ; - i++) { - err = devm_request_irq(dev, pdev->irq + i, - sprd_pci_ep_dev_irqhandler, - IRQF_SHARED, DRV_MODULE_NAME, ep_dev); - if (err) - dev_warn(dev, - "ep: failed to request IRQ %d for MSI %d\n", - pdev->irq + i, i + 1); - } - - #ifdef CONFIG_SPRD_IPA_PCIE_WORKROUND - for (i = ep_dev->ipa_base_irq; - i < ep_dev->ipa_base_irq + IPA_HW_IRQ_CNT; - i++) { - err = devm_request_irq(dev, pdev->irq + i, - sprd_pci_ep_dev_irqhandler, - IRQF_SHARED, DRV_MODULE_NAME, - ep_dev); - if (!err) - sprd_pcie_teardown_msi_irq(pdev->irq + i); - } - #endif - } - -#ifndef SPRD_PCIE_USE_DTS - sipa_module_init(dev); - sipa_eth_init(); - sipa_dummy_init(); -#endif - - return 0; - -err_disable_msi: - pci_disable_msi(pdev); - pci_release_regions(pdev); - -err_disable_pdev: - pci_disable_device(pdev); - - return err; -} - -static void sprd_pci_ep_dev_remove(struct pci_dev *pdev) -{ - u32 i; - struct sprd_ep_dev_notify *notify; - struct sprd_pci_ep_dev *ep_dev = pci_get_drvdata(pdev); - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - dev_info(&pdev->dev, "ep: remove\n"); - ctrl->remote_ready = false; - spipe_device_down(); - spool_device_down(); - - cancel_work_sync(&ep_dev->notify_work); - - /* first notify PCIE_EP_REMOVE */ - notify = &g_ep_dev_notify[ep_dev->ep]; - if (notify->notify) - notify->notify(PCIE_EP_REMOVE, notify->data); - - /* back up some config before remove */ - if (ep_dev->need_backup) - sprd_pci_ep_dev_backup(ep_dev); - - if (ep_dev->no_msi) { - devm_free_irq(&pdev->dev, pdev->irq, ep_dev); - } else { - for (i = ep_dev->base_irq; i < ep_dev->base_irq + PCIE_MSI_MAX_IRQ; i++) - devm_free_irq(&pdev->dev, pdev->irq + i, ep_dev); - - #ifdef CONFIG_SPRD_IPA_PCIE_WORKROUND - for (i = ep_dev->ipa_base_irq; - i < ep_dev->ipa_base_irq + IPA_HW_IRQ_CNT; - i++) - devm_free_irq(&pdev->dev, pdev->irq + i, ep_dev); - #endif - } - - pci_disable_msi(pdev); - -#ifndef SPRD_PCIE_USE_DTS - sipa_dummy_exit(); - sipa_eth_exit(); - sipa_module_exit(); -#endif - - if (ep_dev->legacy_addr) { - sprd_ep_unmap_memory(ep_dev->ep, ep_dev->legacy_addr); - ep_dev->legacy_addr = NULL; - dev_info(&ep_dev->pdev->dev, "set ep_dev->legacy_addr = %lx\n", (long)ep_dev->legacy_addr); - } - - if (ep_dev->cfg_base) { - iounmap(ep_dev->cfg_base); - ep_dev->cfg_base = NULL; - } - - pci_release_regions(pdev); - pci_disable_device(pdev); - - g_ep_dev[ep_dev->ep] = NULL; - ep_dev->bar_res = 0; -} - -static const struct pci_device_id sprd_pci_ep_dev_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_SPRD, PCI_DEVICE_ID_SPRD_ORCA) }, - { } -}; -MODULE_DEVICE_TABLE(pci, sprd_pci_ep_dev_tbl); - -#ifdef CONFIG_PM_SLEEP -static int sprd_pci_ep_suspend(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - int rc; - - dev_info(dev, "suspend\n"); - - /* Exec pci PCI_D3cold one time */ - if (pdev->current_state != PCI_D0) { - dev_info(dev, "done for pm %d\n", pdev->current_state); - return 0; - } - - /* - * TODO: The HAL will ask the shared memory layer whether D3 is allowed. - */ - - /* Save the PCI configuration space of a device before suspending. */ - rc = pci_save_state(pdev); - if (rc) { - dev_err(dev, "pci_save_state error=%d\n", rc); - return rc; - } - - /* Set the power state of a PCI device. - * Transition a device to a new power state, using the device's PCI PM - * registers. - */ - rc = pci_set_power_state(pdev, PCI_D3cold); - if (rc) { - dev_err(dev, "pci_set_power_state error=%d\n", rc); - return rc; - } - return 0; -} - -static int sprd_pci_ep_resume(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - int rc; - - dev_info(dev, "resume\n"); - - /* Set the power state of a PCI device. */ - rc = pci_set_power_state(pdev, PCI_D0); - if (rc) { - dev_err(dev, "pci_set_power_state error=%d\n", rc); - return rc; - } - - /* Restore the saved state of a PCI device. */ - pci_restore_state(pdev); - - /* TODO: The HAL shall inform that the device is active. */ - return 0; -} -#endif /* CONFIG_PM_SLEEP */ - -static const struct dev_pm_ops sprd_pci_ep_pm = { - SET_SYSTEM_SLEEP_PM_OPS(sprd_pci_ep_suspend, - sprd_pci_ep_resume) -}; - -static struct pci_driver sprd_pci_ep_dev_driver = { - .name = DRV_MODULE_NAME, - .id_table = sprd_pci_ep_dev_tbl, - .probe = sprd_pci_ep_dev_probe, - .remove = sprd_pci_ep_dev_remove, - .driver = { - .pm = &sprd_pci_ep_pm, - } -}; -//module_pci_driver(sprd_pci_ep_dev_driver); - -#if defined(CONFIG_DEBUG_FS) -static void sprd_pci_ep_dev_save_show(struct seq_file *m, - struct sprd_pci_ep_dev_save *ep_save, - int ep) -{ - u32 i; - - seq_printf(m, "ep-save-%d configs:\n", ep); - seq_printf(m, "bar_res = 0x%lx\n", ep_save->bar_res); - - for (i = 0; i < BAR_MAX; i++) { - seq_printf(m, "src_addr[%d] = 0x%lx\n", - i, - (unsigned long)ep_save->src_addr[i]); - seq_printf(m, "target_addr[%d] = 0x%lx\n", - i, - (unsigned long)ep_save->target_addr[i]); - seq_printf(m, "map_size[%d] = 0x%lx\n", - i, - (unsigned long)ep_save->map_size[i]); - } -} - -static void sprd_pci_ep_dev_config_show(struct seq_file *m, - struct sprd_pci_ep_dev *ep_dev) -{ - u32 i; - void __iomem *base; - - seq_printf(m, "ep-%d configs:\n", ep_dev->ep); - - /* doorbell regs */ - seq_puts(m, "door bell regs:\n"); - base = ep_dev->cfg_base + DOOR_BELL_BASE; - - seq_printf(m, "irq_enable = 0x%08x\n irq_status = 0x%08x\n", - readl_relaxed(base + DOOR_BELL_ENABLE), - readl_relaxed(base + DOOR_BELL_STATUS)); - - /* iatu reg regs */ - seq_puts(m, "iatu regs reg:\n"); - for (i = 0; i < IATU_MAX_REGION * 2; i++) { - base = ep_dev->cfg_base + IATU_REG_BASE + i * 100; - seq_printf(m, "IATU[%d]:\n", i); - seq_printf(m, "0x%p: 0x%08x 0x%08x 0x%08x 0x%08x\n", - base, - readl_relaxed(base + 0x0), - readl_relaxed(base + 0x4), - readl_relaxed(base + 0x8), - readl_relaxed(base + 0xc)); - base += 0x10; - seq_printf(m, "0x%p: 0x%08x 0x%08x 0x%08x 0x%08x\n", - base, - readl_relaxed(base + 0x0), - readl_relaxed(base + 0x4), - readl_relaxed(base + 0x8), - readl_relaxed(base + 0x10)); - } -} - -static void sprd_pci_ep_dev_backup_show(struct seq_file *m, - struct sprd_pci_ep_dev_save *ep_save, - int ep) -{ - int i; - u32 (*save_reg)[PCIE_SAVE_REG_NUM]; - void __iomem *base; - - save_reg = ep_save->save_reg; - - seq_printf(m, "ep-%d backup configs:\n", ep); - - /* doorbell regs */ - seq_puts(m, "door bell regs:\n"); - seq_printf(m, "irq_enable = 0x%08x\n irq_status = 0x%08x\n", - ep_save->doorbell_enable, - ep_save->doorbell_status); - - /* iatu reg regs */ - seq_puts(m, "iatu regs reg:\n"); - for (i = 0; i < PCIE_SAVE_REGION_NUM; i++) { - seq_printf(m, "IATU[%d]:\n", i); - base = ep_save->cfg_base + IATU_REG_BASE + i * 100; - - seq_printf(m, "0x%p: 0x%08x 0x%08x 0x%08x 0x%08x\n", - base, - save_reg[i][0], - save_reg[i][1], - save_reg[i][2], - save_reg[i][3]); - base += 0x10; - seq_printf(m, "0x%p: 0x%08x 0x%08x 0x%08x 0x%08x\n", - base, - save_reg[i][4], - save_reg[i][5], - save_reg[i][6], - save_reg[i][7]); - } -} - -static int sprd_pci_ep_dev_show(struct seq_file *m, void *unused) -{ - u32 i; - struct sprd_pci_ep_dev *ep_dev; - struct sprd_pci_ep_dev_save *ep_save; - - for (i = 0; i < PCIE_EP_NR; i++) { - /* ep_save configus */ - ep_save = &g_ep_save[i]; - ep_dev = g_ep_dev[i]; - - if (!ep_dev && !ep_save->save_succ) - continue; - - if (ep_save) - sprd_pci_ep_dev_save_show(m, ep_save, i); - - if (ep_dev) - sprd_pci_ep_dev_config_show(m, ep_dev); - else - sprd_pci_ep_dev_backup_show(m, ep_save, i); - } - - return 0; -} - -static int sprd_pci_ep_dev_open(struct inode *inode, struct file *file) -{ - return single_open(file, sprd_pci_ep_dev_show, NULL); -} - -static const struct file_operations sprd_pci_ep_dev_fops = { - .owner = THIS_MODULE, - .open = sprd_pci_ep_dev_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static struct dentry *g_ep_debugfs_root; - -static int sprd_pci_ep_dev_init_debugfs(void) -{ - struct dentry *g_ep_debugfs_root = debugfs_create_dir("ep_dev", NULL); - - if (!g_ep_debugfs_root) - return -ENXIO; - - debugfs_create_file("ep", 0444, - g_ep_debugfs_root, - NULL, &sprd_pci_ep_dev_fops); - return 0; -} - -static void sprd_pci_ep_dev_remove_debugfs(void) -{ - debugfs_remove_recursive(g_ep_debugfs_root); -} -#endif - -static int __init sprd_pci_ep_dev_init(void) -{ - pr_info("%s %s\n", __func__, QUECTEL_SPRD_PCIE_VERSION); -#if defined(CONFIG_DEBUG_FS) - sprd_pci_ep_dev_init_debugfs(); - sipc_init_debugfs(); -#endif - sipc_init(); - spipe_init(); - spool_init(); - modem_power_manager_init(); - return pci_register_driver(&sprd_pci_ep_dev_driver); -} - -static void __exit sprd_pci_ep_dev_exit(void) -{ - spipe_exit(); - spool_exit(); - modem_power_manager_exit(); - pci_unregister_driver(&sprd_pci_ep_dev_driver); -#if defined(CONFIG_DEBUG_FS) - sprd_pci_ep_dev_remove_debugfs(); -#endif - sipc_exit(); -} - -module_init(sprd_pci_ep_dev_init); -module_exit(sprd_pci_ep_dev_exit); - - -MODULE_DESCRIPTION("SPRD PCI EP DEVICE HOST DRIVER"); -MODULE_AUTHOR("Wenping Zhou "); -MODULE_LICENSE("GPL v2"); -MODULE_VERSION(QUECTEL_SPRD_PCIE_VERSION); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/sprd_pcie_quirks.c b/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/sprd_pcie_quirks.c deleted file mode 100644 index 70a3692f2..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/pcie/sprd_pcie_quirks.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * This file contains work-arounds for many known PCI hardware - * bugs. Devices present only on certain architectures (host - * bridges et cetera) should be handled in arch-specific code. - * - * Note: any quirks for hotpluggable devices must _NOT_ be declared __init. - * - * Copyright (c) 1999 Martin Mares - * - * Init/reset quirks for USB host controllers should be in the - * USB quirks file, where their drivers can access reuse it. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 5,4,0 )) -#include -#endif -#include -#include -#include -#include -#include /* isa_dma_bridge_buggy */ - -#ifndef PCI_VENDOR_ID_SYNOPSYS -#define PCI_VENDOR_ID_SYNOPSYS 0x16c3 -#endif - - - /* - * It's possible that ep bar size is larger than rc allocated - * memory, so need to resize ep bar to small size. - * Original ep bar size:bar0:256MB, bar1:64kb, bar2:256MB, - * bar3: 64kb, bar4:256MB, bar5:64kb. - * resize to bar0:8MB, bar1:64kb, bar2:2MB, bar3: 64kb, - * bar4:2MB, bar5:64kb. - */ -#define SPRD_PCI_BAR0 0x10 -#define SPRD_BAR_NUM 0x6 -#define SPRD_PCI_MISC_CTRL1_OFF 0x8bc -#define SPRD_PCI_DBI_RO_WR_EN (0x1 << 0) -#define SPRD_PCI_RESIZABLE_BAR_EXTENDED_CAP_HEADER 0x260 -#define SPRD_PCI_RESIZABLE_BAR_EXTENDED_CAPID 0x15 -/* Resizable BAR Capability Register */ -#define SPRD_PCI_RESIZABLE_BAR0 0x264 -#define SPRD_PCI_RESIZABLE_BAR2 0x26c -#define SPRD_PCI_RESIZABLE_BAR4 0x274 -#define SPRD_BAR_SUPPORT_2MB (0x1 << 5) -#define SPRD_BAR_SUPPORT_4MB (0x1 << 6) -#define SPRD_BAR_SUPPORT_8MB (0x1 << 7) -/* Resizable BAR Control Register */ -#define SPRD_PCI_RESIZABLE_BAR0_CTL 0x268 -#define SPRD_PCI_RESIZABLE_BAR2_CTL 0x270 -#define SPRD_PCI_RESIZABLE_BAR4_CTL 0x278 -/* bit[13:8] is bar size */ -#define SPRD_PCI_RESIZABLE_BAR_SIZE_MASK 0x3F00 -#define SPRD_PCI_RESIZABLE_2MB (0x1 << 8) -#define SPRD_PCI_RESIZABLE_4MB (0x2 << 8) -#define SPRD_PCI_RESIZABLE_8MB (0x3 << 8) -#define SIZE(val) ((~(val & 0xFFFFFFF0)) + 1) - -static void quirk_sprd_pci_resizebar(struct pci_dev *dev) -{ - u32 val, i, backup; - - pci_read_config_dword(dev, - SPRD_PCI_RESIZABLE_BAR_EXTENDED_CAP_HEADER, &val); - if ((val & SPRD_PCI_RESIZABLE_BAR_EXTENDED_CAPID) != - SPRD_PCI_RESIZABLE_BAR_EXTENDED_CAPID) { - dev_info(&dev->dev, "%s: not support resize bar\n", __func__); - return; - } - - pci_read_config_dword(dev, SPRD_PCI_MISC_CTRL1_OFF, &val); - val |= SPRD_PCI_DBI_RO_WR_EN; - pci_write_config_dword(dev, SPRD_PCI_MISC_CTRL1_OFF, val); - - pci_read_config_dword(dev, SPRD_PCI_RESIZABLE_BAR0, &val); - pci_write_config_dword(dev, SPRD_PCI_RESIZABLE_BAR0, - val | SPRD_BAR_SUPPORT_4MB | - SPRD_BAR_SUPPORT_8MB); - pci_read_config_dword(dev, SPRD_PCI_RESIZABLE_BAR2, &val); - pci_write_config_dword(dev, SPRD_PCI_RESIZABLE_BAR2, - val | SPRD_BAR_SUPPORT_4MB | - SPRD_BAR_SUPPORT_8MB); - pci_read_config_dword(dev, SPRD_PCI_RESIZABLE_BAR4, &val); - pci_write_config_dword(dev, SPRD_PCI_RESIZABLE_BAR4, - val | SPRD_BAR_SUPPORT_4MB | - SPRD_BAR_SUPPORT_8MB); - - pci_read_config_dword(dev, SPRD_PCI_MISC_CTRL1_OFF, &val); - val &= ~SPRD_PCI_DBI_RO_WR_EN; - pci_write_config_dword(dev, SPRD_PCI_MISC_CTRL1_OFF, val); - - pci_read_config_dword(dev, SPRD_PCI_RESIZABLE_BAR0_CTL, &val); - pci_write_config_dword(dev, SPRD_PCI_RESIZABLE_BAR0_CTL, - (val & (~SPRD_PCI_RESIZABLE_BAR_SIZE_MASK)) | - SPRD_PCI_RESIZABLE_4MB); - pci_read_config_dword(dev, SPRD_PCI_RESIZABLE_BAR2_CTL, &val); - pci_write_config_dword(dev, SPRD_PCI_RESIZABLE_BAR2_CTL, - (val & (~SPRD_PCI_RESIZABLE_BAR_SIZE_MASK)) | - SPRD_PCI_RESIZABLE_4MB); - pci_read_config_dword(dev, SPRD_PCI_RESIZABLE_BAR4_CTL, &val); - pci_write_config_dword(dev, SPRD_PCI_RESIZABLE_BAR4_CTL, - (val & (~SPRD_PCI_RESIZABLE_BAR_SIZE_MASK)) | - SPRD_PCI_RESIZABLE_4MB); - - for (i = 0; i < SPRD_BAR_NUM; i++) { - pci_read_config_dword(dev, SPRD_PCI_BAR0 + i * 4, &backup); - pci_write_config_dword(dev, SPRD_PCI_BAR0 + i * 4, 0xFFFFFFFF); - pci_read_config_dword(dev, SPRD_PCI_BAR0 + i * 4, &val); - pci_write_config_dword(dev, SPRD_PCI_BAR0 + i * 4, backup); - - dev_info(&dev->dev, "%s: bar%d size 0x%x\n", - __func__, i, SIZE(val)); - } -} -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_sprd_pci_resizebar); \ No newline at end of file diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/power_manager/Makefile b/package/wwan/driver/quectel_SRPD_PCIE/src/power_manager/Makefile deleted file mode 100644 index 6d5c49962..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/power_manager/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y += power_manager.o diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/power_manager/power_manager.c b/package/wwan/driver/quectel_SRPD_PCIE/src/power_manager/power_manager.c deleted file mode 100644 index 077c31ef9..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/power_manager/power_manager.c +++ /dev/null @@ -1,964 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sprd_mpm.h" -#include "../include/sipc.h" -/* - * The data struct of modem power manager. - */ -struct sprd_mpm_data { -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,18,0 )) - struct wakeup_source *ws; -#else - struct wakeup_source ws; -#endif - struct list_head pms_list; - struct timer_list timer; - spinlock_t mpm_lock; - char name[20]; - const char *last_name; - unsigned int dst; - unsigned int up_cnt; - unsigned int awake_cnt; - unsigned int wakelock_cnt; - unsigned int mpm_state; - unsigned long expires; - unsigned int later_idle; - - /* resource ops functions */ - int (*wait_resource)(unsigned int dst, int timeout); - int (*request_resource)(unsigned int dst); - int (*release_resource)(unsigned int dst); - - struct work_struct release_res_work; - struct work_struct request_res_work; -}; - -/* - * Save all the instance of mpm in here. - */ -static struct sprd_mpm_data *g_sprd_mpm[SIPC_ID_NR]; - -/** - * sprd_mpm_print_awake - * print the wake up list to known who prevent system sleep. - */ -static void sprd_mpm_print_awake(struct sprd_mpm_data *mpm) -{ - struct sprd_pms *pms; - char *awake_info; - int len = 0, max_len = 512; - - awake_info = kmalloc(max_len, GFP_KERNEL); - if (!awake_info) - return; - - /* print pms list */ - list_for_each_entry(pms, &mpm->pms_list, entry) { - if (!pms->awake && pms->pre_awake_cnt == pms->awake_cnt) - continue; - - pms->pre_awake_cnt = pms->awake_cnt; - snprintf(awake_info + len, - max_len - len, - "%s is awake, awake_cnt = %d\n", - pms->name, - pms->awake_cnt); - len = strlen(awake_info); - } - - if (len) - pr_info("mpm: %s\n", awake_info); - - kfree(awake_info); -} - -/** - * sprd_mpm_pm_event - * monitor the PM_SUSPEND_PREPARE event. - */ -static int sprd_mpm_pm_event(struct notifier_block *notifier, - unsigned long pm_event, void *unused) -{ - unsigned int i; - struct sprd_mpm_data *cur; - - switch (pm_event) { - case PM_SUSPEND_PREPARE: - case PM_POST_SUSPEND: - /* check if has wake lock. */ - for (i = 0; i < SIPC_ID_NR; i++) { - if (!g_sprd_mpm[i]) - continue; - - cur = g_sprd_mpm[i]; - sprd_mpm_print_awake(cur); - } - break; - - default: - break; - } - - return NOTIFY_DONE; -} - -/* - * The pm event notify data, for the register pm notifier. - */ -static struct notifier_block sprd_mpm_notifier_block = { - .notifier_call = sprd_mpm_pm_event, -}; - -/** - * sprd_mpm_request_resource - * request resource. - */ -static void sprd_mpm_request_resource(struct sprd_mpm_data *mpm) -{ - if (mpm->request_resource) - schedule_work(&mpm->request_res_work); -} - -/** - * sprd_mpm_release_resource - * release resource. - */ -static void sprd_mpm_release_resource(struct sprd_mpm_data *mpm) -{ - if (mpm->release_resource) - schedule_work(&mpm->release_res_work); -} - -/** - * sprd_mpm_wait_resource -wait resource. - */ -static int sprd_mpm_wait_resource(struct sprd_mpm_data *mpm, int timeout) -{ - int ret = 0; - - if (mpm->wait_resource) { - ret = mpm->wait_resource(mpm->dst, timeout); - if (ret < 0 && ret != -ERESTARTSYS && timeout) - pr_err("mpm: %s wait resource, ret=%d, timeout=%d.\n", - mpm->name, ret, timeout); - } - - return ret; -} - -/** - * sprd_mpm_active - * set the state to busy. - */ -static void sprd_mpm_active(struct sprd_mpm_data *mpm) -{ - pr_debug("mpm: %s active, set state to busy.\n", mpm->name); - - mpm->mpm_state = SPRD_MPM_BUSY; - sprd_mpm_request_resource(mpm); -} - -/** - * sprd_mpm_deactive - * del the idle timer, - * set the state to idle. - */ -static void sprd_mpm_deactive(struct sprd_mpm_data *mpm) -{ - pr_debug("mpm: %s deactive, set state to idle.\n", mpm->name); - - mpm->mpm_state = SPRD_MPM_IDLE; - mpm->expires = 0; - sprd_mpm_release_resource(mpm); -} - -/** - * sprd_mpm_start_deactive - * start the deactive timer. - */ -static void sprd_mpm_start_deactive(struct sprd_mpm_data *mpm) -{ - pr_debug("mpm: %s start deactive.\n", mpm->name); - - mpm->expires = jiffies + msecs_to_jiffies(mpm->later_idle); - if (!mpm->expires) - mpm->expires = 1; - - mod_timer(&mpm->timer, mpm->expires); -} - -/** - * sprd_mpm_request_res_work_fn - * do release resource call in here. - */ -static void sprd_mpm_request_res_work_fn(struct work_struct *work) -{ - struct sprd_mpm_data *mpm = container_of(work, struct sprd_mpm_data, - request_res_work); - int ret; - - pr_debug("mpm: %s request res work.\n", mpm->name); - - ret = mpm->request_resource(mpm->dst); - if (ret) - pr_err("mpm: %s request res, ret = %d.\n", mpm->name, ret); -} - -/** - * sprd_mpm_release_res_work_fn - * do relase resource call in here - */ -static void sprd_mpm_release_res_work_fn(struct work_struct *work) -{ - struct sprd_mpm_data *mpm = container_of(work, struct sprd_mpm_data, - release_res_work); - int ret; - - pr_debug("mpm: %s releae res work.\n", mpm->name); - - ret = mpm->release_resource(mpm->dst); - if (ret) - pr_err("mpm: %s request res, ret = %d.\n", mpm->name, ret); -} - -/** - * sprd_mpm_deactive_timer_fn - * in a period of time (mpm->later_idle), - * have no modem resource request, - * we consider that it doesn't need modem resource, - * than set the state to idle. - */ -static void sprd_mpm_deactive_timer_fn( -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 4,10,0 )) - unsigned long data) -{ - struct sprd_mpm_data *mpm = (struct sprd_mpm_data *)data; -#else - struct timer_list *t) -{ - struct sprd_mpm_data *mpm = from_timer(mpm, t, timer); -#endif - - unsigned long flags; - - pr_debug("mpm: %s deactive timer.\n", mpm->name); - - spin_lock_irqsave(&mpm->mpm_lock, flags); - /* expires is 0, means the timer has been cancelled. */ - if (mpm->expires) - sprd_mpm_deactive(mpm); - spin_unlock_irqrestore(&mpm->mpm_lock, flags); -} - -/** - * sprd_pms_cancel_timer - * cancel the pms wakelock timer. - */ -static void sprd_pms_cancel_timer(struct sprd_pms *pms) -{ - unsigned long flags; - bool print = false; - - spin_lock_irqsave(&pms->expires_lock, flags); - if (pms->expires) { - print = true; - pms->expires = 0; - del_timer(&pms->wake_timer); - } - spin_unlock_irqrestore(&pms->expires_lock, flags); - - if (print) - pr_debug("pms: %s del timer.\n", pms->name); - -} - -/** - * sprd_mpm_cancel_timer - * cancel the deactive timer. - */ -static void sprd_mpm_cancel_timer(struct sprd_mpm_data *mpm) -{ - if (mpm->expires) { - pr_debug("mpm: %s del timer.\n", mpm->name); - - mpm->expires = 0; - del_timer(&mpm->timer); - } -} - -/** - * sprd_mpm_up - * modem power manger power up. - */ -static void sprd_mpm_up(struct sprd_mpm_data *mpm, const char *name) -{ - unsigned long flags; - - spin_lock_irqsave(&mpm->mpm_lock, flags); - - /* first cancel deactive timer */ - sprd_mpm_cancel_timer(mpm); - mpm->last_name = name; - - mpm->up_cnt++; - /* when up_cnt is change form 0 to 1, ready active pms. - * Although the cnt is 0, but later down, the state may is still busy, - * so here must see whether the mpm state is idle. - */ - if (mpm->up_cnt == 1 && - mpm->mpm_state == SPRD_MPM_IDLE) - sprd_mpm_active(mpm); - - spin_unlock_irqrestore(&mpm->mpm_lock, flags); - - pr_debug("mpm: %s up, up_cnt=%d.\n", mpm->name, mpm->up_cnt); -} - -/** - * sprd_mpm_down - * modem power manger power down. - */ -static void sprd_mpm_down(struct sprd_mpm_data *mpm, bool immediately) -{ - unsigned long flags; - - /* - * when up_cnt count is change form 1 to 0, - * start deactive pms. - */ - spin_lock_irqsave(&mpm->mpm_lock, flags); - mpm->up_cnt--; - if (!mpm->up_cnt) { - if (mpm->later_idle && !immediately) - sprd_mpm_start_deactive(mpm); - else - sprd_mpm_deactive(mpm); - } - spin_unlock_irqrestore(&mpm->mpm_lock, flags); - - pr_debug("mpm: %s down, up_cnt=%d.\n", mpm->name, mpm->up_cnt); -} - -/** - * sprd_mpm_stay_awake - * modem power manager stay awake. - */ -static void sprd_mpm_stay_awake(struct sprd_mpm_data *mpm) -{ - unsigned long flags; - - /* - * when wakelock_cnt is change form 0 to 1, - * get the system wake lock. - */ - spin_lock_irqsave(&mpm->mpm_lock, flags); - mpm->wakelock_cnt++; - if (mpm->wakelock_cnt == 1) { - mpm->awake_cnt++; -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,18,0 )) - __pm_stay_awake(mpm->ws); -#else - __pm_stay_awake(&mpm->ws); -#endif - } - spin_unlock_irqrestore(&mpm->mpm_lock, flags); - - pr_debug("mpm: %s wake, wake_cnt=%d\n", - mpm->name, mpm->wakelock_cnt); -} - -/** - * sprd_mpm_relax - * modem power manager relax wakelock. - */ -static void sprd_mpm_relax(struct sprd_mpm_data *mpm) -{ - unsigned long flags; - - /* - * when wakelock_cnt is change form 0 to 1, - * release the system wake lock. - */ - spin_lock_irqsave(&mpm->mpm_lock, flags); - mpm->wakelock_cnt--; - if (!mpm->wakelock_cnt) -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,18,0 )) - __pm_relax(mpm->ws); -#else - __pm_relax(&mpm->ws); -#endif - spin_unlock_irqrestore(&mpm->mpm_lock, flags); - - pr_debug("mpm: %s relax wake, wake_cnt=%d\n", - mpm->name, mpm->wakelock_cnt); -} - -/** - * sprd_pms_do_up_single - * do pms power up. - */ -static void sprd_pms_do_up_single(struct sprd_pms *pms) -{ - struct sprd_mpm_data *mpm = (struct sprd_mpm_data *)pms->data; - - /* - * when active_cnt is change form 0 to 1, mpm up. - */ - pms->active_cnt++; - if (pms->active_cnt == 1) - sprd_mpm_up(mpm, pms->name); - - pr_debug("pms: %s up, active_cnt=%d.\n", - pms->name, pms->active_cnt); -} - -/** - * sprd_pms_do_up_multi - * do pms power up. - */ -static void sprd_pms_do_up_multi(struct sprd_pms *pms) -{ - struct sprd_mpm_data *mpm = (struct sprd_mpm_data *)pms->data; - unsigned long flags; - bool active = false; - - /* - * when active_cnt is change form 0 to 1, mpm up. - */ - spin_lock_irqsave(&pms->active_lock, flags); - - pms->active_cnt++; - if (pms->active_cnt == 1) - active = true; - - spin_unlock_irqrestore(&pms->active_lock, flags); - - pr_debug("pms: %s up, active_cnt=%d.\n", - pms->name, pms->active_cnt); - - if (active) - sprd_mpm_up(mpm, pms->name); -} - -static void sprd_pms_do_up(struct sprd_pms *pms) -{ - if (pms->multitask) - sprd_pms_do_up_multi(pms); - else - sprd_pms_do_up_single(pms); -} - -/** - * sprd_pms_do_down_single - * do pms power down. - */ -static void sprd_pms_do_down_single(struct sprd_pms *pms, bool immediately) -{ - struct sprd_mpm_data *mpm = (struct sprd_mpm_data *)pms->data; - /* - * when active_cnt is change form 1 to 0, mpm down. - */ - if (pms->active_cnt > 0) { - pms->active_cnt--; - if (pms->active_cnt == 0) - sprd_mpm_down(mpm, immediately); - } - - pr_debug("pms: %s down, active_cnt=%d.\n", - pms->name, pms->active_cnt); -} - -/** - * sprd_pms_do_down - * do pms power down. - */ -static void sprd_pms_do_down_multi(struct sprd_pms *pms, bool immediately) -{ - struct sprd_mpm_data *mpm = (struct sprd_mpm_data *)pms->data; - unsigned long flags; - bool deactive = false; - - /* - * when active_cnt is change form 1 to 0, mpm down. - */ - spin_lock_irqsave(&pms->active_lock, flags); - - if (pms->active_cnt > 0) { - pms->active_cnt--; - if (pms->active_cnt == 0) - deactive = true; - } - - spin_unlock_irqrestore(&pms->active_lock, flags); - - pr_debug("pms: %s down, active_cnt=%d.\n", - pms->name, pms->active_cnt); - - if (deactive) - sprd_mpm_down(mpm, immediately); -} - -static void sprd_pms_do_down(struct sprd_pms *pms, bool immediately) -{ - if (pms->multitask) - sprd_pms_do_down_multi(pms, immediately); - else - sprd_pms_do_down_single(pms, immediately); -} - -/** - * sprd_pms_stay_awake - * power manger source stay awake. - */ -static void sprd_pms_stay_awake(struct sprd_pms *pms) -{ - struct sprd_mpm_data *mpm = (struct sprd_mpm_data *)pms->data; - - pr_debug("pms: %s stay awake.\n", pms->name); - - pms->awake_cnt++; - if (!pms->awake) { - pms->awake = true; - sprd_mpm_stay_awake(mpm); - } -} - -/** - * sprd_pms_relax - * power manger source release wakelock. - */ -static void sprd_pms_relax(struct sprd_pms *pms) -{ - struct sprd_mpm_data *mpm = (struct sprd_mpm_data *)pms->data; - - pr_debug("pms: %s relax awake.\n", pms->name); - - if (pms->awake) { - pms->awake = false; - sprd_mpm_relax(mpm); - } -} - -/** - * sprd_pms_relax_wakelock_timer - * the timer process function of pms delay release wakelock. - */ -static void sprd_pms_relax_wakelock_timer( -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 4,10,0 )) - unsigned long data) -{ - struct sprd_pms *pms = (struct sprd_pms *)data; -#else - struct timer_list *t) -{ - struct sprd_pms *pms = from_timer(pms, t, wake_timer); -#endif - - unsigned long flags; - bool relax = false; - - pr_debug("pms: %s timer down.\n", pms->name); - - spin_lock_irqsave(&pms->expires_lock, flags); - /* - * if jiffies < pms->expires, mpm called has been canceled, - * don't call sprd_pms_down. - */ - if (pms->expires && time_after_eq(jiffies, pms->expires)) { - pms->expires = 0; - relax = true; - } - spin_unlock_irqrestore(&pms->expires_lock, flags); - - if (relax) - sprd_pms_relax(pms); -} - -int sprd_mpm_create(unsigned int dst, const char *name, - unsigned int later_idle) -{ - struct sprd_mpm_data *mpm; - - if (dst >= SIPC_ID_NR) - return -EINVAL; - - mpm = kzalloc(sizeof(*mpm), GFP_KERNEL); - if (!mpm) - return -ENOMEM; - - snprintf(mpm->name, sizeof(mpm->name), "%s-mpm-%d", name, dst); - - mpm->dst = dst; - mpm->later_idle = later_idle; - - spin_lock_init(&mpm->mpm_lock); - INIT_LIST_HEAD(&mpm->pms_list); -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,18,0 )) - mpm->ws = wakeup_source_register(NULL, mpm->name); -#else - wakeup_source_init(&mpm->ws, mpm->name); -#endif - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 4,10,0 )) - setup_timer(&mpm->timer, - sprd_mpm_deactive_timer_fn, - (unsigned long)mpm); -#else - timer_setup(&mpm->timer, - sprd_mpm_deactive_timer_fn, - 0); -#endif - - INIT_WORK(&mpm->request_res_work, sprd_mpm_request_res_work_fn); - INIT_WORK(&mpm->release_res_work, sprd_mpm_release_res_work_fn); - - g_sprd_mpm[dst] = mpm; - - return 0; -} - -int sprd_mpm_init_resource_ops(unsigned int dst, - int (*wait_resource)(unsigned int dst, - int timeout), - int (*request_resource)(unsigned int dst), - int (*release_resource)(unsigned int dst)) -{ - struct sprd_mpm_data *mpm; - - if (dst >= SIPC_ID_NR) - return -EINVAL; - - mpm = g_sprd_mpm[dst]; - if (!mpm) - return -ENODEV; - - mpm->wait_resource = wait_resource; - mpm->request_resource = request_resource; - mpm->release_resource = release_resource; - - return 0; -} - -int sprd_mpm_destroy(unsigned int dst) -{ - struct sprd_pms *pms, *temp; - struct sprd_mpm_data *mpm; - unsigned long flags; - - if (dst >= SIPC_ID_NR) - return -EINVAL; - - mpm = g_sprd_mpm[dst]; - if (!mpm) - return -ENODEV; - - sprd_mpm_cancel_timer(mpm); - cancel_work_sync(&mpm->request_res_work); - cancel_work_sync(&mpm->release_res_work); - - spin_lock_irqsave(&mpm->mpm_lock, flags); - list_for_each_entry_safe(pms, - temp, - &mpm->pms_list, - entry) { - sprd_pms_cancel_timer(pms); - list_del(&pms->entry); - } - spin_unlock_irqrestore(&mpm->mpm_lock, flags); - - kfree(mpm); - g_sprd_mpm[dst] = NULL; - - return 0; -} - -struct sprd_pms *sprd_pms_create(unsigned int dst, - const char *name, bool multitask) -{ - unsigned long flags; - struct sprd_pms *pms; - struct sprd_mpm_data *mpm; - - if (dst >= SIPC_ID_NR) - return NULL; - - mpm = g_sprd_mpm[dst]; - if (!mpm) { - pr_err("mpm: %s pms init failed, dst=%d.\n", name, dst); - return NULL; - } - - pms = kzalloc(sizeof(*pms), GFP_KERNEL); - if (!pms) - return NULL; - - pms->multitask = multitask; - pms->name = name; - pms->data = (void *)mpm; - - spin_lock_init(&pms->expires_lock); - spin_lock_init(&pms->active_lock); - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 4,10,0 )) - setup_timer(&pms->wake_timer, - sprd_pms_relax_wakelock_timer, (unsigned long)pms); -#else - timer_setup(&pms->wake_timer, - sprd_pms_relax_wakelock_timer, 0); -#endif - - spin_lock_irqsave(&mpm->mpm_lock, flags); - list_add(&pms->entry, &mpm->pms_list); - spin_unlock_irqrestore(&mpm->mpm_lock, flags); - - return pms; -} - -void sprd_pms_destroy(struct sprd_pms *pms) -{ - unsigned long flags; - struct sprd_mpm_data *mpm; - - if (pms) { - sprd_pms_cancel_timer(pms); - mpm = (struct sprd_mpm_data *)pms->data; - spin_lock_irqsave(&mpm->mpm_lock, flags); - list_del(&pms->entry); - spin_unlock_irqrestore(&mpm->mpm_lock, flags); - kfree(pms); - } -} - -/** - * sprd_pms_request_resource - request mpm resource - * - * @pms, the point of this pms. - * @timeout, in ms. - * - * Returns: - * 0 resource ready, - * < 0 resoure not ready, - * -%ERESTARTSYS if it was interrupted by a signal. - */ -int sprd_pms_request_resource(struct sprd_pms *pms, int timeout) -{ - int ret; - struct sprd_mpm_data *mpm; - - if (!pms) - return -EINVAL; - - sprd_pms_do_up(pms); - - /* wait resource */ - mpm = (struct sprd_mpm_data *)pms->data; - ret = sprd_mpm_wait_resource(mpm, timeout); - if (ret) - sprd_pms_do_down(pms, false); - - return ret; -} - -/** - * sprd_pms_release_resource - release mpm resource. - * - * @pms, the point of this pms. - */ -void sprd_pms_release_resource(struct sprd_pms *pms) -{ - if (pms) - sprd_pms_do_down(pms, false); -} - -/** - * sprd_pms_request_wakelock - request wakelock - * - * @pms, the point of this pms. - */ -void sprd_pms_request_wakelock(struct sprd_pms *pms) -{ - if (pms) { - sprd_pms_cancel_timer(pms); - sprd_pms_stay_awake(pms); - } -} - -/** - * sprd_pms_release_wakelock - release wakelock - * - * @pms, the point of this pms. - */ -void sprd_pms_release_wakelock(struct sprd_pms *pms) -{ - if (pms) { - sprd_pms_cancel_timer(pms); - sprd_pms_relax(pms); - } -} - -/** - * sprd_pms_request_wakelock_period - - * request wake lock, and will auto reaslse in msec ms. - * - * @pms, the point of this pms. - * @msec, will auto reaslse in msec ms - */ -void sprd_pms_request_wakelock_period(struct sprd_pms *pms, unsigned int msec) -{ - sprd_pms_request_wakelock(pms); - sprd_pms_release_wakelock_later(pms, msec); -} - -/** - * sprd_pms_release_wakelock_later - release wakelock later. - * - * @pms, the point of this pms. - * @msec, later time (in ms). - */ -void sprd_pms_release_wakelock_later(struct sprd_pms *pms, - unsigned int msec) -{ - unsigned long expires; - unsigned long flags; - - if (pms) { - pr_debug("pms: %s release wakelock after %d ms.\n", - pms->name, msec); - - spin_lock_irqsave(&pms->expires_lock, flags); - expires = jiffies + msecs_to_jiffies(msec); - if (!expires) - expires = 1; - - /* always update the timer with new time */ - pms->expires = expires; - mod_timer(&pms->wake_timer, expires); - spin_unlock_irqrestore(&pms->expires_lock, flags); - } -} - -void sprd_pms_power_up(struct sprd_pms *pms) -{ - if (pms) - sprd_pms_do_up(pms); -} - -void sprd_pms_power_down(struct sprd_pms *pms, bool immediately) -{ - if (pms) - sprd_pms_do_down(pms, immediately); -} - -#if defined(CONFIG_DEBUG_FS) -static int sprd_mpm_stats_show(struct seq_file *m, void *unused) -{ - unsigned long flags; - struct sprd_pms *pms; - struct sprd_mpm_data *cur; - unsigned int i, ms; - - seq_puts(m, "---------------------------------------------\n"); - seq_puts(m, "All mpm list:\n"); - - for (i = 0; i < SIPC_ID_NR; i++) { - if (!g_sprd_mpm[i]) - continue; - - cur = g_sprd_mpm[i]; - seq_puts(m, "------------------------------------\n"); - seq_printf(m, "mpm = %s info:\n", cur->name); - seq_printf(m, "last up module = %s info:\n", - cur->last_name ? cur->last_name : "null"); - - if (cur->expires > 0) { - ms = jiffies_to_msecs(cur->expires - jiffies); - seq_printf(m, "left %d ms to idle\n", ms); - } - - seq_printf(m, "up_cnt=%d, state=%d.\n", - cur->up_cnt, cur->mpm_state); - seq_printf(m, "wakelock_cnt=%d, awake_cnt=%d\n", - cur->wakelock_cnt, cur->awake_cnt); - seq_puts(m, "------------------------------------\n"); - - seq_puts(m, "active pms list:\n"); - spin_lock_irqsave(&cur->mpm_lock, flags); - list_for_each_entry(pms, &cur->pms_list, entry) { - if (!pms->active_cnt && !pms->awake) - continue; - - seq_printf(m, " %s: active_cnt=%d, awake=%d\n", - pms->name, pms->active_cnt, pms->awake); - } - spin_unlock_irqrestore(&cur->mpm_lock, flags); - } - - seq_puts(m, "---------------------------------------------\n"); - - return 0; -} - -static int sprd_mpm_stats_open(struct inode *inode, struct file *file) -{ - return single_open(file, sprd_mpm_stats_show, NULL); -} - -static const struct file_operations sprd_mpm_stats_fops = { - .owner = THIS_MODULE, - .open = sprd_mpm_stats_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int sprd_mpm_init_debugfs(void) -{ - struct dentry *root = debugfs_create_dir("mpm", NULL); - - if (!root) - return -ENXIO; - - debugfs_create_file("power_manage", 0444, - (struct dentry *)root, - NULL, &sprd_mpm_stats_fops); - return 0; -} -#endif - - -int modem_power_manager_init(void) -{ - register_pm_notifier(&sprd_mpm_notifier_block); - -#if defined(CONFIG_DEBUG_FS) - sprd_mpm_init_debugfs(); -#endif - - return 0; -} -EXPORT_SYMBOL(modem_power_manager_init); - -void modem_power_manager_exit(void) -{ - unregister_pm_notifier(&sprd_mpm_notifier_block); -} -EXPORT_SYMBOL(modem_power_manager_exit); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/pwake_function/ipq4019/pcie-qcom.c b/package/wwan/driver/quectel_SRPD_PCIE/src/pwake_function/ipq4019/pcie-qcom.c deleted file mode 100755 index fcd0d30a2..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/pwake_function/ipq4019/pcie-qcom.c +++ /dev/null @@ -1,2237 +0,0 @@ -/* - * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. - * Copyright 2015 Linaro Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only 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 the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pcie-designware.h" - -#define PCIE20_PARF_SYS_CTRL 0x00 -#define ECAM_BLOCKER_EN_RANGE2 BIT(30) -#define MAC_PHY_POWERDOWN_IN_P2_D_MUX_EN BIT(29) -#define ECAM_REMOVE_OFFSET_EN BIT(27) -#define ECAM_BLOCKER_EN BIT(26) -#define MST_WAKEUP_EN BIT(13) -#define SLV_WAKEUP_EN BIT(12) -#define MSTR_ACLK_CGC_DIS BIT(10) -#define SLV_ACLK_CGC_DIS BIT(9) -#define CORE_CLK_CGC_DIS BIT(6) -#define AUX_PWR_DET BIT(4) -#define CORE_CLK_2AUX_CLK_MUX_DIS BIT(3) -#define L23_CLK_RMV_DIS BIT(2) -#define L1_CLK_RMV_DIS BIT(1) - -#define PCIE20_PARF_Q2A_FLUSH 0x1AC - -#define PCIE20_PARF_LTSSM 0x1B0 -#define LTSSM_EN (1 << 8) - -#define PCIE20_PARF_PHY_CTRL 0x40 -#define PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK (0x1f << 16) -#define PHY_CTRL_PHY_TX0_TERM_OFFSET(x) (x << 16) - -#define PCIE20_PARF_PHY_REFCLK 0x4C -#define REF_SSP_EN BIT(16) -#define REF_USE_PAD BIT(12) - -#define PCIE20_PARF_DBI_BASE_ADDR 0x168 -#define PCIE20_PARF_SLV_ADDR_SPACE_SIZE 0x16c -#define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT 0x178 - -#define PARF_MHI_CLOCK_RESET_CTRL 0x174 -#define BYPASS BIT(4) -#define MSTR_AXI_CLK_EN BIT(1) -#define AHB_CLK_EN BIT(0) - -#define PARF_BLOCK_SLV_AXI_WR_BASE 0x360 -#define PARF_BLOCK_SLV_AXI_WR_LIMIT 0x368 -#define PARF_BLOCK_SLV_AXI_RD_BASE 0x370 -#define PARF_BLOCK_SLV_AXI_RD_LIMIT 0x378 -#define PARF_ECAM_BASE 0x380 -#define PARF_ECAM_OFFSET_REMOVAL_BASE 0x388 -#define PARF_ECAM_OFFSET_REMOVAL_LIMIT 0x390 -#define PARF_BLOCK_SLV_AXI_WR_BASE_2 0x398 -#define PARF_BLOCK_SLV_AXI_WR_LIMIT_2 0x3A0 -#define PARF_BLOCK_SLV_AXI_RD_BASE_2 0x3A8 -#define PARF_BLOCK_SLV_AXI_RD_LIMIT_2 0x3B0 -#define PARF_BDF_TO_SID_TABLE 0x2000 - -#define PCIE_PARF_DEVICE_TYPE 0x1000 -#define DEVICE_TYPE_RC 0x4 - -#define PCIE20_ELBI_SYS_CTRL 0x04 -#define PCIE20_ELBI_SYS_CTRL_LT_ENABLE BIT(0) -#define PCIE20_ELBI_SYS_STTS 0x08 -#define XMLH_LINK_UP 0x400 - -#define PCIE20_CAP 0x70 -#define PCIE20_CAP_LINKCTRLSTATUS (PCIE20_CAP + 0x10) - -#define PCIE20_AXI_MSTR_RESP_COMP_CTRL0 0x818 -#define PCIE20_AXI_MSTR_RESP_COMP_CTRL1 0x81c - -#define PCIE20_PLR_IATU_VIEWPORT 0x900 -#define PCIE20_PLR_IATU_REGION_OUTBOUND (0x0 << 31) -#define PCIE20_PLR_IATU_REGION_INDEX(x) (x << 0) - -#define PCIE20_PLR_IATU_CTRL1 0x904 -#define PCIE20_PLR_IATU_TYPE_CFG0 (0x4 << 0) -#define PCIE20_PLR_IATU_TYPE_MEM (0x0 << 0) - -#define PCIE20_PLR_IATU_CTRL2 0x908 -#define PCIE20_PLR_IATU_ENABLE BIT(31) - -#define PCIE20_PLR_IATU_LBAR 0x90C -#define PCIE20_PLR_IATU_UBAR 0x910 -#define PCIE20_PLR_IATU_LAR 0x914 -#define PCIE20_PLR_IATU_LTAR 0x918 -#define PCIE20_PLR_IATU_UTAR 0x91c - -#define MSM_PCIE_DEV_CFG_ADDR 0x01000000 -#define PCIE20_CAP_LINK_CAPABILITIES (PCIE20_CAP + 0xC) -#define PCIE20_CAP_LINK_1 (PCIE20_CAP + 0x14) -#define PCIE_CAP_LINK1_VAL 0x2fd7f - - -#define PCIE20_COMMAND_STATUS 0x04 -#define CMD_BME_VAL 0x4 -#define BUS_MASTER_EN 0x7 - -#define PCIE20_DEVICE_CONTROL2_STATUS2 0x98 -#define PCIE_CAP_CPL_TIMEOUT_DISABLE 0x10 - -#define PCIE30_GEN3_RELATED_OFF 0x890 -#define GEN3_EQUALIZATION_DISABLE BIT(16) -#define RXEQ_RGRDLESS_RXTS BIT(13) -#define GEN3_ZRXDC_NONCOMPL BIT(0) - -#define PCIE20_MISC_CONTROL_1_REG 0x8BC -#define DBI_RO_WR_EN 1 - -#define PERST_DELAY_US 1000 -/* PARF registers */ -#define PCIE20_PARF_PCS_DEEMPH 0x34 -#define PCS_DEEMPH_TX_DEEMPH_GEN1(x) (x << 16) -#define PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(x) (x << 8) -#define PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(x) (x << 0) - -#define PCIE20_PARF_PCS_SWING 0x38 -#define PCS_SWING_TX_SWING_FULL(x) (x << 8) -#define PCS_SWING_TX_SWING_LOW(x) (x << 0) - -#define PCIE20_PARF_CONFIG_BITS 0x50 -#define PHY_RX0_EQ(x) (x << 24) - -#define PCIE20_LNK_CONTROL2_LINK_STATUS2 0xA0 -#define PCIE_CAP_CURR_DEEMPHASIS BIT(16) -#define SPEED_GEN1 0x1 -#define SPEED_GEN2 0x2 -#define SPEED_GEN3 0x3 -#define PCIE_CAP_TARGET_LINK_SPEED_MASK __mask(3, 0) - -#define __set(v, a, b) (((v) << (b)) & GENMASK(a, b)) -#define __mask(a, b) (((1 << ((a) + 1)) - 1) & ~((1 << (b)) - 1)) -#define PCIE20_DEV_CAS 0x78 -#define PCIE20_MRRS_MASK __mask(14, 12) -#define PCIE20_MRRS(x) __set(x, 14, 12) -#define PCIE20_MPS_MASK __mask(7, 5) -#define PCIE20_MPS(x) __set(x, 7, 5) - -#define AXI_CLK_RATE 200000000 -#define RCHNG_CLK_RATE 100000000 - -#define PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE 0x358 -#define SLV_ADDR_SPACE_SZ 0x10000000 - -#define PCIE_V2_PARF_SIZE 0x2000 - -#define PCIE20_INT_ALL_STATUS 0x224 -#define PCIE20_INT_ALL_CLEAR 0x228 -#define PCIE20_INT_ALL_MASK 0x22c -#define PCIE_LINK_UP 0x2000 -#define PCIE_LINK_DOWN 0x2 - -#define PCIE_ATU_CR1_OUTBOUND_6_GEN3 0xC00 -#define PCIE_ATU_CR2_OUTBOUND_6_GEN3 0xC04 -#define PCIE_ATU_LOWER_BASE_OUTBOUND_6_GEN3 0xC08 -#define PCIE_ATU_UPPER_BASE_OUTBOUND_6_GEN3 0xC0C -#define PCIE_ATU_LIMIT_OUTBOUND_6_GEN3 0xC10 -#define PCIE_ATU_LOWER_TARGET_OUTBOUND_6_GEN3 0xC14 -#define PCIE_ATU_UPPER_TARGET_OUTBOUND_6_GEN3 0xC18 - -#define PCIE_ATU_CR1_OUTBOUND_7_GEN3 0xE00 -#define PCIE_ATU_CR2_OUTBOUND_7_GEN3 0xE04 -#define PCIE_ATU_LOWER_BASE_OUTBOUND_7_GEN3 0xE08 -#define PCIE_ATU_UPPER_BASE_OUTBOUND_7_GEN3 0xE0C -#define PCIE_ATU_LIMIT_OUTBOUND_7_GEN3 0xE10 -#define PCIE_ATU_LOWER_TARGET_OUTBOUND_7_GEN3 0xE14 -#define PCIE_ATU_UPPER_TARGET_OUTBOUND_7_GEN3 0xE18 - -#define PCIE_ASPM_MASK 0x3 -#define PCIE_ASPM_POS 10 - -struct qcom_pcie_resources_v0 { - struct clk *iface_clk; - struct clk *core_clk; - struct clk *phy_clk; - struct clk *aux_clk; - struct clk *ref_clk; - struct reset_control *pci_reset; - struct reset_control *axi_reset; - struct reset_control *ahb_reset; - struct reset_control *por_reset; - struct reset_control *phy_reset; - struct reset_control *ext_reset; - struct regulator *vdda; - struct regulator *vdda_phy; - struct regulator *vdda_refclk; - uint8_t phy_tx0_term_offset; -}; - -struct qcom_pcie_resources_v1 { - struct clk *iface; - struct clk *aux; - struct clk *master_bus; - struct clk *slave_bus; - struct reset_control *core; - struct regulator *vdda; -}; - -struct qcom_pcie_resources_v2 { - struct clk *ahb_clk; - struct clk *axi_m_clk; - struct clk *axi_s_clk; - struct reset_control *axi_m_reset; - struct reset_control *axi_s_reset; - struct reset_control *pipe_reset; - struct reset_control *axi_m_vmid_reset; - struct reset_control *axi_s_xpu_reset; - struct reset_control *parf_reset; - struct reset_control *phy_reset; - struct reset_control *axi_m_sticky_reset; - struct reset_control *pipe_sticky_reset; - struct reset_control *pwr_reset; - struct reset_control *ahb_reset; - struct reset_control *phy_ahb_reset; - struct regulator *vdda; - struct regulator *vdda_phy; - struct regulator *vdda_refclk; -}; - -struct qcom_pcie_resources_v3 { - struct clk *sys_noc_clk; - struct clk *axi_m_clk; - struct clk *axi_s_clk; - struct clk *ahb_clk; - struct clk *aux_clk; - struct clk *axi_bridge_clk; - struct clk *rchng_clk; - struct reset_control *axi_m_reset; - struct reset_control *axi_s_reset; - struct reset_control *pipe_reset; - struct reset_control *axi_m_sticky_reset; - struct reset_control *axi_s_sticky_reset; - struct reset_control *ahb_reset; - struct reset_control *sticky_reset; - struct reset_control *sleep_reset; - - struct regulator *vdda; - struct regulator *vdda_phy; - struct regulator *vdda_refclk; -}; - -union qcom_pcie_resources { - struct qcom_pcie_resources_v0 v0; - struct qcom_pcie_resources_v1 v1; - struct qcom_pcie_resources_v2 v2; - struct qcom_pcie_resources_v3 v3; -}; - -struct qcom_pcie; - -struct qcom_pcie_ops { - int (*get_resources)(struct qcom_pcie *pcie); - int (*init)(struct qcom_pcie *pcie); - void (*deinit)(struct qcom_pcie *pcie); -}; - -struct qcom_pcie { - struct pcie_port pp; - struct device *dev; - union qcom_pcie_resources res; - void __iomem *parf; - void __iomem *dbi; - void __iomem *elbi; - void __iomem *dm_iatu; - struct phy *phy; - struct gpio_desc *reset; - struct qcom_pcie_ops *ops; - struct work_struct handle_wake_work; - struct work_struct handle_e911_work; - uint32_t force_gen1; - uint32_t force_gen2; - u32 is_emulation; - u32 compliance; - u32 use_delay; - u32 link_retries_count; - u32 slot_id; - u32 cap_active_state_link_pm; - u32 is_gen3; - int global_irq; - int wake_irq; - int link_down_irq; - int link_up_irq; - int mdm2ap_e911_irq; - bool enumerated; - uint32_t rc_idx; - struct qcom_pcie_register_event *event_reg; - struct notifier_block pci_reboot_notifier; -}; - -#define to_qcom_pcie(x) container_of(x, struct qcom_pcie, pp) - -#define MAX_RC_NUM 3 -static struct qcom_pcie *qcom_pcie_dev[MAX_RC_NUM]; -struct gpio_desc *mdm2ap_e911; - -static inline void -writel_masked(void __iomem *addr, u32 clear_mask, u32 set_mask) -{ - u32 val = readl(addr); - - val &= ~clear_mask; - val |= set_mask; - writel(val, addr); -} - -static void qcom_ep_reset_assert(struct qcom_pcie *pcie) -{ - gpiod_set_value(pcie->reset, 1); - usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500); -} - -static void qcom_ep_reset_deassert(struct qcom_pcie *pcie) -{ - msleep(100); - gpiod_set_value(pcie->reset, 0); - usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500); -} - -static irqreturn_t qcom_pcie_msi_irq_handler(int irq, void *arg) -{ - struct pcie_port *pp = arg; - - return dw_handle_msi_irq(pp); -} - -static int qcom_pcie_establish_link(struct qcom_pcie *pcie) -{ - u32 val; - - if (dw_pcie_link_up(&pcie->pp)) - return 0; - - /* enable link training */ - val = readl(pcie->elbi + PCIE20_ELBI_SYS_CTRL); - val |= PCIE20_ELBI_SYS_CTRL_LT_ENABLE; - writel(val, pcie->elbi + PCIE20_ELBI_SYS_CTRL); - - return dw_pcie_wait_for_link(&pcie->pp); -} - -static void qcom_pcie_notify_client(struct qcom_pcie *dev, - enum qcom_pcie_event event) -{ - if (dev->event_reg && dev->event_reg->callback && - (dev->event_reg->events & event)) { - struct qcom_pcie_notify *notify = &dev->event_reg->notify; - notify->event = event; - notify->user = dev->event_reg->user; - pr_info("PCIe: callback RC%d for event %d.\n", - dev->rc_idx, event); - dev->event_reg->callback(notify); - - } else { - pr_info( - "PCIe: Client of RC%d does not have registered for event %d.\n", - dev->rc_idx, event); - } -} - -static irqreturn_t handle_link_down_irq(int irq, void *data) -{ - struct qcom_pcie *qcom_pcie = data; - - pr_info("PCIe: link_down IRQ for RC=%d\n", qcom_pcie->rc_idx); - - qcom_pcie_notify_client(qcom_pcie, QCOM_PCIE_EVENT_LINKDOWN); - return IRQ_HANDLED; -} - -static irqreturn_t handle_link_up_irq(int irq, void *data) -{ - struct qcom_pcie *qcom_pcie = data; - - pr_info("PCIe: link_up IRQ for RC=%d\n", qcom_pcie->rc_idx); - - return IRQ_HANDLED; -} - -/* PCIe wake-irq handler */ -static void handle_wake_func(struct work_struct *work) -{ - int ret; - struct qcom_pcie *pcie = container_of(work, struct qcom_pcie, - handle_wake_work); - struct pcie_port *pp = &pcie->pp; - - pci_lock_rescan_remove(); - if (pcie->enumerated) { - pr_info("PCIe: RC%d has been already enumerated\n", pcie->rc_idx); - pci_unlock_rescan_remove(); - return; - } - - if (!gpiod_get_value(mdm2ap_e911)) { - ret = dw_pcie_host_init_pm(pp); - - if (ret) - pr_err("PCIe: failed to enable RC%d upon wake request from the device\n", - pcie->rc_idx); - else { - pcie->enumerated = true; - pr_info("PCIe: enumerated RC%d successfully upon wake request from the device\n", - pcie->rc_idx); - } - } - - pci_unlock_rescan_remove(); -} - -static irqreturn_t qcom_pcie_wake_irq_handler(int irq, void *data) -{ - struct qcom_pcie *pcie = data; - - schedule_work(&pcie->handle_wake_work); - - return IRQ_HANDLED; -} - -/* PCIe global int handler */ -static irqreturn_t qcom_pcie_global_irq_handler(int irq, void *data) -{ - u32 status = 0; - unsigned long val, val_status, val_mask; - irqreturn_t ret = IRQ_HANDLED; - struct qcom_pcie *pcie = data; - - val_status = readl_relaxed(pcie->parf + PCIE20_INT_ALL_STATUS); - val_mask = readl_relaxed(pcie->parf + PCIE20_INT_ALL_MASK); - status = val_status & val_mask; - - /* Clear PARF status register */ - val = readl_relaxed(pcie->parf + PCIE20_INT_ALL_CLEAR) | status; - writel_relaxed(val, pcie->parf + PCIE20_INT_ALL_CLEAR); - /* ensure data is written to hw register */ - wmb(); - - if (status & PCIE_LINK_DOWN) - pr_info("PCIe: link_up IRQ for RC=%d\n", pcie->rc_idx); - if (status & PCIE_LINK_UP) - pr_info("PCIe: link_down IRQ for RC=%d\n", pcie->rc_idx); - - return ret; -} - -static void qcom_pcie_prog_viewport_cfg0(struct qcom_pcie *pcie, u32 busdev) -{ - struct pcie_port *pp = &pcie->pp; - - /* - * program and enable address translation region 0 (device config - * address space); region type config; - * axi config address range to device config address range - */ - writel(PCIE20_PLR_IATU_REGION_OUTBOUND | - PCIE20_PLR_IATU_REGION_INDEX(0), - pcie->dbi + PCIE20_PLR_IATU_VIEWPORT); - - writel(PCIE20_PLR_IATU_TYPE_CFG0, pcie->dbi + PCIE20_PLR_IATU_CTRL1); - writel(PCIE20_PLR_IATU_ENABLE, pcie->dbi + PCIE20_PLR_IATU_CTRL2); - writel(pp->cfg0_base, pcie->dbi + PCIE20_PLR_IATU_LBAR); - writel((pp->cfg0_base >> 32), pcie->dbi + PCIE20_PLR_IATU_UBAR); - writel((pp->cfg0_base + pp->cfg0_size - 1), - pcie->dbi + PCIE20_PLR_IATU_LAR); - writel(busdev, pcie->dbi + PCIE20_PLR_IATU_LTAR); - writel(0, pcie->dbi + PCIE20_PLR_IATU_UTAR); -} - -static void qcom_pcie_prog_viewport_mem2_outbound(struct qcom_pcie *pcie) -{ - struct pcie_port *pp = &pcie->pp; - - /* - * program and enable address translation region 2 (device resource - * address space); region type memory; - * axi device bar address range to device bar address range - */ - writel(PCIE20_PLR_IATU_REGION_OUTBOUND | - PCIE20_PLR_IATU_REGION_INDEX(2), - pcie->dbi + PCIE20_PLR_IATU_VIEWPORT); - - writel(PCIE20_PLR_IATU_TYPE_MEM, pcie->dbi + PCIE20_PLR_IATU_CTRL1); - writel(PCIE20_PLR_IATU_ENABLE, pcie->dbi + PCIE20_PLR_IATU_CTRL2); - writel(pp->mem_base, pcie->dbi + PCIE20_PLR_IATU_LBAR); - writel((pp->mem_base >> 32), pcie->dbi + PCIE20_PLR_IATU_UBAR); - writel(pp->mem_base + pp->mem_size - 1, - pcie->dbi + PCIE20_PLR_IATU_LAR); - writel(pp->mem_bus_addr, pcie->dbi + PCIE20_PLR_IATU_LTAR); - writel(upper_32_bits(pp->mem_bus_addr), - pcie->dbi + PCIE20_PLR_IATU_UTAR); - - /* 256B PCIE buffer setting */ - writel(0x1, pcie->dbi + PCIE20_AXI_MSTR_RESP_COMP_CTRL0); - writel(0x1, pcie->dbi + PCIE20_AXI_MSTR_RESP_COMP_CTRL1); -} - -static int qcom_pcie_get_resources_v0(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v0 *res = &pcie->res.v0; - struct device *dev = pcie->dev; - - res->vdda = devm_regulator_get(dev, "vdda"); - if (IS_ERR(res->vdda)) - return PTR_ERR(res->vdda); - - res->vdda_phy = devm_regulator_get(dev, "vdda_phy"); - if (IS_ERR(res->vdda_phy)) - return PTR_ERR(res->vdda_phy); - - res->vdda_refclk = devm_regulator_get(dev, "vdda_refclk"); - if (IS_ERR(res->vdda_refclk)) - return PTR_ERR(res->vdda_refclk); - - res->iface_clk = devm_clk_get(dev, "iface"); - if (IS_ERR(res->iface_clk)) - return PTR_ERR(res->iface_clk); - - res->core_clk = devm_clk_get(dev, "core"); - if (IS_ERR(res->core_clk)) - return PTR_ERR(res->core_clk); - - res->phy_clk = devm_clk_get(dev, "phy"); - if (IS_ERR(res->phy_clk)) - return PTR_ERR(res->phy_clk); - - res->aux_clk = devm_clk_get(dev, "aux"); - if (IS_ERR(res->aux_clk)) - return PTR_ERR(res->aux_clk); - - res->ref_clk = devm_clk_get(dev, "ref"); - if (IS_ERR(res->ref_clk)) - return PTR_ERR(res->ref_clk); - - res->pci_reset = devm_reset_control_get(dev, "pci"); - if (IS_ERR(res->pci_reset)) - return PTR_ERR(res->pci_reset); - - res->axi_reset = devm_reset_control_get(dev, "axi"); - if (IS_ERR(res->axi_reset)) - return PTR_ERR(res->axi_reset); - - res->ahb_reset = devm_reset_control_get(dev, "ahb"); - if (IS_ERR(res->ahb_reset)) - return PTR_ERR(res->ahb_reset); - - res->por_reset = devm_reset_control_get(dev, "por"); - if (IS_ERR(res->por_reset)) - return PTR_ERR(res->por_reset); - - res->phy_reset = devm_reset_control_get(dev, "phy"); - if (IS_ERR(res->phy_reset)) - return PTR_ERR(res->phy_reset); - - res->ext_reset = devm_reset_control_get(dev, "ext"); - if (IS_ERR(res->ext_reset)) - return PTR_ERR(res->ext_reset); - - if (of_property_read_u8(dev->of_node, "phy-tx0-term-offset", - &res->phy_tx0_term_offset)) - res->phy_tx0_term_offset = 0; - - return 0; -} - -static int qcom_pcie_get_resources_v1(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v1 *res = &pcie->res.v1; - struct device *dev = pcie->dev; - - res->vdda = devm_regulator_get(dev, "vdda"); - if (IS_ERR(res->vdda)) - return PTR_ERR(res->vdda); - - res->iface = devm_clk_get(dev, "iface"); - if (IS_ERR(res->iface)) - return PTR_ERR(res->iface); - - res->aux = devm_clk_get(dev, "aux"); - if (IS_ERR(res->aux)) - return PTR_ERR(res->aux); - - res->master_bus = devm_clk_get(dev, "master_bus"); - if (IS_ERR(res->master_bus)) - return PTR_ERR(res->master_bus); - - res->slave_bus = devm_clk_get(dev, "slave_bus"); - if (IS_ERR(res->slave_bus)) - return PTR_ERR(res->slave_bus); - - res->core = devm_reset_control_get(dev, "core"); - if (IS_ERR(res->core)) - return PTR_ERR(res->core); - - return 0; -} - -static int qcom_pcie_get_resources_v2(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v2 *res = &pcie->res.v2; - struct device *dev = pcie->dev; - - res->vdda = devm_regulator_get(dev, "vdda"); - if (IS_ERR(res->vdda)) - return PTR_ERR(res->vdda); - - res->vdda_phy = devm_regulator_get(dev, "vdda_phy"); - if (IS_ERR(res->vdda_phy)) - return PTR_ERR(res->vdda_phy); - - res->vdda_refclk = devm_regulator_get(dev, "vdda_refclk"); - if (IS_ERR(res->vdda_refclk)) - return PTR_ERR(res->vdda_refclk); - - res->ahb_clk = devm_clk_get(dev, "ahb"); - if (IS_ERR(res->ahb_clk)) - return PTR_ERR(res->ahb_clk); - - res->axi_m_clk = devm_clk_get(dev, "axi_m"); - if (IS_ERR(res->axi_m_clk)) - return PTR_ERR(res->axi_m_clk); - - res->axi_s_clk = devm_clk_get(dev, "axi_s"); - if (IS_ERR(res->axi_s_clk)) - return PTR_ERR(res->axi_s_clk); - - res->axi_m_reset = devm_reset_control_get(dev, "axi_m"); - if (IS_ERR(res->axi_m_reset)) - return PTR_ERR(res->axi_m_reset); - - res->axi_s_reset = devm_reset_control_get(dev, "axi_s"); - if (IS_ERR(res->axi_s_reset)) - return PTR_ERR(res->axi_s_reset); - - res->pipe_reset = devm_reset_control_get(dev, "pipe"); - if (IS_ERR(res->pipe_reset)) - return PTR_ERR(res->pipe_reset); - - res->axi_m_vmid_reset = devm_reset_control_get(dev, "axi_m_vmid"); - if (IS_ERR(res->axi_m_vmid_reset)) - return PTR_ERR(res->axi_m_vmid_reset); - - res->axi_s_xpu_reset = devm_reset_control_get(dev, "axi_s_xpu"); - if (IS_ERR(res->axi_s_xpu_reset)) - return PTR_ERR(res->axi_s_xpu_reset); - - res->parf_reset = devm_reset_control_get(dev, "parf"); - if (IS_ERR(res->parf_reset)) - return PTR_ERR(res->parf_reset); - - res->phy_reset = devm_reset_control_get(dev, "phy"); - if (IS_ERR(res->phy_reset)) - return PTR_ERR(res->phy_reset); - - res->axi_m_sticky_reset = devm_reset_control_get(dev, "axi_m_sticky"); - if (IS_ERR(res->axi_m_sticky_reset)) - return PTR_ERR(res->axi_m_sticky_reset); - - res->pipe_sticky_reset = devm_reset_control_get(dev, "pipe_sticky"); - if (IS_ERR(res->pipe_sticky_reset)) - return PTR_ERR(res->pipe_sticky_reset); - - res->pwr_reset = devm_reset_control_get(dev, "pwr"); - if (IS_ERR(res->pwr_reset)) - return PTR_ERR(res->pwr_reset); - - res->ahb_reset = devm_reset_control_get(dev, "ahb"); - if (IS_ERR(res->ahb_reset)) - return PTR_ERR(res->ahb_reset); - - res->phy_ahb_reset = devm_reset_control_get(dev, "phy_ahb"); - if (IS_ERR(res->phy_ahb_reset)) - return PTR_ERR(res->phy_ahb_reset); - - return 0; -} - - -static int qcom_pcie_get_resources_v3(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v3 *res = &pcie->res.v3; - struct device *dev = pcie->dev; - - res->vdda = devm_regulator_get(dev, "vdda"); - if (IS_ERR(res->vdda)) - return PTR_ERR(res->vdda); - - res->vdda_phy = devm_regulator_get(dev, "vdda_phy"); - if (IS_ERR(res->vdda_phy)) - return PTR_ERR(res->vdda_phy); - - res->vdda_refclk = devm_regulator_get(dev, "vdda_refclk"); - if (IS_ERR(res->vdda_refclk)) - return PTR_ERR(res->vdda_refclk); - - res->sys_noc_clk = devm_clk_get(dev, "sys_noc"); - if (IS_ERR(res->sys_noc_clk)) - return PTR_ERR(res->sys_noc_clk); - - res->axi_m_clk = devm_clk_get(dev, "axi_m"); - if (IS_ERR(res->axi_m_clk)) - return PTR_ERR(res->axi_m_clk); - - res->axi_s_clk = devm_clk_get(dev, "axi_s"); - if (IS_ERR(res->axi_s_clk)) - return PTR_ERR(res->axi_s_clk); - - res->ahb_clk = devm_clk_get(dev, "ahb"); - if (IS_ERR(res->ahb_clk)) - return PTR_ERR(res->ahb_clk); - - res->aux_clk = devm_clk_get(dev, "aux"); - if (IS_ERR(res->aux_clk)) - return PTR_ERR(res->aux_clk); - - if (pcie->is_gen3) { - res->axi_bridge_clk = devm_clk_get(dev, "axi_bridge"); - if (IS_ERR(res->axi_bridge_clk)) - return PTR_ERR(res->axi_bridge_clk); - - res->rchng_clk = devm_clk_get(dev, "rchng"); - if (IS_ERR(res->rchng_clk)) - res->rchng_clk = NULL; - } - - res->axi_m_reset = devm_reset_control_get(dev, "axi_m"); - if (IS_ERR(res->axi_m_reset)) - return PTR_ERR(res->axi_m_reset); - - res->axi_s_reset = devm_reset_control_get(dev, "axi_s"); - if (IS_ERR(res->axi_s_reset)) - return PTR_ERR(res->axi_s_reset); - - res->pipe_reset = devm_reset_control_get(dev, "pipe"); - if (IS_ERR(res->pipe_reset)) - return PTR_ERR(res->pipe_reset); - - res->axi_m_sticky_reset = devm_reset_control_get(dev, "axi_m_sticky"); - if (IS_ERR(res->axi_m_sticky_reset)) - return PTR_ERR(res->axi_m_sticky_reset); - - if (pcie->is_gen3) { - res->axi_s_sticky_reset = devm_reset_control_get(dev, "axi_s_sticky"); - if (IS_ERR(res->axi_s_sticky_reset)) - return PTR_ERR(res->axi_s_sticky_reset); - } - res->sticky_reset = devm_reset_control_get(dev, "sticky"); - if (IS_ERR(res->sticky_reset)) - return PTR_ERR(res->sticky_reset); - - res->ahb_reset = devm_reset_control_get(dev, "ahb"); - if (IS_ERR(res->ahb_reset)) - return PTR_ERR(res->ahb_reset); - - res->sleep_reset = devm_reset_control_get(dev, "sleep"); - if (IS_ERR(res->sleep_reset)) - return PTR_ERR(res->sleep_reset); - - return 0; -} - -static void qcom_pcie_deinit_v0(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v0 *res = &pcie->res.v0; - - clk_disable_unprepare(res->phy_clk); - reset_control_assert(res->phy_reset); - reset_control_assert(res->axi_reset); - reset_control_assert(res->ahb_reset); - reset_control_assert(res->por_reset); - reset_control_assert(res->pci_reset); - reset_control_assert(res->ext_reset); - clk_disable_unprepare(res->iface_clk); - clk_disable_unprepare(res->core_clk); - clk_disable_unprepare(res->aux_clk); - clk_disable_unprepare(res->ref_clk); - regulator_disable(res->vdda); - regulator_disable(res->vdda_phy); - regulator_disable(res->vdda_refclk); -} - -static int qcom_pcie_init_v0(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v0 *res = &pcie->res.v0; - struct device *dev = pcie->dev; - int ret; - - ret = reset_control_assert(res->ahb_reset); - if (ret) { - dev_err(dev, "cannot assert ahb reset\n"); - return ret; - } - - ret = regulator_enable(res->vdda); - if (ret) { - dev_err(dev, "cannot enable vdda regulator\n"); - return ret; - } - - ret = regulator_enable(res->vdda_refclk); - if (ret) { - dev_err(dev, "cannot enable vdda_refclk regulator\n"); - goto err_refclk; - } - - ret = regulator_enable(res->vdda_phy); - if (ret) { - dev_err(dev, "cannot enable vdda_phy regulator\n"); - goto err_vdda_phy; - } - - ret = reset_control_deassert(res->ext_reset); - if (ret) { - dev_err(dev, "cannot assert ext reset\n"); - goto err_reset_ext; - } - - ret = clk_prepare_enable(res->iface_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable iface clock\n"); - goto err_iface; - } - - ret = clk_prepare_enable(res->core_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable core clock\n"); - goto err_clk_core; - } - - ret = clk_prepare_enable(res->aux_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable aux clock\n"); - goto err_clk_aux; - } - - ret = clk_prepare_enable(res->ref_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable ref clock\n"); - goto err_clk_ref; - } - - ret = reset_control_deassert(res->ahb_reset); - if (ret) { - dev_err(dev, "cannot deassert ahb reset\n"); - goto err_deassert_ahb; - } - - writel_masked(pcie->parf + PCIE20_PARF_PHY_CTRL, BIT(0), 0); - - /* Set Tx termination offset */ - writel_masked(pcie->parf + PCIE20_PARF_PHY_CTRL, - PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK, - PHY_CTRL_PHY_TX0_TERM_OFFSET(res->phy_tx0_term_offset)); - - /* PARF programming */ - writel(PCS_DEEMPH_TX_DEEMPH_GEN1(0x18) | - PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(0x18) | - PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(0x22), - pcie->parf + PCIE20_PARF_PCS_DEEMPH); - writel(PCS_SWING_TX_SWING_FULL(0x78) | - PCS_SWING_TX_SWING_LOW(0x78), - pcie->parf + PCIE20_PARF_PCS_SWING); - writel(PHY_RX0_EQ(0x4), pcie->parf + PCIE20_PARF_CONFIG_BITS); - - /* Enable reference clock */ - writel_masked(pcie->parf + PCIE20_PARF_PHY_REFCLK, - REF_USE_PAD, REF_SSP_EN); - - - ret = reset_control_deassert(res->phy_reset); - if (ret) { - dev_err(dev, "cannot deassert phy reset\n"); - return ret; - } - - ret = reset_control_deassert(res->pci_reset); - if (ret) { - dev_err(dev, "cannot deassert pci reset\n"); - return ret; - } - - ret = reset_control_deassert(res->por_reset); - if (ret) { - dev_err(dev, "cannot deassert por reset\n"); - return ret; - } - - ret = reset_control_deassert(res->axi_reset); - if (ret) { - dev_err(dev, "cannot deassert axi reset\n"); - return ret; - } - - ret = clk_prepare_enable(res->phy_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable phy clock\n"); - goto err_deassert_ahb; - } - - /* wait for clock acquisition */ - usleep_range(1000, 1500); - if (pcie->force_gen1) { - writel_relaxed(((readl_relaxed( - pcie->dbi + PCIE20_LNK_CONTROL2_LINK_STATUS2) - & (~PCIE_CAP_TARGET_LINK_SPEED_MASK)) | SPEED_GEN1), - pcie->dbi + PCIE20_LNK_CONTROL2_LINK_STATUS2); - } - - qcom_pcie_prog_viewport_cfg0(pcie, MSM_PCIE_DEV_CFG_ADDR); - qcom_pcie_prog_viewport_mem2_outbound(pcie); - - return 0; - -err_deassert_ahb: - clk_disable_unprepare(res->ref_clk); -err_clk_ref: - clk_disable_unprepare(res->aux_clk); -err_clk_aux: - clk_disable_unprepare(res->core_clk); -err_clk_core: - clk_disable_unprepare(res->iface_clk); -err_iface: - reset_control_assert(res->ext_reset); -err_reset_ext: - regulator_disable(res->vdda_phy); -err_vdda_phy: - regulator_disable(res->vdda_refclk); -err_refclk: - regulator_disable(res->vdda); - - return ret; -} - -static void qcom_pcie_deinit_v1(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v1 *res = &pcie->res.v1; - - reset_control_assert(res->core); - clk_disable_unprepare(res->slave_bus); - clk_disable_unprepare(res->master_bus); - clk_disable_unprepare(res->iface); - clk_disable_unprepare(res->aux); - regulator_disable(res->vdda); -} - -static int qcom_pcie_init_v1(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v1 *res = &pcie->res.v1; - struct device *dev = pcie->dev; - int ret; - - ret = reset_control_deassert(res->core); - if (ret) { - dev_err(dev, "cannot deassert core reset\n"); - return ret; - } - - ret = clk_prepare_enable(res->aux); - if (ret) { - dev_err(dev, "cannot prepare/enable aux clock\n"); - goto err_res; - } - - ret = clk_prepare_enable(res->iface); - if (ret) { - dev_err(dev, "cannot prepare/enable iface clock\n"); - goto err_aux; - } - - ret = clk_prepare_enable(res->master_bus); - if (ret) { - dev_err(dev, "cannot prepare/enable master_bus clock\n"); - goto err_iface; - } - - ret = clk_prepare_enable(res->slave_bus); - if (ret) { - dev_err(dev, "cannot prepare/enable slave_bus clock\n"); - goto err_master; - } - - ret = regulator_enable(res->vdda); - if (ret) { - dev_err(dev, "cannot enable vdda regulator\n"); - goto err_slave; - } - - /* change DBI base address */ - writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR); - - if (IS_ENABLED(CONFIG_PCI_MSI)) { - u32 val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT); - - val |= BIT(31); - writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT); - } - - return 0; -err_slave: - clk_disable_unprepare(res->slave_bus); -err_master: - clk_disable_unprepare(res->master_bus); -err_iface: - clk_disable_unprepare(res->iface); -err_aux: - clk_disable_unprepare(res->aux); -err_res: - reset_control_assert(res->core); - - return ret; -} - -static void qcom_pcie_deinit_v2(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v2 *res = &pcie->res.v2; - - /* Assert pcie_pipe_ares */ - reset_control_assert(res->axi_m_reset); - reset_control_assert(res->axi_s_reset); - usleep_range(10000, 12000); /* wait 12ms */ - - reset_control_assert(res->pipe_reset); - reset_control_assert(res->pipe_sticky_reset); - reset_control_assert(res->phy_reset); - reset_control_assert(res->phy_ahb_reset); - usleep_range(10000, 12000); /* wait 12ms */ - - reset_control_assert(res->axi_m_sticky_reset); - reset_control_assert(res->pwr_reset); - reset_control_assert(res->ahb_reset); - usleep_range(10000, 12000); /* wait 12ms */ - - clk_disable_unprepare(res->ahb_clk); - clk_disable_unprepare(res->axi_m_clk); - clk_disable_unprepare(res->axi_s_clk); - regulator_disable(res->vdda); - regulator_disable(res->vdda_phy); - regulator_disable(res->vdda_refclk); -} - -static int qcom_pcie_enable_resources_v2(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v2 *res = &pcie->res.v2; - struct device *dev = pcie->dev; - int ret; - - ret = regulator_enable(res->vdda); - if (ret) { - dev_err(dev, "cannot enable vdda regulator\n"); - return ret; - } - - ret = regulator_enable(res->vdda_refclk); - if (ret) { - dev_err(dev, "cannot enable vdda_refclk regulator\n"); - goto err_refclk; - } - - ret = regulator_enable(res->vdda_phy); - if (ret) { - dev_err(dev, "cannot enable vdda_phy regulator\n"); - goto err_vdda_phy; - } - - ret = clk_prepare_enable(res->ahb_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable iface clock\n"); - goto err_ahb; - } - - ret = clk_prepare_enable(res->axi_m_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable core clock\n"); - goto err_clk_axi_m; - } - - ret = clk_prepare_enable(res->axi_s_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable phy clock\n"); - goto err_clk_axi_s; - } - - udelay(1); - - return 0; - -err_clk_axi_s: - clk_disable_unprepare(res->axi_m_clk); -err_clk_axi_m: - clk_disable_unprepare(res->ahb_clk); -err_ahb: - regulator_disable(res->vdda_phy); -err_vdda_phy: - regulator_disable(res->vdda_refclk); -err_refclk: - regulator_disable(res->vdda); - return ret; -} - -static void qcom_pcie_v2_reset(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v2 *res = &pcie->res.v2; - /* Assert pcie_pipe_ares */ - reset_control_assert(res->axi_m_reset); - reset_control_assert(res->axi_s_reset); - usleep_range(10000, 12000); /* wait 12ms */ - - reset_control_assert(res->pipe_reset); - reset_control_assert(res->pipe_sticky_reset); - reset_control_assert(res->phy_reset); - reset_control_assert(res->phy_ahb_reset); - usleep_range(10000, 12000); /* wait 12ms */ - - reset_control_assert(res->axi_m_sticky_reset); - reset_control_assert(res->pwr_reset); - reset_control_assert(res->ahb_reset); - usleep_range(10000, 12000); /* wait 12ms */ - - reset_control_deassert(res->phy_ahb_reset); - reset_control_deassert(res->phy_reset); - reset_control_deassert(res->pipe_reset); - reset_control_deassert(res->pipe_sticky_reset); - usleep_range(10000, 12000); /* wait 12ms */ - - reset_control_deassert(res->axi_m_reset); - reset_control_deassert(res->axi_m_sticky_reset); - reset_control_deassert(res->axi_s_reset); - reset_control_deassert(res->pwr_reset); - reset_control_deassert(res->ahb_reset); - usleep_range(10000, 12000); /* wait 12ms */ - wmb(); /* ensure data is written to hw register */ -} - -static int qcom_pcie_init_v2(struct qcom_pcie *pcie) -{ - int ret; - - qcom_pcie_v2_reset(pcie); - qcom_ep_reset_assert(pcie); - - ret = qcom_pcie_enable_resources_v2(pcie); - if (ret) - return ret; - - writel_masked(pcie->parf + PCIE20_PARF_PHY_CTRL, BIT(0), 0); - - writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR); - - writel(MST_WAKEUP_EN | SLV_WAKEUP_EN | MSTR_ACLK_CGC_DIS - | SLV_ACLK_CGC_DIS | CORE_CLK_CGC_DIS | - AUX_PWR_DET | L23_CLK_RMV_DIS | L1_CLK_RMV_DIS, - pcie->parf + PCIE20_PARF_SYS_CTRL); - writel(0, pcie->parf + PCIE20_PARF_Q2A_FLUSH); - writel(CMD_BME_VAL, pcie->dbi + PCIE20_COMMAND_STATUS); - writel(DBI_RO_WR_EN, pcie->dbi + PCIE20_MISC_CONTROL_1_REG); - writel(PCIE_CAP_LINK1_VAL, pcie->dbi + PCIE20_CAP_LINK_1); - - writel_masked(pcie->dbi + PCIE20_CAP_LINK_CAPABILITIES, - BIT(10) | BIT(11), 0); - writel(PCIE_CAP_CPL_TIMEOUT_DISABLE, pcie->dbi + - PCIE20_DEVICE_CONTROL2_STATUS2); - writel(LTSSM_EN, pcie->parf + PCIE20_PARF_LTSSM); - - return 0; -} - -static void qcom_pcie_deinit_v3(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v3 *res = &pcie->res.v3; - - clk_disable_unprepare(res->axi_m_clk); - clk_disable_unprepare(res->axi_s_clk); - clk_disable_unprepare(res->ahb_clk); - clk_disable_unprepare(res->aux_clk); - clk_disable_unprepare(res->sys_noc_clk); - regulator_disable(res->vdda); - regulator_disable(res->vdda_phy); - regulator_disable(res->vdda_refclk); -} - -static void qcom_pcie_v3_reset(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v3 *res = &pcie->res.v3; - /* Assert pcie_pipe_ares */ - reset_control_assert(res->pipe_reset); - reset_control_assert(res->sleep_reset); - reset_control_assert(res->sticky_reset); - reset_control_assert(res->axi_m_reset); - reset_control_assert(res->axi_s_reset); - reset_control_assert(res->ahb_reset); - reset_control_assert(res->axi_m_sticky_reset); - if (pcie->is_gen3) - reset_control_assert(res->axi_s_sticky_reset); - usleep_range(10000, 12000); /* wait 12ms */ - - reset_control_deassert(res->pipe_reset); - reset_control_deassert(res->sleep_reset); - reset_control_deassert(res->sticky_reset); - reset_control_deassert(res->axi_m_reset); - reset_control_deassert(res->axi_s_reset); - reset_control_deassert(res->ahb_reset); - reset_control_deassert(res->axi_m_sticky_reset); - if (pcie->is_gen3) - reset_control_deassert(res->axi_s_sticky_reset); - usleep_range(10000, 12000); /* wait 12ms */ - wmb(); /* ensure data is written to hw register */ -} - -static int qcom_pcie_enable_resources_v3(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v3 *res = &pcie->res.v3; - struct device *dev = pcie->dev; - int ret; - - ret = regulator_enable(res->vdda); - if (ret) { - dev_err(dev, "cannot enable vdda regulator\n"); - return ret; - } - - ret = regulator_enable(res->vdda_refclk); - if (ret) { - dev_err(dev, "cannot enable vdda_refclk regulator\n"); - goto err_refclk; - } - - ret = regulator_enable(res->vdda_phy); - if (ret) { - dev_err(dev, "cannot enable vdda_phy regulator\n"); - goto err_vdda_phy; - } - - ret = clk_prepare_enable(res->sys_noc_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable core clock\n"); - goto err_clk_sys_noc; - } - - ret = clk_prepare_enable(res->axi_m_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable core clock\n"); - goto err_clk_axi_m; - } - - ret = clk_set_rate(res->axi_m_clk, AXI_CLK_RATE); - if (ret) { - dev_err(dev, "MClk rate set failed (%d)\n", ret); - goto err_clk_axi_m; - } - - ret = clk_prepare_enable(res->axi_s_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable axi slave clock\n"); - goto err_clk_axi_s; - } - - ret = clk_set_rate(res->axi_s_clk, AXI_CLK_RATE); - if (ret) { - dev_err(dev, "MClk rate set failed (%d)\n", ret); - goto err_clk_axi_s; - } - - ret = clk_prepare_enable(res->ahb_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable ahb clock\n"); - goto err_clk_ahb; - } - - ret = clk_prepare_enable(res->aux_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable aux clock\n"); - goto err_clk_aux; - } - - if (pcie->is_gen3) { - ret = clk_prepare_enable(res->axi_bridge_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable axi_bridge clock\n"); - goto err_clk_axi_bridge; - } - - if (res->rchng_clk) { - ret = clk_prepare_enable(res->rchng_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable rchng_clk clock\n"); - goto err_clk_rchng; - } - - ret = clk_set_rate(res->rchng_clk, RCHNG_CLK_RATE); - if (ret) { - dev_err(dev, "rchng_clk rate set failed (%d)\n", - ret); - goto err_clk_rchng; - } - } - } - - - udelay(1); - - return 0; - -err_clk_rchng: - clk_disable_unprepare(res->axi_bridge_clk); -err_clk_axi_bridge: - clk_disable_unprepare(res->aux_clk); -err_clk_aux: - clk_disable_unprepare(res->ahb_clk); -err_clk_ahb: - clk_disable_unprepare(res->axi_s_clk); -err_clk_axi_s: - clk_disable_unprepare(res->axi_m_clk); -err_clk_axi_m: - clk_disable_unprepare(res->sys_noc_clk); -err_clk_sys_noc: - regulator_disable(res->vdda_phy); -err_vdda_phy: - regulator_disable(res->vdda_refclk); -err_refclk: - regulator_disable(res->vdda); - return ret; -} - - -static int qcom_pcie_init_v3(struct qcom_pcie *pcie) -{ - int ret, i; - - qcom_pcie_v3_reset(pcie); - if (!pcie->is_emulation) - qcom_ep_reset_assert(pcie); - - ret = qcom_pcie_enable_resources_v3(pcie); - if (ret) - return ret; - - writel(SLV_ADDR_SPACE_SZ, pcie->parf + PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE); - - ret = phy_power_on(pcie->phy); - if (ret) - return ret; - - writel_masked(pcie->parf + PCIE20_PARF_PHY_CTRL, BIT(0), 0); - - writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR); - - if (pcie->is_gen3) { - writel(DEVICE_TYPE_RC, pcie->parf + PCIE_PARF_DEVICE_TYPE); - writel(BYPASS | MSTR_AXI_CLK_EN | AHB_CLK_EN, - pcie->parf + PARF_MHI_CLOCK_RESET_CTRL); - writel(RXEQ_RGRDLESS_RXTS | - GEN3_ZRXDC_NONCOMPL, pcie->dbi + PCIE30_GEN3_RELATED_OFF); - } - - writel(MST_WAKEUP_EN | SLV_WAKEUP_EN | MSTR_ACLK_CGC_DIS - | SLV_ACLK_CGC_DIS | CORE_CLK_CGC_DIS | - AUX_PWR_DET | L23_CLK_RMV_DIS | L1_CLK_RMV_DIS, - pcie->parf + PCIE20_PARF_SYS_CTRL); - - writel(0, pcie->parf + PCIE20_PARF_Q2A_FLUSH); - if (pcie->is_gen3) - writel(BUS_MASTER_EN, pcie->dbi + PCIE20_COMMAND_STATUS); - else - writel(CMD_BME_VAL, pcie->dbi + PCIE20_COMMAND_STATUS); - writel(DBI_RO_WR_EN, pcie->dbi + PCIE20_MISC_CONTROL_1_REG); - writel(PCIE_CAP_LINK1_VAL, pcie->dbi + PCIE20_CAP_LINK_1); - - /* Configure PCIe link capabilities for ASPM */ - writel_masked(pcie->dbi + PCIE20_CAP_LINK_CAPABILITIES, - PCIE_ASPM_MASK << PCIE_ASPM_POS, - (pcie->cap_active_state_link_pm & PCIE_ASPM_MASK) << PCIE_ASPM_POS); - - writel(PCIE_CAP_CPL_TIMEOUT_DISABLE, pcie->dbi + - PCIE20_DEVICE_CONTROL2_STATUS2); - - if (pcie->is_gen3 && !pcie->force_gen2) - writel_relaxed(PCIE_CAP_CURR_DEEMPHASIS | SPEED_GEN3, - pcie->dbi + PCIE20_LNK_CONTROL2_LINK_STATUS2); - else if (pcie->force_gen2) - writel_relaxed(PCIE_CAP_CURR_DEEMPHASIS | SPEED_GEN2, - pcie->dbi + PCIE20_LNK_CONTROL2_LINK_STATUS2); - - if (pcie->force_gen1) { - writel_relaxed(((readl_relaxed( - pcie->dbi + PCIE20_LNK_CONTROL2_LINK_STATUS2) - & (~PCIE_CAP_TARGET_LINK_SPEED_MASK)) | SPEED_GEN1), - pcie->dbi + PCIE20_LNK_CONTROL2_LINK_STATUS2); - } - - writel(LTSSM_EN, pcie->parf + PCIE20_PARF_LTSSM); - if (pcie->is_emulation) - qcom_ep_reset_deassert(pcie); - - if (pcie->is_gen3) { - for (i = 0; i < 255; i++) - writel(0x0, pcie->parf + PARF_BDF_TO_SID_TABLE + (4 * i)); - writel( 0x4, pcie->dm_iatu + PCIE_ATU_CR1_OUTBOUND_6_GEN3); - writel( 0x90000000, pcie->dm_iatu + PCIE_ATU_CR2_OUTBOUND_6_GEN3); - writel( 0x0, pcie->dm_iatu + PCIE_ATU_LOWER_BASE_OUTBOUND_6_GEN3); - writel( 0x0, pcie->dm_iatu + PCIE_ATU_UPPER_BASE_OUTBOUND_6_GEN3); - writel( 0x00107FFFF, pcie->dm_iatu + PCIE_ATU_LIMIT_OUTBOUND_6_GEN3); - writel( 0x0, pcie->dm_iatu + PCIE_ATU_LOWER_TARGET_OUTBOUND_6_GEN3); - writel( 0x0, pcie->dm_iatu + PCIE_ATU_UPPER_TARGET_OUTBOUND_6_GEN3); - writel( 0x5, pcie->dm_iatu + PCIE_ATU_CR1_OUTBOUND_7_GEN3); - writel( 0x90000000, pcie->dm_iatu + PCIE_ATU_CR2_OUTBOUND_7_GEN3); - writel( 0x200000, pcie->dm_iatu + PCIE_ATU_LOWER_BASE_OUTBOUND_7_GEN3); - writel( 0x0, pcie->dm_iatu+ PCIE_ATU_UPPER_BASE_OUTBOUND_7_GEN3); - writel( 0x7FFFFF, pcie->dm_iatu + PCIE_ATU_LIMIT_OUTBOUND_7_GEN3); - writel( 0x0, pcie->dm_iatu + PCIE_ATU_LOWER_TARGET_OUTBOUND_7_GEN3); - writel( 0x0, pcie->dm_iatu + PCIE_ATU_UPPER_TARGET_OUTBOUND_7_GEN3); - } - - phy_power_off(pcie->phy); - return 0; -} - -static int qcom_pcie_link_up(struct pcie_port *pp) -{ - struct qcom_pcie *pcie = to_qcom_pcie(pp); - u32 val; - - val = readl_relaxed(pcie->elbi + PCIE20_ELBI_SYS_STTS); - if (val & XMLH_LINK_UP) - return 1; - return 0; -} - -static int qcom_pcie_host_init(struct pcie_port *pp) -{ - struct qcom_pcie *pcie = to_qcom_pcie(pp); - int ret; - - if (gpiod_get_value(mdm2ap_e911)) - return -EBUSY; - - if (!pcie->is_emulation) - qcom_ep_reset_assert(pcie); - - ret = pcie->ops->init(pcie); - if (ret) - goto err_deinit; - - ret = phy_power_on(pcie->phy); - if (ret) - goto err_deinit; - - if (IS_ENABLED(CONFIG_PCI_MSI)) { - if (!pp->msi_gicm_addr) - dw_pcie_msi_init(pp); - } - - if (!pcie->is_emulation) - qcom_ep_reset_deassert(pcie); - - ret = qcom_pcie_establish_link(pcie); - if (ret) - goto err; - - return 0; - -err: - if (pcie->compliance == 1) - return 0; - - if (!pcie->is_emulation) - qcom_ep_reset_assert(pcie); - - phy_power_off(pcie->phy); - -err_deinit: - if (pcie->compliance == 1) - return 0; - - pcie->ops->deinit(pcie); - return ret; -} - -static int qcom_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, - u32 *val) -{ - /* the device class is not reported correctly from the register */ - if (where == PCI_CLASS_REVISION && size == 4) { - *val = readl(pp->dbi_base + PCI_CLASS_REVISION); - *val &= 0xff; /* keep revision id */ - *val |= PCI_CLASS_BRIDGE_PCI << 16; - return PCIBIOS_SUCCESSFUL; - } - - return dw_pcie_cfg_read(pp->dbi_base + where, size, val); -} - -static struct pcie_host_ops qcom_pcie_dw_ops = { - .link_up = qcom_pcie_link_up, - .host_init = qcom_pcie_host_init, - .rd_own_conf = qcom_pcie_rd_own_conf, -}; - -static const struct qcom_pcie_ops ops_v0 = { - .get_resources = qcom_pcie_get_resources_v0, - .init = qcom_pcie_init_v0, - .deinit = qcom_pcie_deinit_v0, -}; - -static const struct qcom_pcie_ops ops_v1 = { - .get_resources = qcom_pcie_get_resources_v1, - .init = qcom_pcie_init_v1, - .deinit = qcom_pcie_deinit_v1, -}; - -static const struct qcom_pcie_ops ops_v2 = { - .get_resources = qcom_pcie_get_resources_v2, - .init = qcom_pcie_init_v2, - .deinit = qcom_pcie_deinit_v2, -}; - -static const struct qcom_pcie_ops ops_v3 = { - .get_resources = qcom_pcie_get_resources_v3, - .init = qcom_pcie_init_v3, - .deinit = qcom_pcie_deinit_v3, -}; - -static void qcom_slot_remove(int val) -{ - - struct pcie_port *pp; - pci_lock_rescan_remove(); - - if ((val >= 0) && (val < MAX_RC_NUM)) { - if (qcom_pcie_dev[val]) { - if (!qcom_pcie_dev[val]->enumerated) { - pr_notice("\nPCIe: RC%d already removed", val); - } else { - pr_notice("---> Removing %d", val); - pp = &qcom_pcie_dev[val]->pp; - pci_stop_root_bus(pp->pci_bus); - pci_remove_root_bus(pp->pci_bus); - if (!qcom_pcie_dev[val]->is_emulation) - qcom_ep_reset_assert(qcom_pcie_dev[val]); - phy_power_off(qcom_pcie_dev[val]->phy); - qcom_pcie_dev[val]->ops->deinit(qcom_pcie_dev[val]); - pp->pci_bus = NULL; - qcom_pcie_dev[val]->enumerated = false; - pr_notice(" ... done<---\n"); - } - } - } - pci_unlock_rescan_remove(); -} - -static void qcom_slot_rescan(int val) -{ - - int ret; - struct pcie_port *pp; - pci_lock_rescan_remove(); - - if ((val >= 0) && (val < MAX_RC_NUM)) { - if (qcom_pcie_dev[val]) { - if (qcom_pcie_dev[val]->enumerated) { - pr_notice("PCIe: RC%d already enumerated", val); - } else { - pp = &qcom_pcie_dev[val]->pp; - ret = dw_pcie_host_init_pm(pp); - if (!ret) - qcom_pcie_dev[val]->enumerated = true; - } - } - } - pci_unlock_rescan_remove(); - -} - -int qcom_pcie_rescan(void) -{ - int i, ret; - struct pcie_port *pp; - - for (i = 0; i < MAX_RC_NUM; i++) { - /* reset and enumerate the pcie devices */ - if (qcom_pcie_dev[i]) { - pr_notice("---> Initializing %d\n", i); - if (qcom_pcie_dev[i]->enumerated) - continue; - - pp = &qcom_pcie_dev[i]->pp; - ret = dw_pcie_host_init_pm(pp); - if (!ret) - qcom_pcie_dev[i]->enumerated = true; - pr_notice(" ... done<---\n"); - } - } - return 0; -} - -void qcom_pcie_remove_bus(void) -{ - int i; - - for (i = 0; i < MAX_RC_NUM; i++) { - if (qcom_pcie_dev[i]) { - struct pcie_port *pp; - struct qcom_pcie *pcie; - - pr_notice("---> Removing %d\n", i); - - pcie = qcom_pcie_dev[i]; - if (!pcie->enumerated) - continue; - - pp = &qcom_pcie_dev[i]->pp; - pci_stop_root_bus(pp->pci_bus); - pci_remove_root_bus(pp->pci_bus); - - if (!pcie->is_emulation) - qcom_ep_reset_assert(pcie); - phy_power_off(pcie->phy); - - qcom_pcie_dev[i]->ops->deinit(qcom_pcie_dev[i]); - pp->pci_bus = NULL; - pcie->enumerated = false; - pr_notice(" ... done<---\n"); - } - } -} - -static void handle_e911_func(struct work_struct *work) -{ - - int slot_id; - struct qcom_pcie *pcie = container_of(work, struct qcom_pcie, - handle_e911_work); - slot_id = pcie->slot_id; - - if (gpiod_get_value(mdm2ap_e911)) - qcom_slot_remove(slot_id); - else - qcom_slot_rescan(slot_id); -} - -static irqreturn_t handle_mdm2ap_e911_irq(int irq, void *data) -{ - struct qcom_pcie *pcie = data; - - schedule_work(&pcie->handle_e911_work); - - return IRQ_HANDLED; -} - -static ssize_t qcom_bus_rescan_store(struct bus_type *bus, const char *buf, - size_t count) -{ - unsigned long val; - - if (kstrtoul(buf, 0, &val) < 0) - return -EINVAL; - - if (gpiod_get_value(mdm2ap_e911)) - return -EBUSY; - - if (val) { - pci_lock_rescan_remove(); - qcom_pcie_rescan(); - pci_unlock_rescan_remove(); - } - return count; -} -static BUS_ATTR(rcrescan, (S_IWUSR|S_IWGRP), NULL, qcom_bus_rescan_store); - -static ssize_t qcom_bus_remove_store(struct bus_type *bus, const char *buf, - size_t count) -{ - unsigned long val; - - if (kstrtoul(buf, 0, &val) < 0) - return -EINVAL; - - if (val) { - pci_lock_rescan_remove(); - qcom_pcie_remove_bus(); - pci_unlock_rescan_remove(); - } - return count; -} -static BUS_ATTR(rcremove, (S_IWUSR|S_IWGRP), NULL, qcom_bus_remove_store); - -static ssize_t qcom_slot_rescan_store(struct bus_type *bus, const char *buf, - size_t count) -{ - unsigned long val; - - if (kstrtoul(buf, 0, &val) < 0) - return -EINVAL; - - qcom_slot_rescan(val); - - return count; -} -static BUS_ATTR(slot_rescan, (S_IWUSR|S_IWGRP), NULL, qcom_slot_rescan_store); - -static ssize_t qcom_slot_remove_store(struct bus_type *bus, const char *buf, - size_t count) -{ - unsigned long val; - - if (kstrtoul(buf, 0, &val) < 0) - return -EINVAL; - - qcom_slot_remove(val); - - return count; -} -static BUS_ATTR(slot_remove, (S_IWUSR|S_IWGRP), NULL, qcom_slot_remove_store); - -int qcom_pcie_register_event(struct qcom_pcie_register_event *reg) -{ - int ret = 0; - struct pci_dev *pci_dev; - struct pcie_port *pp; - struct qcom_pcie *qcom_pcie; - - if (!reg) { - pr_err("PCIe: Event registration is NULL\n"); - return -ENODEV; - } - - if (!reg->user) { - pr_err("PCIe: User of event registration is NULL\n"); - return -ENODEV; - } - pci_dev = (struct pci_dev *)reg->user; - pp = pci_dev->bus->sysdata; - qcom_pcie = to_qcom_pcie(pp); - - if (qcom_pcie) { - qcom_pcie->event_reg = reg; - pr_info("Event 0x%x is registered for RC %d\n", reg->events, - qcom_pcie->rc_idx); - } else { - pr_err("PCIe: did not find RC for pci endpoint device %p\n", - reg->user); - ret = -ENODEV; - } - - return ret; -} -EXPORT_SYMBOL(qcom_pcie_register_event); - -int qcom_pcie_deregister_event(struct qcom_pcie_register_event *reg) -{ - int ret = 0; - struct pci_dev *pci_dev; - struct pcie_port *pp; - struct qcom_pcie *qcom_pcie; - - if (!reg) { - pr_err("PCIe: Event deregistration is NULL\n"); - return -ENODEV; - } - - if (!reg->user) { - pr_err("PCIe: User of event deregistration is NULL\n"); - return -ENODEV; - } - pci_dev = (struct pci_dev *)reg->user; - pp = pci_dev->bus->sysdata; - qcom_pcie = to_qcom_pcie(pp); - - if (qcom_pcie) { - qcom_pcie->event_reg = NULL; - pr_info("Event is deregistered for RC %d\n", - qcom_pcie->rc_idx); - } else { - pr_err("PCIe: did not find RC for pci endpoint device %p\n", - reg->user); - ret = -ENODEV; - } - - return ret; -} -EXPORT_SYMBOL(qcom_pcie_deregister_event); - -static int pci_reboot_handler(struct notifier_block *this, - unsigned long event, void *ptr) -{ - pci_lock_rescan_remove(); - qcom_pcie_remove_bus(); - pci_unlock_rescan_remove(); - - return 0; -} - -static int qcom_pcie_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct resource *res; - struct qcom_pcie *pcie; - struct pcie_port *pp; - int ret; - uint32_t force_gen1 = 0; - uint32_t force_gen2 = 0; - struct device_node *np = pdev->dev.of_node; - u32 is_emulation = 0; - u32 use_delay = 0; - u32 link_retries_count = 0; - u32 slot_id = -1; - u32 compliance = 0; - static int rc_idx; - int i; - char irq_name[20]; - u32 soc_version_major; - int index = 0; - - pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); - if (!pcie) - return -ENOMEM; - - pcie->ops = (struct qcom_pcie_ops *)of_device_get_match_data(dev); - pcie->dev = dev; - - of_property_read_u32(np, "compliance", &compliance); - pcie->compliance = compliance; - - of_property_read_u32(np, "is_emulation", &is_emulation); - pcie->is_emulation = is_emulation; - - of_property_read_u32(np, "use_delay", &use_delay); - pcie->use_delay = use_delay; - - of_property_read_u32(np, "link_retries_count", &link_retries_count); - pcie->link_retries_count = link_retries_count; - - of_property_read_u32(np, "slot_id", &slot_id); - pcie->slot_id = slot_id; - - of_property_read_u32(np, "pcie-cap-active-state-link-pm", - &pcie->cap_active_state_link_pm); - - pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_HIGH); - if (IS_ERR(pcie->reset)) - return PTR_ERR(pcie->reset); - - of_property_read_u32(np, "force_gen1", &force_gen1); - pcie->force_gen1 = force_gen1; - - of_property_read_u32(np, "force_gen2", &force_gen2); - pcie->force_gen2 = force_gen2; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); - pcie->dbi = devm_ioremap_resource(dev, res); - if (IS_ERR(pcie->dbi)) - return PTR_ERR(pcie->dbi); - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi"); - pcie->elbi = devm_ioremap_resource(dev, res); - if (IS_ERR(pcie->elbi)) - return PTR_ERR(pcie->elbi); - - pcie->is_gen3 = 0; - if (of_device_is_compatible(pdev->dev.of_node, "qcom,pcie-ipq807x")) { - soc_version_major = read_ipq_soc_version_major(); - BUG_ON(soc_version_major <= 0); - index = of_property_match_string(dev->of_node, "phy-names", - "pciephy"); - if (index < 0) { - if (soc_version_major == 1) { - pcie->phy = devm_phy_optional_get(dev, "pciephy-gen2"); - if (IS_ERR(pcie->phy)) - return PTR_ERR(pcie->phy); - pcie->is_gen3 = 0; - } else if (soc_version_major == 2) { - pcie->phy = devm_phy_optional_get(dev, "pciephy-gen3"); - if (IS_ERR(pcie->phy)) - return PTR_ERR(pcie->phy); - pcie->is_gen3 = 1; - } else { - dev_err(dev, "missing phy-names\n"); - return index; - } - } else { - pcie->phy = devm_phy_optional_get(dev, "pciephy"); - if (IS_ERR(pcie->phy)) - return PTR_ERR(pcie->phy); - pcie->is_gen3 = 0; - } - } else if (of_device_is_compatible(pdev->dev.of_node, "qcom,pcie-ipq6018")) { - if (!pcie->is_emulation) { - pcie->phy = devm_phy_optional_get(dev, "pciephy"); - if (IS_ERR(pcie->phy)) - return PTR_ERR(pcie->phy); - } - pcie->is_gen3 = 1; - } else if (of_device_is_compatible(pdev->dev.of_node, - "qcom,pcie-ipq5018")) { - if (!pcie->is_emulation) { - pcie->phy = devm_phy_optional_get(dev, "pciephy"); - if (IS_ERR(pcie->phy)) - return PTR_ERR(pcie->phy); - } - pcie->is_gen3 = 1; - } - - if (pcie->is_gen3) { - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dm_iatu"); - pcie->dm_iatu = devm_ioremap_resource(dev, res); - if (IS_ERR(pcie->dm_iatu)) - return PTR_ERR(pcie->dm_iatu); - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "parf"); - if (res) - res->end += PCIE_V2_PARF_SIZE; - pcie->parf = devm_ioremap_resource(dev, res); - if (IS_ERR(pcie->parf)) - return PTR_ERR(pcie->parf); - } else { - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "parf"); - pcie->parf = devm_ioremap_resource(dev, res); - if (IS_ERR(pcie->parf)) - return PTR_ERR(pcie->parf); - } - - ret = pcie->ops->get_resources(pcie); - if (ret) - return ret; - - pp = &pcie->pp; - pp->dev = dev; - pp->dbi_base = pcie->dbi; - pp->dm_iatu = pcie->dm_iatu; - pp->is_gen3 = pcie->is_gen3; - pp->use_delay = pcie->use_delay; - pp->link_retries_count = pcie->link_retries_count; - pp->root_bus_nr = -1; - pp->ops = &qcom_pcie_dw_ops; - - pcie->mdm2ap_e911_irq = platform_get_irq_byname(pdev, - "mdm2ap_e911"); - if (pcie->mdm2ap_e911_irq >= 0) { - mdm2ap_e911 = devm_gpiod_get_optional(&pdev->dev, "e911", - GPIOD_IN); - - if (IS_ERR(mdm2ap_e911)) { - pr_err("requesting for e911 gpio failed %ld\n", - PTR_ERR(mdm2ap_e911)); - return PTR_ERR(mdm2ap_e911); - } - - INIT_WORK(&pcie->handle_e911_work, handle_e911_func); - - ret = devm_request_irq(&pdev->dev, pcie->mdm2ap_e911_irq, - handle_mdm2ap_e911_irq, - IRQ_TYPE_EDGE_BOTH, "mdm2ap_e911", - pcie); - - if (ret) { - dev_err(&pdev->dev, "Unable to request mdm2ap_e911 irq\n"); - return ret; - } - - pcie->pci_reboot_notifier.notifier_call = pci_reboot_handler; - ret = register_reboot_notifier(&pcie->pci_reboot_notifier); - if (ret) { - pr_warn("%s: Failed to register notifier (%d)\n", - __func__, ret); - return ret; - } - } - - pcie->link_down_irq = platform_get_irq_byname(pdev, - "int_link_down"); - if (pcie->link_down_irq >= 0) { - ret = devm_request_irq(&pdev->dev, pcie->link_down_irq, - handle_link_down_irq, - IRQF_TRIGGER_RISING, "pci_link_down", - pcie); - } - - pcie->link_up_irq = platform_get_irq_byname(pdev, "int_link_up"); - if (pcie->link_up_irq >= 0) { - ret = devm_request_irq(&pdev->dev, pcie->link_up_irq, - handle_link_up_irq, - IRQF_TRIGGER_RISING, "pci_link_up", - pcie); - } - - pcie->global_irq = platform_get_irq_byname(pdev, "global"); - if (pcie->global_irq >= 0) { - ret = devm_request_irq(&pdev->dev, pcie->global_irq, - qcom_pcie_global_irq_handler, - IRQF_TRIGGER_RISING, "qcom-pcie-global", pcie); - if (ret) { - dev_err(&pdev->dev, "cannot request global irq\n"); - return ret; - } - } - - pp->msi_gicm_addr = 0; - pp->msi_gicm_base = 0; - of_property_read_u32(np, "qcom,msi-gicm-addr", &pp->msi_gicm_addr); - of_property_read_u32(np, "qcom,msi-gicm-base", &pp->msi_gicm_base); - - if (IS_ENABLED(CONFIG_PCI_MSI)) { - pp->msi_irq = platform_get_irq_byname(pdev, "msi"); - if (pp->msi_irq < 0) - return pp->msi_irq; - - ret = devm_request_irq(dev, pp->msi_irq, - qcom_pcie_msi_irq_handler, - IRQF_SHARED, "qcom-pcie-msi", pp); - if (ret) { - dev_err(dev, "cannot request msi irq\n"); - return ret; - } - for (i = 0; i < MAX_MSI_IRQS; i++) { - snprintf(irq_name, sizeof(irq_name), "msi_%d", i); - pp->msi[i] = platform_get_irq_byname(pdev, irq_name); - if (pp->msi[i] < 0) - break; - } - } - - ret = phy_init(pcie->phy); - if (ret) - return ret; - - pcie->wake_irq = platform_get_irq_byname(pdev, "wake_gpio"); - - ret = dw_pcie_host_init(pp); - - if (ret) { - if (pcie->wake_irq < 0) { - dev_err(dev, "cannot initialize host\n"); - return ret; - } - pr_info("PCIe: RC%d is not enabled during bootup;it will be enumerated upon client request\n", - rc_idx); - } else { - pcie->enumerated = true; - pr_info("PCIe: RC%d enabled during bootup\n", rc_idx); - } - - if (pcie->wake_irq >= 0) { - INIT_WORK(&pcie->handle_wake_work, handle_wake_func); - - ret = devm_request_irq(&pdev->dev, pcie->wake_irq, - qcom_pcie_wake_irq_handler, - IRQF_TRIGGER_FALLING, "qcom-pcie-wake", pcie); - if (ret) { - dev_err(&pdev->dev, "Unable to request wake irq\n"); - return ret; - } - } - - /* - ####ipq-4019, add pcie_wake control - static irqreturn_t quectel_pcie_wake_irq(int irq, void *data) - { - return IRQ_WAKE_THREAD; - } - - static irqreturn_t quectel_pcie_wake_thread_irq(int irq, void *data) - { - struct qcom_pcie *pcie = data; - int val = gpiod_get_value(pcie->quectel_pwake); - struct dw_pcie *pci = ep->pci; - - pr_info("pwake val: %d\n", val); - if (val){ - //up: rescan - pci_lock_rescan_remove(); - qcom_pcie_rescan(); - pci_unlock_rescan_remove(); - }else{ - //down: remove - pci_lock_rescan_remove(); - qcom_pcie_remove_bus(); - pci_unlock_rescan_remove(); - } - return IRQ_HANDLED; - } - - pcie->quectel_pwake = devm_gpiod_get_index(dev, "pcie-wake", 0, GPIOD_IN); - if (IS_ERR(pcie->quectel_pwake)) { - dev_err(&pdev->dev, "Please set pcie-wake gpio in DTS\n"); - return PTR_ERR(pcie->quectel_pwake); - } - - pcie->quectel_pwake_irq = gpiod_to_irq(pcie->quectel_pwake); - - ret = devm_request_threaded_irq(&pdev->dev, pcie->quectel_pwake_irq, - quectel_pcie_wake_irq, - quectel_pcie_wake_thread_irq, - IRQF_TRIGGER_RISING | - IRQF_TRIGGER_FALLING | IRQF_NO_SUSPEND, - "quectel-pcie-wake", pcie); - - enable_irq_wake(pcie->quectel_pcie_wake); - */ - - platform_set_drvdata(pdev, pcie); - - if (!rc_idx) { - ret = bus_create_file(&pci_bus_type, &bus_attr_rcrescan); - if (ret != 0) { - dev_err(&pdev->dev, - "Failed to create sysfs rcrescan file\n"); - return ret; - } - - ret = bus_create_file(&pci_bus_type, &bus_attr_rcremove); - if (ret != 0) { - dev_err(&pdev->dev, - "Failed to create sysfs rcremove file\n"); - return ret; - } - } - - /* create sysfs files to support slot rescan and remove*/ - if (!rc_idx) { - ret = bus_create_file(&pci_bus_type, &bus_attr_slot_rescan); - if (ret != 0) { - dev_err(&pdev->dev, - "Failed to create sysfs rcrescan file\n"); - return ret; - } - - ret = bus_create_file(&pci_bus_type, &bus_attr_slot_remove); - if (ret != 0) { - dev_err(&pdev->dev, - "Failed to create sysfs rcremove file\n"); - return ret; - } - } - - pcie->rc_idx = rc_idx; - qcom_pcie_dev[rc_idx++] = pcie; - - return 0; -} - -static int qcom_pcie_remove(struct platform_device *pdev) -{ - struct qcom_pcie *pcie = platform_get_drvdata(pdev); - - if (!pcie->is_emulation) - qcom_ep_reset_assert(pcie); - - phy_power_off(pcie->phy); - phy_exit(pcie->phy); - pcie->ops->deinit(pcie); - - return 0; -} - -static void qcom_pcie_fixup_final(struct pci_dev *dev) -{ - int cap, err; - u16 ctl, reg_val; - - cap = pci_pcie_cap(dev); - if (!cap) - return; - - err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); - - if (err) - return; - - reg_val = ctl; - - if (((reg_val & PCIE20_MRRS_MASK) >> 12) > 1) - reg_val = (reg_val & ~(PCIE20_MRRS_MASK)) | PCIE20_MRRS(0x1); - - if (((ctl & PCIE20_MPS_MASK) >> 5) > 1) - reg_val = (reg_val & ~(PCIE20_MPS_MASK)) | PCIE20_MPS(0x1); - - err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, reg_val); - - if (err) - pr_err("pcie config write failed %d\n", err); -} -DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, qcom_pcie_fixup_final); - -static const struct of_device_id qcom_pcie_match[] = { - { .compatible = "qcom,pcie-ipq8064", .data = &ops_v0 }, - { .compatible = "qcom,pcie-apq8064", .data = &ops_v0 }, - { .compatible = "qcom,pcie-apq8084", .data = &ops_v1 }, - { .compatible = "qcom,pcie-ipq4019", .data = &ops_v2 }, - { .compatible = "qcom,pcie-ipq807x", .data = &ops_v3 }, - { .compatible = "qcom,pcie-ipq6018", .data = &ops_v3 }, - { .compatible = "qcom,pcie-ipq5018", .data = &ops_v3 }, - { } -}; -MODULE_DEVICE_TABLE(of, qcom_pcie_match); - -static struct platform_driver qcom_pcie_driver = { - .probe = qcom_pcie_probe, - .remove = qcom_pcie_remove, - .driver = { - .name = "qcom-pcie", - .of_match_table = qcom_pcie_match, - }, -}; - -module_platform_driver(qcom_pcie_driver); - -MODULE_AUTHOR("Stanimir Varbanov "); -MODULE_DESCRIPTION("Qualcomm PCIe root complex driver"); -MODULE_LICENSE("GPL v2"); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/Kconfig b/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/Kconfig deleted file mode 100644 index f6480336a..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -menu "SIPA modules" - -config SPRD_SIPA - bool "sipa ipa" - default n - help - sipa is a module for spreadtrum ip packet accelator driver. - -endmenu diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/Makefile b/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/Makefile deleted file mode 100644 index 1d5101bf8..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -EXTRA_CFLAGS += -Wno-error -Wno-packed-bitfield-compat -ccflags-y += -DCONFIG_SPRD_SIPA -obj-y += sipa_core.o sipa_skb_send.o sipa_skb_recv.o \ - sipa_nic.o sipa_debugfs.o sipa_dele_cmn.o \ - sipa_eth.o sipa_dummy.o -obj-y += sipa_phy_v0/ diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_core.c b/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_core.c deleted file mode 100644 index bcde7e519..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_core.c +++ /dev/null @@ -1,333 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note. - * - * UNISOC 'virt sipa' driver - * - * Qingsheng.Li - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License v2 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 the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sipa.h" -#include "../include/sprd_pcie_ep_device.h" -#include "../include/sipc.h" -#include "sipa_core.h" - -#define DRV_NAME "virt_sipa" - -struct sipa_core *sipa_ctrl; - -struct sipa_core *sipa_get_ctrl_pointer(void) -{ - return sipa_ctrl; -} -EXPORT_SYMBOL(sipa_get_ctrl_pointer); - -static void sipa_notify_sender_flow_ctrl(struct work_struct *work) -{ - struct sipa_core *sipa_ctrl = container_of(work, struct sipa_core, - flow_ctrl_work); - - if (sipa_ctrl->sender && sipa_ctrl->sender->free_notify_net) - wake_up(&sipa_ctrl->sender->free_waitq); -} - -static int sipa_init_cmn_fifo(struct sipa_core *ipa, - enum sipa_cmn_fifo_index id) -{ - size_t size; - dma_addr_t dma_addr; - struct sipa_cmn_fifo_cfg_tag *cmn_fifo; - - cmn_fifo = &ipa->cmn_fifo_cfg[id]; - cmn_fifo->fifo_id = id; - cmn_fifo->dst = SIPA_TERM_VCP; - cmn_fifo->cur = SIPA_TERM_PCIE0; - size = cmn_fifo->tx_fifo.depth * - sizeof(struct sipa_node_description_tag); - cmn_fifo->tx_fifo.virtual_addr = dma_alloc_coherent(ipa->pci_dev, size, - &dma_addr, - GFP_KERNEL); - if (!cmn_fifo->tx_fifo.virtual_addr) - return -ENOMEM; - cmn_fifo->tx_fifo.dma_ptr = dma_addr; - memset(cmn_fifo->tx_fifo.virtual_addr, 0, size); - pr_info("comfifo%d tx_fifo addr-0x%lx\n", id, (long unsigned int)cmn_fifo->tx_fifo.virtual_addr); - - cmn_fifo->tx_fifo.fifo_base_addr_l = lower_32_bits(dma_addr); - cmn_fifo->tx_fifo.fifo_base_addr_h = 0x2; - - size = cmn_fifo->rx_fifo.depth * - sizeof(struct sipa_node_description_tag); - cmn_fifo->rx_fifo.virtual_addr = dma_alloc_coherent(ipa->pci_dev, size, - &dma_addr, - GFP_KERNEL); - if (!cmn_fifo->rx_fifo.virtual_addr) - return -ENOMEM; - cmn_fifo->rx_fifo.dma_ptr = dma_addr; - memset(cmn_fifo->rx_fifo.virtual_addr, 0, size); - pr_info("comfifo%d rx_fifo addr-0x%lx\n", id, (long unsigned int)cmn_fifo->rx_fifo.virtual_addr); - - cmn_fifo->rx_fifo.fifo_base_addr_l = lower_32_bits(dma_addr); - cmn_fifo->rx_fifo.fifo_base_addr_h = 0x2; - - return 0; -} - -static void sipa_free_cmn_fifo(struct sipa_core *ipa, enum sipa_cmn_fifo_index id) -{ - size_t size; - struct sipa_cmn_fifo_cfg_tag *cmn_fifo; - - cmn_fifo = &ipa->cmn_fifo_cfg[id]; - size = cmn_fifo->tx_fifo.depth * sizeof(struct sipa_node_description_tag); - dma_free_coherent(ipa->dev, size, cmn_fifo->tx_fifo.virtual_addr, cmn_fifo->tx_fifo.dma_ptr); - size = cmn_fifo->rx_fifo.depth * sizeof(struct sipa_node_description_tag); - dma_free_coherent(ipa->dev, size, cmn_fifo->rx_fifo.virtual_addr, cmn_fifo->rx_fifo.dma_ptr); -} - -static void sipa_init_ep(struct sipa_core *ipa) -{ - struct sipa_endpoint *ep = &ipa->ep; - - ep->send_fifo = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_UL]; - ep->recv_fifo = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_DL]; -} - -#ifdef SPRD_PCIE_USE_DTS -static int sipa_parse_dts_configuration(struct platform_device *pdev, - struct sipa_core *ipa) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *cmn_fifo; - - ipa->reg_res = platform_get_resource_byname(pdev, - IORESOURCE_MEM, "ipa-base"); - if (!ipa->reg_res) { - dev_err(&pdev->dev, "get ipa-base res fail\n"); - return -EINVAL; - } - - cmn_fifo = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_DL]; - ret = of_property_read_u32(pdev->dev.of_node, "pcie-dl-tx-fifo-depth", - &cmn_fifo->tx_fifo.depth); - if (ret) { - dev_err(&pdev->dev, - "get pcie-dl-tx-fifo-depth ret = %d\n", ret); - return ret; - } - - ret = of_property_read_u32(pdev->dev.of_node, "pcie-dl-rx-fifo-depth", - &cmn_fifo->rx_fifo.depth); - if (ret) { - dev_err(&pdev->dev, - "get pcie-dl-rx-fifo-depth ret = %d\n", ret); - return ret; - } - - cmn_fifo = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_UL]; - ret = of_property_read_u32(pdev->dev.of_node, "pcie-ul-tx-fifo-depth", - &cmn_fifo->tx_fifo.depth); - if (ret) { - dev_err(&pdev->dev, - "get pcie-ul-tx-fifo-depth ret = %d\n", ret); - return ret; - } - - ret = of_property_read_u32(pdev->dev.of_node, "pcie-ul-rx-fifo-depth", - &cmn_fifo->rx_fifo.depth); - if (ret) { - dev_err(&pdev->dev, - "get pcie-ul-rx-fifo-depth ret = %d\n", ret); - return ret; - } - - return 0; -} -#else -static struct resource ipa_res = { - .start = 0x2e000000, - .end = 0x2e000000 + 0x2000 -1, - .flags = IORESOURCE_MEM, -}; - -static int sipa_parse_dts_configuration(struct platform_device *pdev, - struct sipa_core *ipa) -{ - struct sipa_cmn_fifo_cfg_tag *cmn_fifo; - ipa->reg_res = &ipa_res; - cmn_fifo = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_DL]; - cmn_fifo->tx_fifo.depth = 4096; - cmn_fifo->rx_fifo.depth = 4096; - cmn_fifo = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_UL]; - cmn_fifo->tx_fifo.depth = 4096; - cmn_fifo->rx_fifo.depth = 4096; - return 0; -} -#endif - -static int sipa_plat_drv_probe(struct platform_device *pdev) -{ - int ret; - struct sipa_core *ipa; - struct device *dev = &pdev->dev; - struct device *pci_dev; - - pci_dev = (struct device *)dev_get_drvdata(dev); - if(!pci_dev) - return -1; - - ipa = devm_kzalloc(dev, sizeof(*ipa), GFP_KERNEL); - if (!ipa) - return -ENOMEM; - - sipa_ctrl = ipa; - ipa->dev = dev; - ipa->pci_dev = pci_dev; - ipa->pcie_mem_offset = SIPA_PCIE_MEM_OFFSET; - dev_set_drvdata(dev, ipa); - ret = sipa_parse_dts_configuration(pdev, ipa); - if (ret) - return ret; - - ret = sipa_init_cmn_fifo(ipa, SIPA_FIFO_PCIE_DL); - if (ret) - return ret; - - ret = sipa_init_cmn_fifo(ipa, SIPA_FIFO_PCIE_UL); - if (ret) - return ret; - - sipa_init_ep(ipa); - - sipa_fifo_ops_init(&ipa->hal_ops); - INIT_WORK(&ipa->flow_ctrl_work, sipa_notify_sender_flow_ctrl); - - create_sipa_skb_receiver(&ipa->ep, &ipa->receiver); - create_sipa_skb_sender(&ipa->ep, &ipa->sender); - device_init_wakeup(dev, true); - - sipa_create_smsg_channel(ipa); - - sprd_ep_dev_register_irq_handler(PCIE_EP_MODEM, PCIE_MSI_IPA, - (irq_handler_t)sipa_int_callback_func, - (void *)ipa); - sipa_init_debugfs(ipa); - - return 0; -} - -extern void destroy_sipa_skb_receiver(struct sipa_skb_receiver *receiver); -extern void destroy_sipa_skb_sender(struct sipa_skb_sender *sender); - -static int sipa_plat_drv_remove(struct platform_device *pdev) -{ - struct sipa_core *ipa; - - ipa = dev_get_drvdata(&pdev->dev); - smsg_ch_close(SIPC_ID_MINIAP, SMSG_CH_COMM_SIPA, 1000); - if(ipa->smsg_thread){ - kthread_stop(ipa->smsg_thread); - ipa->smsg_thread = NULL; - } - destroy_sipa_skb_sender(ipa->sender); - destroy_sipa_skb_receiver(ipa->receiver); - cancel_work_sync(&ipa->flow_ctrl_work); - mdelay(1000); - sipa_free_cmn_fifo(ipa, SIPA_FIFO_PCIE_UL); - sipa_free_cmn_fifo(ipa, SIPA_FIFO_PCIE_DL); - if (!IS_ERR_OR_NULL(ipa->dentry)) - debugfs_remove_recursive(ipa->dentry); - devm_kfree(&pdev->dev, ipa); - platform_set_drvdata(pdev, NULL); - return 0; -} - -#ifdef SPRD_PCIE_USE_DTS -static const struct of_device_id sipa_plat_drv_match[] = { - { .compatible = "sprd,virt-sipa"}, -}; -#endif - -static struct platform_driver sipa_plat_drv = { - .probe = sipa_plat_drv_probe, - .remove = sipa_plat_drv_remove, - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, -#ifdef SPRD_PCIE_USE_DTS - .of_match_table = sipa_plat_drv_match, -#endif - }, -}; - -#ifndef SPRD_PCIE_USE_DTS -static struct platform_device *sipa_plat_dev; -static int sipa_core_platform_device_reigster(struct device *dev) -{ - int retval = -ENOMEM; - - sipa_plat_dev = platform_device_alloc("virt_sipa", -1); - if (!sipa_plat_dev) - return retval; - - sipa_plat_dev->dev.dma_mask = dev->dma_mask; - sipa_plat_dev->dev.coherent_dma_mask = dev->coherent_dma_mask; - sipa_plat_dev->dev.archdata = dev->archdata; - dev_set_drvdata(&sipa_plat_dev->dev, dev); - retval = platform_device_add(sipa_plat_dev); - if (retval < 0) - platform_device_put(sipa_plat_dev); - - return retval; -} -#endif - -int sipa_module_init(struct device *dev) -{ -#ifndef SPRD_PCIE_USE_DTS - sipa_core_platform_device_reigster(dev); -#endif - return platform_driver_register(&sipa_plat_drv); -} -EXPORT_SYMBOL(sipa_module_init); - -void sipa_module_exit(void) -{ - platform_driver_unregister(&sipa_plat_drv); -#ifndef SPRD_PCIE_USE_DTS - platform_device_unregister(sipa_plat_dev); - #endif -} -EXPORT_SYMBOL(sipa_module_exit); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_core.h b/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_core.h deleted file mode 100644 index f67853bd1..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_core.h +++ /dev/null @@ -1,519 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#ifndef _SIPA_CORE_H_ -#define _SIPA_CORE_H_ - -#include -#include -#include -#include -#include -#include -#include - -enum sipa_cmn_fifo_index { - SIPA_FIFO_PCIE_DL, - SIPA_FIFO_PCIE_UL, - SIPA_FIFO_MAX, -}; - -enum sipa_irq_evt_type { - SIPA_IRQ_TX_FIFO_THRESHOLD_SW = BIT(22), - SIPA_IRQ_EXIT_FLOW_CTRL = BIT(20), - SIPA_IRQ_ENTER_FLOW_CTRL = BIT(19), - SIPA_IRQ_TXFIFO_FULL_INT = BIT(18), - SIPA_IRQ_TXFIFO_OVERFLOW = BIT(17), - SIPA_IRQ_ERRORCODE_IN_TX_FIFO = BIT(16), - SIPA_IRQ_INTR_BIT = BIT(15), - SIPA_IRQ_THRESHOLD = BIT(14), - SIPA_IRQ_DELAY_TIMER = BIT(13), - SIPA_IRQ_DROP_PACKT_OCCUR = BIT(12), - - SIPA_IRQ_ERROR = 0x0, -}; - -#define SIPA_FIFO_THRESHOLD_IRQ_EN BIT(1) -#define SIPA_FIFO_DELAY_TIMER_IRQ_EN BIT(0) - -#define SIPA_PCIE_MEM_OFFSET 0x200000000ULL - -enum sipa_nic_status_e { - NIC_OPEN, - NIC_CLOSE -}; - -#define SIPA_RECV_EVT (SIPA_IRQ_INTR_BIT | SIPA_IRQ_THRESHOLD | \ - SIPA_IRQ_DELAY_TIMER | SIPA_IRQ_TX_FIFO_THRESHOLD_SW) - -#define SIPA_RECV_WARN_EVT (SIPA_IRQ_TXFIFO_FULL_INT | SIPA_IRQ_TXFIFO_OVERFLOW) - -#define SMSG_FLG_DELE_REQUEST 0x1 -#define SMSG_FLG_DELE_RELEASE 0x2 - -typedef void (*sipa_irq_notify_cb)(void *priv, - enum sipa_irq_evt_type evt, - u32 data); - -struct sipa_node_description_tag { - /*soft need to set*/ - u64 address : 40; - /*soft need to set*/ - u32 length : 20; - /*soft need to set*/ - u16 offset : 12; - /*soft need to set*/ - u8 net_id; - /*soft need to set*/ - u8 src : 5; - /*soft need to set*/ - u8 dst : 5; - u8 prio : 3; - u8 bear_id : 7; - /*soft need to set*/ - u8 intr : 1; - /*soft need to set*/ - u8 indx : 1; - u8 err_code : 4; - u32 reserved : 22; -} __attribute__((__packed__)); - -struct sipa_cmn_fifo_params { - u32 tx_intr_delay_us; - u32 tx_intr_threshold; - bool flowctrl_in_tx_full; - u32 flow_ctrl_cfg; - u32 flow_ctrl_irq_mode; - u32 tx_enter_flowctrl_watermark; - u32 tx_leave_flowctrl_watermark; - u32 rx_enter_flowctrl_watermark; - u32 rx_leave_flowctrl_watermark; - - u32 data_ptr_cnt; - u32 buf_size; - dma_addr_t data_ptr; -}; - -struct sipa_skb_dma_addr_node { - struct sk_buff *skb; - u64 dma_addr; - struct list_head list; -}; - -struct sipa_cmn_fifo_tag { - u32 depth; - u32 wr; - u32 rd; - - u32 fifo_base_addr_l; - u32 fifo_base_addr_h; - - void *virtual_addr; - dma_addr_t dma_ptr; -}; - -struct sipa_cmn_fifo_cfg_tag { - const char *fifo_name; - - void *priv; - - enum sipa_cmn_fifo_index fifo_id; - - bool state; - u32 dst; - u32 cur; - - void __iomem *fifo_reg_base; - - struct sipa_cmn_fifo_tag rx_fifo; - struct sipa_cmn_fifo_tag tx_fifo; - - u32 enter_flow_ctrl_cnt; - u32 exit_flow_ctrl_cnt; - - sipa_irq_notify_cb irq_cb; -}; - -struct sipa_endpoint { - /* Centered on CPU/PAM */ - struct sipa_cmn_fifo_cfg_tag *send_fifo; - struct sipa_cmn_fifo_cfg_tag *recv_fifo; - - struct sipa_cmn_fifo_params send_fifo_param; - struct sipa_cmn_fifo_params recv_fifo_param; - - bool inited; - bool connected; - bool suspended; -}; - -struct sipa_nic { - enum sipa_nic_id nic_id; - struct sipa_endpoint *send_ep; - struct sk_buff_head rx_skb_q; - int need_notify; - u32 src_mask; - int netid; - struct list_head list; - sipa_notify_cb cb; - void *cb_priv; - atomic_t status; - bool flow_ctrl_status; - bool continue_notify; - bool rm_flow_ctrl; -}; - -struct sipa_skb_array { - struct sipa_skb_dma_addr_node *array; - u32 rp; - u32 wp; - u32 depth; -}; - -struct sipa_skb_sender { - struct device *dev; - - struct sipa_endpoint *ep; - - atomic_t left_cnt; - /* To be used for add/remove nic device */ - spinlock_t nic_lock; - /* To be used for send skb process */ - spinlock_t send_lock; - spinlock_t exit_lock; - struct list_head nic_list; - struct list_head sending_list; - struct list_head pair_free_list; - struct sipa_skb_dma_addr_node *pair_cache; - - bool free_notify_net; - bool ep_cover_net; - bool send_notify_net; - - wait_queue_head_t free_waitq; - - struct task_struct *free_thread; - struct task_struct *send_thread; - - bool init_flag; - u32 no_mem_cnt; - u32 no_free_cnt; - u32 enter_flow_ctrl_cnt; - u32 exit_flow_ctrl_cnt; - u32 run; -}; - -struct sipa_skb_receiver { - struct sipa_endpoint *ep; - u32 rsvd; - struct sipa_skb_array recv_array; - wait_queue_head_t recv_waitq; - wait_queue_head_t fill_recv_waitq; - spinlock_t lock; - spinlock_t exit_lock; - u32 nic_cnt; - atomic_t need_fill_cnt; - struct sipa_nic *nic_array[SIPA_NIC_MAX]; - - struct task_struct *fill_thread; - - u32 tx_danger_cnt; - u32 rx_danger_cnt; - u32 run; -}; - -struct sipa_fifo_hal_ops { - int (*open)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, void *cookie); - int (*close)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base); - int (*set_rx_depth)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, u32 depth); - int (*set_tx_depth)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, u32 depth); - u32 (*get_rx_depth)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base); - int (*hal_set_tx_depth)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 depth); - u32 (*get_tx_depth)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base); - int (*set_intr_drop_packet)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, sipa_irq_notify_cb cb); - int (*set_intr_error_code)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, sipa_irq_notify_cb cb); - int (*set_intr_timeout)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, u32 time, sipa_irq_notify_cb cb); - int (*set_hw_intr_timeout)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, u32 time, sipa_irq_notify_cb cb); - int (*set_intr_threshold)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, u32 cnt, sipa_irq_notify_cb cb); - int (*set_hw_intr_thres)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, u32 cnt, sipa_irq_notify_cb cb); - int (*set_src_dst_term)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 src, u32 dst); - int (*enable_local_flowctrl_intr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag * - cfg_base, u32 enable, u32 irq_mode, - sipa_irq_notify_cb cb); - int (*enable_remote_flowctrl_intr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag * - cfg_base, u32 work_mode, - u32 tx_entry_watermark, - u32 tx_exit_watermark, - u32 rx_entry_watermark, - u32 rx_exit_watermark); - int (*set_interrupt_intr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, sipa_irq_notify_cb cb); - int (*set_intr_txfifo_overflow)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, sipa_irq_notify_cb cb); - int (*set_intr_txfifo_full)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, sipa_irq_notify_cb cb); - int (*put_node_to_rx_fifo)(struct device *dev, - enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - struct sipa_node_description_tag *node, - u32 force_intr, u32 num); - u32 (*get_left_cnt)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base); - u32 (*recv_node_from_tx_fifo)(struct device *dev, - enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 num); - void (*get_rx_ptr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 *wr, u32 *rd); - void (*get_tx_ptr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 *wr, u32 *rd); - void (*get_filled_depth)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 *rx_filled, u32 *tx_filled); - u32 (*get_tx_full_status)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base); - u32 (*get_tx_empty_status)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base); - u32 (*get_rx_full_status)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base); - u32 (*get_rx_empty_status)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base); - bool (*set_rx_fifo_wptr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 wptr); - bool (*set_tx_fifo_wptr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 wptr); - int (*set_rx_tx_fifo_ptr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 rx_rd, u32 rx_wr, u32 tx_rd, u32 tx_wr); - int (*ctrl_receive)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - bool stop); - struct sipa_node_description_tag * - (*get_tx_fifo_rp)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 index); - struct sipa_node_description_tag * - (*get_rx_fifo_wr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 index); - int (*set_tx_fifo_rp)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 tx_rd); - int (*set_rx_fifo_wr)(struct device *dev, enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 num); - int (*set_intr_eb)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - bool eb, u32 type); - void (*clr_tout_th_intr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base); -}; - -struct sipa_core { - const char *name; - - struct device *dev; - struct device *pci_dev; - struct dentry *dentry; - struct sipa_endpoint ep; - - struct sipa_cmn_fifo_cfg_tag cmn_fifo_cfg[SIPA_FIFO_MAX]; - - struct work_struct flow_ctrl_work; - - /* ipa low power*/ - bool remote_ready; - - struct resource *reg_res; - phys_addr_t reg_mapped; - void __iomem *virt_reg_addr; - /* IPA NIC interface */ - struct sipa_nic *nic[SIPA_NIC_MAX]; - - /* sender & receiver */ - struct sipa_skb_sender *sender; - struct sipa_skb_receiver *receiver; - - atomic_t recv_cnt; - u64 pcie_mem_offset; - - struct sipa_fifo_hal_ops hal_ops; - - struct task_struct *smsg_thread; - - struct dentry *debugfs_root; - const void *debugfs_data; -}; - -void sipa_fifo_ops_init(struct sipa_fifo_hal_ops *ops); -struct sipa_core *sipa_get_ctrl_pointer(void); - -void sipa_receiver_add_nic(struct sipa_skb_receiver *receiver, - struct sipa_nic *nic); -void sipa_receiver_open_cmn_fifo(struct sipa_skb_receiver *receiver); - -void sipa_sender_open_cmn_fifo(struct sipa_skb_sender *sender); -int create_sipa_skb_sender(struct sipa_endpoint *ep, - struct sipa_skb_sender **sender_pp); -void destroy_sipa_skb_sender(struct sipa_skb_sender *sender); -void sipa_skb_sender_add_nic(struct sipa_skb_sender *sender, - struct sipa_nic *nic); -void sipa_skb_sender_remove_nic(struct sipa_skb_sender *sender, - struct sipa_nic *nic); -int sipa_skb_sender_send_data(struct sipa_skb_sender *sender, - struct sk_buff *skb, - enum sipa_term_type dst, - u8 netid); -int create_sipa_skb_receiver(struct sipa_endpoint *ep, - struct sipa_skb_receiver **receiver_pp); - -void sipa_nic_notify_evt(struct sipa_nic *nic, enum sipa_evt_type evt); -void sipa_nic_try_notify_recv(struct sipa_nic *nic); -void sipa_nic_push_skb(struct sipa_nic *nic, struct sk_buff *skb); -void sipa_nic_check_flow_ctrl(void); - -int sipa_create_smsg_channel(struct sipa_core *ipa); - -int sipa_init_debugfs(struct sipa_core *ipa); - -int sipa_int_callback_func(int evt, void *cookie); - -#if defined (__BIG_ENDIAN_BITFIELD) -static inline int sipa_get_node_desc(u8 *node_addr, - struct sipa_node_description_tag *node) -{ - if (!node_addr || !node) - return -EINVAL; - - node->address = node_addr[0] + ((u32)node_addr[1] << 8) + - ((u32)node_addr[2] << 16) + ((u32)node_addr[3] << 24) + - ((u64)node_addr[4] << 32); -#if 0 - node->length = node_addr[5] + ((u32)node_addr[6] << 8) + - ((u32)(node_addr[7] & 0xf) << 16); - node->offset = ((node_addr[7] & 0xf0) >> 4) + - ((u16)node_addr[8] << 4); -#endif - node->net_id = node_addr[9]; - node->src = node_addr[10] & 0x1f; -#if 0 - node->dst = ((node_addr[11] & 0x3) << 3) + - ((node_addr[10] & 0xe0) >> 5); -#endif - node->err_code = ((node_addr[12] & 0xc0) >> 6) + - ((node_addr[13] & 0x03) << 2); -#if 0 - node->prio = (node_addr[11] & 0x1c) >> 2; - node->bear_id = ((node_addr[11] & 0xe0) >> 5) + - ((node_addr[12] & 0xf) << 3); - node->intr = !!(node_addr[12] & BIT(4)); - node->indx = !!(node_addr[12] & BIT(5)); - node->reserved = ((node_addr[13] & 0xfc) >> 2) + - ((u32)node_addr[14] << 6) + ((u32)node_addr[15] << 14); -#endif - smp_rmb(); - - return 0; -} - -static inline int sipa_set_node_desc(u8 *dst_addr, u8 *src_addr) -{ - if (!dst_addr || !src_addr) - return -EINVAL; - - /* address */ - dst_addr[0] = src_addr[4]; - dst_addr[1] = src_addr[3]; - dst_addr[2] = src_addr[2]; - dst_addr[3] = src_addr[1]; - dst_addr[4] = src_addr[0]; - - /* length */ - dst_addr[5] = (src_addr[7] >> 4) + ((src_addr[6] & 0x0f) << 4); - dst_addr[6] = (src_addr[6] >> 4) + ((src_addr[5] & 0x0f) << 4); - dst_addr[7] = src_addr[5] >> 4; - - /* offset */ - dst_addr[7] += ((src_addr[8] & 0x0f) << 4); - dst_addr[8] = (src_addr[7] << 4) + (src_addr[8] >> 4); - - /* netid */ - dst_addr[9] = src_addr[9]; - - /* src */ - dst_addr[10] = ((src_addr[10] & 0xf8) >> 3); - - /* dst */ - dst_addr[10] += - ((src_addr[11] >> 6) + ((src_addr[10] & 0x01) << 2)) << 5; - dst_addr[11] = (src_addr[10] & 0x6) >> 1; - - /* prio */ - dst_addr[11] += ((src_addr[11] & 0x38) >> 1); - - /* bear_id */ - dst_addr[11] += ((src_addr[12] & 0x70) << 1); - dst_addr[12] = ((src_addr[11] & 0x7) << 1) + (src_addr[12] >> 7); - - /* intx */ - dst_addr[12] += ((src_addr[12] & 0x8) << 1); - - /* indx */ - dst_addr[12] += ((src_addr[12] & 0x4) << 3); - - /* err code */ - dst_addr[12] += (src_addr[13] & 0xc0); - dst_addr[13] = src_addr[12] & 0x3; - - /* reserved */ - dst_addr[13] += src_addr[15] << 2; - dst_addr[14] = (src_addr[15] & 0x3) + (src_addr[14] << 2); - dst_addr[15] = ((src_addr[13] & 0x3f) << 2) + - ((src_addr[14] & 0xc0) >> 6); - smp_wmb(); - - return 0; -} -#endif -#endif diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_debugfs.c b/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_debugfs.c deleted file mode 100644 index 13dba6029..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_debugfs.c +++ /dev/null @@ -1,590 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sipa.h" -#include "sipa_core.h" - -static u32 debug_cmd[5], data_buf[5]; -static struct sipa_node_description_tag ipa_node; - -static int sipa_params_debug_show(struct seq_file *s, void *unused) -{ - int i; - u32 tmp; - struct sipa_core *ipa = (struct sipa_core *)s->private; - struct sipa_cmn_fifo_cfg_tag *fifo_cfg; - - seq_printf(s, "dma_mask = 0x%llx coherent_dma_mask = 0x%llx\n", - (u64)*ipa->pci_dev->dma_mask, (u64)ipa->pci_dev->coherent_dma_mask); - seq_printf(s, "remote ready = %d reg_mapped = 0x%llx virt_reg_addr = 0x%p\n", - ipa->remote_ready, (long long unsigned int)ipa->reg_mapped, ipa->virt_reg_addr); - seq_printf(s, "ipa reg start = 0x%llx size = 0x%llx pcie_mem_offset = %llx\n", - (long long unsigned int)ipa->reg_res->start, (long long unsigned int)resource_size(ipa->reg_res), - (long long unsigned int)ipa->pcie_mem_offset); - for (i = 0; i < SIPA_NIC_MAX; i++) { - if (!ipa->nic[i]) - continue; - - seq_printf(s, "open = %d src_mask = 0x%x netid = %d flow_ctrl_status = %d", - atomic_read(&ipa->nic[i]->status), ipa->nic[i]->src_mask, - ipa->nic[i]->netid, ipa->nic[i]->flow_ctrl_status); - seq_printf(s, " qlen = %d need_notify = %d continue_notify = %d\n", - ipa->nic[i]->rx_skb_q.qlen, ipa->nic[i]->need_notify, - ipa->nic[i]->continue_notify); - } - - seq_printf(s, "sender no_mem_cnt = %d no_free_cnt = %d left_cnt = %d\n", - ipa->sender->no_mem_cnt, ipa->sender->no_free_cnt, - atomic_read(&ipa->sender->left_cnt)); - seq_printf(s, "sender enter_flow_ctrl_cnt=%d, exit_flow_ctrl_cnt=%d, free_notify_net=%d, ep_cover_net=%d\n", - ipa->sender->enter_flow_ctrl_cnt, ipa->sender->exit_flow_ctrl_cnt, - ipa->sender->free_notify_net, ipa->sender->ep_cover_net); - seq_printf(s, "receiver need_fill_cnt = %d", - atomic_read(&ipa->receiver->need_fill_cnt)); - seq_printf(s, " tx_danger_cnt = %d rx_danger_cnt = %d\n", - ipa->receiver->tx_danger_cnt, ipa->receiver->rx_danger_cnt); - - fifo_cfg = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_DL]; - seq_printf(s, "[PCIE_DL]state = %d fifo_reg_base = %p\n", - fifo_cfg->state, fifo_cfg->fifo_reg_base); - seq_printf(s, "[PCIE_DL]rx fifo depth = 0x%x wr = 0x%x rd = 0x%x\n", - fifo_cfg->rx_fifo.depth, - fifo_cfg->rx_fifo.wr, - fifo_cfg->rx_fifo.rd); - seq_printf(s, "[PCIE_DL]rx_fifo fifo_addrl = 0x%x fifo_addrh = 0x%x\n", - fifo_cfg->rx_fifo.fifo_base_addr_l, - fifo_cfg->rx_fifo.fifo_base_addr_h); - seq_printf(s, "[PCIE_DL]rx fifo virt addr = %p\n", - fifo_cfg->rx_fifo.virtual_addr); - seq_printf(s, "[PCIE_DL]tx fifo depth = 0x%x wr = 0x%x rd = 0x%x\n", - fifo_cfg->tx_fifo.depth, fifo_cfg->tx_fifo.wr, - fifo_cfg->tx_fifo.rd); - seq_printf(s, "[PCIE_DL]tx_fifo fifo_addrl = 0x%x fifo_addrh = 0x%x\n", - fifo_cfg->tx_fifo.fifo_base_addr_l, - fifo_cfg->tx_fifo.fifo_base_addr_h); - seq_printf(s, "[PCIE_DL]tx fifo virt addr = %p\n", - fifo_cfg->tx_fifo.virtual_addr); - fifo_cfg = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_UL]; - seq_printf(s, "[PCIE_UL]state = %d fifo_reg_base = %p\n", - fifo_cfg->state, fifo_cfg->fifo_reg_base); - seq_printf(s, "[PCIE_UL]rx fifo depth = 0x%x wr = 0x%x rd = 0x%x\n", - fifo_cfg->rx_fifo.depth, - fifo_cfg->rx_fifo.wr, - fifo_cfg->rx_fifo.rd); - seq_printf(s, "[PCIE_UL]rx_fifo fifo_addrl = 0x%x fifo_addrh = 0x%x\n", - fifo_cfg->rx_fifo.fifo_base_addr_l, - fifo_cfg->rx_fifo.fifo_base_addr_h); - seq_printf(s, "[PCIE_UL]rx fifo virt addr = %p\n", - fifo_cfg->rx_fifo.virtual_addr); - seq_printf(s, "[PCIE_UL]tx fifo depth = 0x%x wr = 0x%x rd = 0x%x\n", - fifo_cfg->tx_fifo.depth, fifo_cfg->tx_fifo.wr, - fifo_cfg->tx_fifo.rd); - seq_printf(s, "[PCIE_UL]tx_fifo fifo_addrl = 0x%x fifo_addrh = 0x%x\n", - fifo_cfg->tx_fifo.fifo_base_addr_l, - fifo_cfg->tx_fifo.fifo_base_addr_h); - seq_printf(s, "[PCIE_UL]tx fifo virt addr = %p\n", - fifo_cfg->tx_fifo.virtual_addr); - - //ep: IPA_COMMON_TX_FIFO_DEPTH 0x0Cl - tmp = readl_relaxed(ipa->virt_reg_addr + 0xc00 + 0x0C); - seq_printf(s, "neil: read IPA_COMMON_TX_FIFO_DEPTH, value = %x\n", (tmp >> 16)); - - //ep: IPA_COMMON_TX_FIFO_WR 0x10l - tmp = readl_relaxed(ipa->virt_reg_addr + 0xc00 + 0x10); - seq_printf(s, "neil: read IPA_COMMON_TX_FIFO_WR, value = %x\n", (tmp >> 16)); - - //ep: IPA_COMMON_TX_FIFO_RD 0x14l - tmp = readl_relaxed(ipa->virt_reg_addr + 0xc00 + 0x14); - seq_printf(s, "neil: read IPA_COMMON_TX_FIFO_RD, value = %x\n", (tmp >> 16)); - return 0; -} - -static int sipa_params_debug_open(struct inode *inode, - struct file *file) -{ - return single_open(file, sipa_params_debug_show, - inode->i_private); -} - -static ssize_t sipa_endian_debug_write(struct file *f, const char __user *buf, - size_t size, loff_t *l) -{ - ssize_t len; - u32 debug_cmd[24], data_buf[24]; - - len = min(size, sizeof(data_buf) - 1); - if (copy_from_user((char *)data_buf, buf, len)) - return -EFAULT; - - len = sscanf((char *)data_buf, "%x %x %x %x %x %x %x %x %x %x %x %x\n", - &debug_cmd[0], &debug_cmd[1], &debug_cmd[2], - &debug_cmd[3], &debug_cmd[4], &debug_cmd[5], - &debug_cmd[6], &debug_cmd[7], &debug_cmd[8], - &debug_cmd[9], &debug_cmd[10], &debug_cmd[11]); - - ipa_node.address = debug_cmd[0]; - ipa_node.length = debug_cmd[1]; - ipa_node.offset = debug_cmd[2]; - ipa_node.net_id = debug_cmd[3]; - ipa_node.src = debug_cmd[4]; - ipa_node.dst = debug_cmd[5]; - ipa_node.prio = debug_cmd[6]; - ipa_node.bear_id = debug_cmd[7]; - ipa_node.intr = debug_cmd[8]; - ipa_node.indx = debug_cmd[9]; - ipa_node.err_code = debug_cmd[10]; - ipa_node.reserved = debug_cmd[11]; - - return size; -} - -static int sipa_endian_debug_show(struct seq_file *s, void *unused) -{ - int i; - u8 *byte; - - seq_printf(s, "address = 0x%llx length = 0x%x offset = 0x%x net_id = 0x%x\n", - (u64)ipa_node.address, ipa_node.length, ipa_node.offset, - ipa_node.net_id); - seq_printf(s, "src = 0x%x dst = 0x%x prio = 0x%x bear_id = 0x%x\n", - ipa_node.src, ipa_node.dst, ipa_node.prio, ipa_node.bear_id); - seq_printf(s, "intr = 0x%x indx = 0x%x err_code = 0x%x reserved = 0x%x\n", - ipa_node.intr, ipa_node.indx, - ipa_node.err_code, ipa_node.reserved); - - byte = (u8 *)&ipa_node; - for (i = 0; i < sizeof(ipa_node); i++) - seq_printf(s, "0x%x ", *(byte + i)); - - seq_puts(s, "\n"); - - return 0; -} - -static const struct file_operations sipa_params_fops = { - .open = sipa_params_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int sipa_endian_debug_open(struct inode *inode, - struct file *file) -{ - return single_open(file, sipa_endian_debug_show, - inode->i_private); -} - -static const struct file_operations sipa_endian_fops = { - .open = sipa_endian_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = sipa_endian_debug_write, -}; - -static ssize_t sipa_get_node_debug_write(struct file *f, const char __user *buf, - size_t size, loff_t *l) -{ - int i; - ssize_t len; - u8 debug_cmd[16], data_buf[128]; - - len = min(size, sizeof(data_buf) - 1); - if (copy_from_user((char *)data_buf, buf, len)) - return -EFAULT; - - len = sscanf((char *)data_buf, "%4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx\n", - &debug_cmd[0], &debug_cmd[1], &debug_cmd[2], - &debug_cmd[3], &debug_cmd[4], &debug_cmd[5], - &debug_cmd[6], &debug_cmd[7], &debug_cmd[8], - &debug_cmd[9], &debug_cmd[10], &debug_cmd[11], - &debug_cmd[12], &debug_cmd[13], &debug_cmd[14], - &debug_cmd[15]); - - for (i = 0; i < 16; i++) - pr_err("0x%x ", debug_cmd[i]); - pr_err("\n"); - -#if defined (__BIG_ENDIAN_BITFIELD) - sipa_get_node_desc(debug_cmd, &ipa_node); -#else - ipa_node.address = debug_cmd[4] + ((u32)debug_cmd[3] << 8) + - ((u32)debug_cmd[2] << 16) + ((u32)debug_cmd[1] << 24) + - ((u64)debug_cmd[0] << 32); - ipa_node.net_id = debug_cmd[9]; - ipa_node.src = debug_cmd[10] & 0x1f; - ipa_node.err_code = ((debug_cmd[13] & 0xc0) >> 6) + - ((debug_cmd[12] & 0x03) << 2); -#endif - return size; -} - -static int sipa_get_node_debug_show(struct seq_file *s, void *unused) -{ - int i; - u8 *byte; - - seq_printf(s, "address = 0x%llx length = 0x%x offset = 0x%x net_id = 0x%x\n", - (u64)ipa_node.address, ipa_node.length, ipa_node.offset, - ipa_node.net_id); - seq_printf(s, "src = 0x%x dst = 0x%x prio = 0x%x bear_id = 0x%x\n", - ipa_node.src, ipa_node.dst, ipa_node.prio, ipa_node.bear_id); - seq_printf(s, "intr = 0x%x indx = 0x%x err_code = 0x%x reserved = 0x%x\n", - ipa_node.intr, ipa_node.indx, - ipa_node.err_code, ipa_node.reserved); - - byte = (u8 *)&ipa_node; - for (i = 0; i < sizeof(ipa_node); i++) - seq_printf(s, "0x%x ", *(byte + i)); - - seq_puts(s, "\n"); - - return 0; -} - -static int sipa_get_node_debug_open(struct inode *inode, - struct file *file) -{ - return single_open(file, sipa_get_node_debug_show, - inode->i_private); -} - -static const struct file_operations sipa_get_node_fops = { - .open = sipa_get_node_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = sipa_get_node_debug_write, -}; - -static ssize_t sipa_set_node_debug_write(struct file *f, const char __user *buf, - size_t size, loff_t *l) -{ - ssize_t len; - u32 debug_cmd[24], data_buf[24]; - - len = min(size, sizeof(data_buf) - 1); - if (copy_from_user((char *)data_buf, buf, len)) - return -EFAULT; - - len = sscanf((char *)data_buf, "%x %x %x %x %x %x %x %x %x %x %x %x\n", - &debug_cmd[0], &debug_cmd[1], &debug_cmd[2], - &debug_cmd[3], &debug_cmd[4], &debug_cmd[5], - &debug_cmd[6], &debug_cmd[7], &debug_cmd[8], - &debug_cmd[9], &debug_cmd[10], &debug_cmd[11]); - - ipa_node.address = debug_cmd[0]; - ipa_node.length = debug_cmd[1]; - ipa_node.offset = debug_cmd[2]; - ipa_node.net_id = debug_cmd[3]; - ipa_node.src = debug_cmd[4]; - ipa_node.dst = debug_cmd[5]; - ipa_node.prio = debug_cmd[6]; - ipa_node.bear_id = debug_cmd[7]; - ipa_node.intr = debug_cmd[8]; - ipa_node.indx = debug_cmd[9]; - ipa_node.err_code = debug_cmd[10]; - ipa_node.reserved = debug_cmd[11]; - - return size; -} - -static int sipa_set_node_debug_show(struct seq_file *s, void *unused) -{ -#if defined (__BIG_ENDIAN_BITFIELD) - int i; - u8 node_buf[16]; -#endif - - seq_printf(s, "address = 0x%llx length = 0x%x offset = 0x%x net_id = 0x%x\n", - (u64)ipa_node.address, ipa_node.length, ipa_node.offset, - ipa_node.net_id); - seq_printf(s, "src = 0x%x dst = 0x%x prio = 0x%x bear_id = 0x%x\n", - ipa_node.src, ipa_node.dst, ipa_node.prio, ipa_node.bear_id); - seq_printf(s, "intr = 0x%x indx = 0x%x err_code = 0x%x reserved = 0x%x\n", - ipa_node.intr, ipa_node.indx, - ipa_node.err_code, ipa_node.reserved); - -#if defined (__BIG_ENDIAN_BITFIELD) - sipa_set_node_desc(node_buf, (u8 *)&ipa_node); - for (i = 0; i < sizeof(node_buf); i++) - seq_printf(s, "0x%x ", node_buf[i]); -#endif - - seq_puts(s, "\n"); - - return 0; -} - -static int sipa_set_node_debug_open(struct inode *inode, - struct file *file) -{ - return single_open(file, sipa_set_node_debug_show, - inode->i_private); -} - -static const struct file_operations sipa_set_node_fops = { - .open = sipa_set_node_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = sipa_set_node_debug_write, -}; - -static ssize_t sipa_reg_debug_write(struct file *f, const char __user *buf, - size_t size, loff_t *l) -{ - ssize_t len; - struct sipa_core *ipa = f->f_inode->i_private; - - len = min(size, sizeof(data_buf) - 1); - if (copy_from_user((char *)data_buf, buf, len)) - return -EFAULT; - - len = sscanf((char *)data_buf, "%x %x %x %x %x\n", - &debug_cmd[0], &debug_cmd[1], &debug_cmd[2], - &debug_cmd[3], &debug_cmd[4]); - if (debug_cmd[2]) - writel_relaxed(debug_cmd[1], ipa->virt_reg_addr + debug_cmd[0]); - - return size; -} - -static int sipa_reg_debug_show(struct seq_file *s, void *unused) -{ - u32 tx_filled, rx_filled; - u32 tx_wr, tx_rd, rx_wr, rx_rd; - struct sipa_core *ipa = (struct sipa_core *)s->private; - - seq_printf(s, "0x%x\n", - readl_relaxed(ipa->virt_reg_addr + debug_cmd[0])); - - seq_printf(s, "pcie dl tx fifo empty = %d full = %d rx fifo empty = %d full = %d\n", - ipa->hal_ops.get_tx_empty_status(SIPA_FIFO_PCIE_DL, - ipa->cmn_fifo_cfg), - ipa->hal_ops.get_tx_full_status(SIPA_FIFO_PCIE_DL, - ipa->cmn_fifo_cfg), - ipa->hal_ops.get_rx_empty_status(SIPA_FIFO_PCIE_DL, - ipa->cmn_fifo_cfg), - ipa->hal_ops.get_rx_full_status(SIPA_FIFO_PCIE_DL, - ipa->cmn_fifo_cfg)); - seq_printf(s, "pcie ul tx fifo empty = %d full = %d rx fifo empty = %d full = %d\n", - ipa->hal_ops.get_tx_empty_status(SIPA_FIFO_PCIE_UL, - ipa->cmn_fifo_cfg), - ipa->hal_ops.get_tx_full_status(SIPA_FIFO_PCIE_UL, - ipa->cmn_fifo_cfg), - ipa->hal_ops.get_rx_empty_status(SIPA_FIFO_PCIE_UL, - ipa->cmn_fifo_cfg), - ipa->hal_ops.get_rx_full_status(SIPA_FIFO_PCIE_UL, - ipa->cmn_fifo_cfg)); - ipa->hal_ops.get_filled_depth(SIPA_FIFO_PCIE_DL, ipa->cmn_fifo_cfg, - &rx_filled, &tx_filled); - seq_printf(s, "pcie dl tx filled = 0x%x rx filled = 0x%x\n", - tx_filled, rx_filled); - ipa->hal_ops.get_filled_depth(SIPA_FIFO_PCIE_UL, ipa->cmn_fifo_cfg, - &rx_filled, &tx_filled); - seq_printf(s, "pcie ul tx filled = 0x%x rx filled = 0x%x\n", - tx_filled, rx_filled); - - ipa->hal_ops.get_rx_ptr(SIPA_FIFO_PCIE_UL, ipa->cmn_fifo_cfg, &rx_wr, &rx_rd); - ipa->hal_ops.get_tx_ptr(SIPA_FIFO_PCIE_UL, ipa->cmn_fifo_cfg, &tx_wr, &tx_rd); - seq_printf(s, "pcie ul rx_wr = 0x%x, rx_rd = 0x%x, tx_wr = 0x%x, tx_rd = 0x%x\n", - rx_wr, rx_rd, tx_wr, tx_rd); - - ipa->hal_ops.get_rx_ptr(SIPA_FIFO_PCIE_DL, ipa->cmn_fifo_cfg, &rx_wr, &rx_rd); - ipa->hal_ops.get_tx_ptr(SIPA_FIFO_PCIE_DL, ipa->cmn_fifo_cfg, &tx_wr, &tx_rd); - seq_printf(s, "pcie dl rx_wr = 0x%x, rx_rd = 0x%x, tx_wr = 0x%x, tx_rd = 0x%x\n", - rx_wr, rx_rd, tx_wr, tx_rd); - - sipa_int_callback_func(0, NULL); - - return 0; -} - -static int sipa_reg_debug_open(struct inode *inode, - struct file *file) -{ - return single_open(file, sipa_reg_debug_show, - inode->i_private); -} - -static const struct file_operations sipa_reg_debug_fops = { - .open = sipa_reg_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = sipa_reg_debug_write, -}; - -static int sipa_send_test_show(struct seq_file *s, void *unused) -{ - struct sk_buff *skb = NULL; - struct sipa_core *ipa = (struct sipa_core *)s->private; - - if (!skb) { - skb = __dev_alloc_skb(256, GFP_KERNEL | GFP_NOWAIT); - if (!skb) { - dev_err(ipa->dev, "failed to alloc skb!\n"); - return 0; - } - skb_put(skb, 128); - memset(skb->data, 0xE7, skb->len); - - sipa_skb_sender_send_data(ipa->sender, skb, 0x19, 0); - } - - return 0; -} - -static int sipa_send_test_open(struct inode *inode, struct file *file) -{ - return single_open(file, sipa_send_test_show, inode->i_private); -} - -static const struct file_operations sipa_send_test_fops = { - .open = sipa_send_test_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static ssize_t sipa_nic_debug_write(struct file *f, const char __user *buf, - size_t size, loff_t *l) -{ - ssize_t len; - u8 debug_cmd[24], data_buf[24]; - - len = min(size, sizeof(data_buf) - 1); - if (copy_from_user((char *)data_buf, buf, len)) - return -EFAULT; - - len = sscanf((char *)data_buf, "%4hhx %4hhx\n", - &debug_cmd[0], &debug_cmd[1]); - if (debug_cmd[1]) - sipa_nic_open(debug_cmd[0], 0, NULL, NULL); - else - sipa_nic_close(debug_cmd[0]); - - return size; -} - -static int sipa_nic_debug_show(struct seq_file *s, void *unused) -{ - //struct sk_buff *skb = NULL; - struct sipa_core *ipa = (struct sipa_core *)s->private; - struct sipa_cmn_fifo_cfg_tag *pcie_dl = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_DL]; - //struct sipa_cmn_fifo_cfg_tag *pcie_ul = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_UL]; - //struct sipa_cmn_fifo_tag *dl_tx_fifo = &pcie_dl->tx_fifo; - struct sipa_cmn_fifo_tag *dl_rx_fifo = &pcie_dl->rx_fifo; - //struct sipa_cmn_fifo_tag *ul_tx_fifo = &pcie_ul->tx_fifo; - //struct sipa_cmn_fifo_tag *ul_rx_fifo = &pcie_ul->rx_fifo; - struct sipa_node_description_tag *node; - int i = 0; - - pr_info("dl rx_fifo addr: 0x%lx wp-%d rp-%d\n", (long unsigned int)dl_rx_fifo->virtual_addr, - dl_rx_fifo->wr, dl_rx_fifo->rd); - node = (struct sipa_node_description_tag *)dl_rx_fifo->virtual_addr; - for (i = 0; i < dl_rx_fifo->depth; i++, node++) { - pr_info("node addr 0x%lx\n", (long unsigned int)node); - pr_info("node info i-%d, addr-0x%llx len-%u off-%u netid-%u src-%u dst-%u pro-%u bearid-%u intr-%u indx-%u err-%u resd-%u\n", - i, (long long unsigned int)node->address, node->length, node->offset, node->net_id, - node->src, node->dst, node->prio, node->bear_id, node->intr, - node->indx, node->err_code, node->reserved); - } - - - return 0; -} - -static int sipa_nic_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, sipa_nic_debug_show, inode->i_private); -} - -static const struct file_operations sipa_nic_debug_fops = { - .open = sipa_nic_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = sipa_nic_debug_write, -}; - -int sipa_init_debugfs(struct sipa_core *ipa) -{ - struct dentry *root; - struct dentry *file; - - root = debugfs_create_dir(dev_name(ipa->dev), NULL); - if (!root) { - dev_err(ipa->dev, "sipa create debugfs fail\n"); - return -ENOMEM; - } - - file = debugfs_create_file("params", 0444, root, ipa, - &sipa_params_fops); - if (!file) { - dev_err(ipa->dev, "sipa create params file debugfs fail\n"); - debugfs_remove_recursive(root); - return -ENOMEM; - } - - file = debugfs_create_file("endian", 0444, root, ipa, - &sipa_endian_fops); - if (!file) { - dev_err(ipa->dev, "sipa create endian file debugfs fail\n"); - debugfs_remove_recursive(root); - return -ENOMEM; - } - - file = debugfs_create_file("get_node", 0444, root, ipa, - &sipa_get_node_fops); - if (!file) { - dev_err(ipa->dev, "sipa create endian file debugfs fail\n"); - debugfs_remove_recursive(root); - return -ENOMEM; - } - - file = debugfs_create_file("set_node", 0444, root, ipa, - &sipa_set_node_fops); - if (!file) { - dev_err(ipa->dev, "sipa create set node file debugfs fail\n"); - debugfs_remove_recursive(root); - return -ENOMEM; - } - - file = debugfs_create_file("reg", 0444, root, ipa, - &sipa_reg_debug_fops); - if (!file) { - dev_err(ipa->dev, "sipa create reg debug file debugfs fail\n"); - debugfs_remove_recursive(root); - return -ENOMEM; - } - - file = debugfs_create_file("send_test", 0444, root, ipa, - &sipa_send_test_fops); - if (!file) { - dev_err(ipa->dev, "sipa create send_test debug file debugfs fail\n"); - debugfs_remove_recursive(root); - return -ENOMEM; - } - - file = debugfs_create_file("nic", 0444, root, ipa, - &sipa_nic_debug_fops); - if (!file) { - dev_err(ipa->dev, "sipa create nic debug file debugfs fail\n"); - debugfs_remove_recursive(root); - return -ENOMEM; - } - ipa->dentry = root; - - return 0; -} -EXPORT_SYMBOL(sipa_init_debugfs); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_dele_cmn.c b/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_dele_cmn.c deleted file mode 100644 index e90895b88..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_dele_cmn.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2018-2019 Unisoc Corporation - * - * 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 the GNU - * General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sipa.h" -#include "../include/sipc.h" -#include "../include/sprd_pcie_ep_device.h" -#include "sipa_core.h" - -#define SIPA_PCIE_DL_CMN_FIFO_REG_OFFSET 0x980 -#define SIPA_PCIE_UL_CMN_FIFO_REG_OFFSET 0x200 - -static int sipa_dele_start_req_work(void) -{ - struct smsg msg; - - msg.channel = SMSG_CH_COMM_SIPA; - msg.type = SMSG_TYPE_CMD; - msg.flag = SMSG_FLG_DELE_REQUEST; - msg.value = 0; - - return smsg_send(SIPC_ID_MINIAP, &msg, -1); -} - -static int sipa_init_cmn_fifo_reg_addr(struct sipa_core *ipa) -{ - ipa->reg_mapped = sprd_ep_ipa_map(PCIE_IPA_TYPE_REG, - ipa->reg_res->start, - resource_size(ipa->reg_res)); -#ifndef devm_ioremap_nocache -#define devm_ioremap_nocache devm_ioremap -#endif - ipa->virt_reg_addr = devm_ioremap_nocache(ipa->dev, - (resource_size_t)ipa->reg_mapped, - (resource_size_t)(resource_size(ipa->reg_res))); - if (!ipa->virt_reg_addr) { - dev_err(ipa->dev, "ipa reg base remap fail\n"); - return -ENOMEM; - } - - ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_DL].fifo_reg_base = - ipa->virt_reg_addr + SIPA_PCIE_DL_CMN_FIFO_REG_OFFSET; - ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_UL].fifo_reg_base = - ipa->virt_reg_addr + SIPA_PCIE_UL_CMN_FIFO_REG_OFFSET; - - return 0; -} - -static int conn_thread(void *data) -{ - struct smsg mrecv; - int ret, timeout = 500; - struct sipa_core *ipa = data; - - /* since the channel open may hang, we call it in the thread context */ - ret = smsg_ch_open(SIPC_ID_MINIAP, SMSG_CH_COMM_SIPA, -1); - if (ret != 0) { - dev_err(ipa->dev, "sipa_delegator failed to open dst %d channel %d\n", - SIPC_ID_MINIAP, SMSG_CH_COMM_SIPA); - /* assign NULL to thread poniter as failed to open channel */ - return ret; - } - - while (sipa_dele_start_req_work() && timeout--) - usleep_range(5000, 10000); - - /* start listen the smsg events */ - while (!kthread_should_stop()) { - /* monitor seblock recv smsg */ - smsg_set(&mrecv, SMSG_CH_COMM_SIPA, 0, 0, 0); - ret = smsg_recv(SIPC_ID_MINIAP, &mrecv, -1); - if (ret == -EIO || ret == -ENODEV) { - /* channel state is FREE */ - usleep_range(5000, 10000); - continue; - } - - dev_dbg(ipa->dev, "sipa type=%d, flag=0x%x, value=0x%08x\n", - mrecv.type, mrecv.flag, mrecv.value); - - switch (mrecv.type) { - case SMSG_TYPE_OPEN: - /* just ack open */ - smsg_open_ack(SIPC_ID_AP, SMSG_CH_COMM_SIPA); - break; - case SMSG_TYPE_CLOSE: - /* handle channel close */ - smsg_close_ack(SIPC_ID_AP, SMSG_CH_COMM_SIPA); - break; - case SMSG_TYPE_CMD: - /* handle commads */ - break; - case SMSG_TYPE_DONE: - sipa_init_cmn_fifo_reg_addr(ipa); - dev_info(ipa->dev, "remote ipa ready reg_mapped = 0x%llx\n", (long long unsigned int)ipa->reg_mapped); - sipa_receiver_open_cmn_fifo(ipa->receiver); - sipa_sender_open_cmn_fifo(ipa->sender); - sipa_nic_check_flow_ctrl(); - ipa->remote_ready = true; - /* handle cmd done */ - break; - case SMSG_TYPE_EVENT: - /* handle events */ - break; - default: - ret = 1; - break; - }; - - if (ret) { - dev_info(ipa->dev, "unknown msg in conn_thrd: %d, %d, %d\n", - mrecv.type, mrecv.flag, mrecv.value); - ret = 0; - } - } - - return ret; -} - -int sipa_create_smsg_channel(struct sipa_core *ipa) -{ - /* create channel thread for this seblock channel */ - ipa->smsg_thread = kthread_create(conn_thread, ipa, "sipa-dele"); - if (IS_ERR(ipa->smsg_thread)) { - dev_err(ipa->dev, "Failed to create monitor smsg kthread\n"); - return PTR_ERR(ipa->smsg_thread); - } - - wake_up_process(ipa->smsg_thread); - - return 0; -} -EXPORT_SYMBOL(sipa_create_smsg_channel); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_dummy.c b/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_dummy.c deleted file mode 100644 index 6d3c8f91b..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_dummy.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - * Copyright (C) 2020 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) "sipa_dummy: " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sipa_eth.h" -#include "sipa_core.h" -#include "../include/sipa.h" - - -/* Device status */ -#define DEV_ON 1 -#define DEV_OFF 0 - -#define SIPA_DUMMY_NAPI_WEIGHT 64 - -extern struct sipa_eth_netid_device * dev_list[]; -static struct net_device *dummy_dev; -static struct dentry *dummy_root; -static int sipa_dummy_debugfs_mknod(void *data); - -#ifndef CONFIG_SPRD_ETHERNET -static int sipa_arp_reply(struct net_device *net, struct sk_buff *skb) { - struct arphdr *parp; - u8 *arpptr, *sha; - u8 sip[4], tip[4]; - struct sk_buff *reply = NULL; - - parp = arp_hdr(skb); - - if (parp->ar_hrd == htons(ARPHRD_ETHER) && parp->ar_pro == htons(ETH_P_IP) - && parp->ar_op == htons(ARPOP_REQUEST) && parp->ar_hln == 6 && parp->ar_pln == 4) { - arpptr = (u8 *)parp + sizeof(struct arphdr); - sha = arpptr; - arpptr += net->addr_len; /* sha */ - memcpy(sip, arpptr, sizeof(sip)); - arpptr += sizeof(sip); - arpptr += net->addr_len; /* tha */ - memcpy(tip, arpptr, sizeof(tip)); - - pr_info("%s sip = %d.%d.%d.%d, tip=%d.%d.%d.%d\n", netdev_name(net), sip[0], sip[1], sip[2], sip[3], tip[0], tip[1], tip[2], tip[3]); - reply = arp_create(ARPOP_REPLY, ETH_P_ARP, *((__be32 *)sip), skb->dev, *((__be32 *)tip), sha, net->dev_addr, sha); - if (reply) { - dev_queue_xmit(reply); - } - return 1; - } - - return 0; -} - -static void sipa_get_modem_mac(struct sk_buff *skb, struct SIPA_ETH *sipa_eth) -{ - struct ethhdr *ehdr; - struct iphdr *iph; - struct udphdr *udph; - struct sipa_eth_init_data *pdata = sipa_eth->pdata; - - ehdr = (struct ethhdr *)(skb->data - ETH_HLEN); - iph = ip_hdr(skb); - udph = (struct udphdr *)(skb->data + iph->ihl*4); - - if (ehdr->h_proto == htons(ETH_P_ARP)) { - sipa_arp_reply(skb->dev, skb); - return; - } - - //printk("%s skb=%p, h_proto=%x, protocol=%x, saddr=%x, daddr=%x dest=%x\n", __func__, skb, ehdr->h_proto, iph->protocol, iph->saddr, iph->daddr, udph->dest); - if (ehdr->h_proto == htons(ETH_P_IP) && iph->protocol == IPPROTO_UDP && iph->saddr != 0x00000000 && iph->daddr == 0xFFFFFFFF) { - if (udph->dest == htons(68)) //DHCP offer/ACK - { - memcpy(pdata->modem_mac, ehdr->h_source, ETH_ALEN); - pr_info("Modem Mac Address: %02x:%02x:%02x:%02x:%02x:%02x\n", - pdata->modem_mac[0], pdata->modem_mac[1], pdata->modem_mac[2], pdata->modem_mac[3], pdata->modem_mac[4], pdata->modem_mac[5]); - } - } -} -#endif - -/* Term type 0x6 means we are in direct mode, currently. - * we will recv pkt with a dummy mac header, which will - * cause us fail to get skb->pkt_type and skb->protocol. - */ -static void sipa_dummy_prepare_skb(struct sk_buff *skb) -{ - struct iphdr *iph; - struct ipv6hdr *ipv6h; - struct net_device *dev; - unsigned int real_len = 0, payload_len = 0; - bool ip_arp = true; - - dev = skb->dev; - - skb->protocol = eth_type_trans(skb, dev); - skb_reset_network_header(skb); - - switch (ntohs(skb->protocol)) { - case ETH_P_IP: - iph = ip_hdr(skb); - real_len = ntohs(iph->tot_len); - break; - case ETH_P_IPV6: - ipv6h = ipv6_hdr(skb); - payload_len = ntohs(ipv6h->payload_len); - real_len = payload_len + sizeof(struct ipv6hdr); - break; - case ETH_P_ARP: - real_len = arp_hdr_len(dev); - break; - default: - ip_arp = false; - break; - } - - if (ip_arp) - skb_trim(skb, real_len); - - /* TODO chechsum ... */ - skb->ip_summed = CHECKSUM_NONE; - skb->pkt_type = PACKET_HOST; -} - -/* Term type 0x6 means we are in direct mode, currently. - * we will recv pkt with a dummy mac header, which will - * cause us fail to get skb->pkt_type and skb->protocol. - */ -static void sipa_dummy_direct_mode_prepare_skb(struct sk_buff *skb) -{ - struct iphdr *iph; - struct ipv6hdr *ipv6h; - unsigned int real_len = 0, payload_len = 0; - - skb_pull_inline(skb, ETH_HLEN); - skb_reset_network_header(skb); - iph = ip_hdr(skb); - if (iph->version == 4) { - skb->protocol = htons(ETH_P_IP); - iph = ip_hdr(skb); - real_len = ntohs(iph->tot_len); - skb_trim(skb, real_len); - } else if(iph->version == 6){ - skb->protocol = htons(ETH_P_IPV6); - ipv6h = ipv6_hdr(skb); - payload_len = ntohs(ipv6h->payload_len); - real_len = payload_len + sizeof(struct ipv6hdr); - skb_trim(skb, real_len); - } else { - pr_err("unrecognized ip version %d\n", iph->version); - } - - skb->ip_summed = CHECKSUM_NONE; - skb->pkt_type = PACKET_HOST; -} - -static int sipa_dummy_rx(struct SIPA_DUMMY *sipa_dummy, int budget) -{ - struct sk_buff *skb; - struct sipa_eth_netid_device *netid_dev_info; - struct SIPA_ETH *sipa_eth; - int real_netid = 0; - int skb_cnt = 0; - int ret; - - if (!sipa_dummy) { - pr_err("no sipa_dummy device\n"); - return -EINVAL; - } - - atomic_set(&sipa_dummy->rx_evt, 0); - while (skb_cnt < budget) { - ret = sipa_nic_rx(&real_netid, &skb, skb_cnt); - - if (ret) { - switch (ret) { - case -ENODEV: - pr_err("sipa fail to find dev\n"); - sipa_dummy->stats.rx_errors++; - sipa_dummy->netdev->stats.rx_errors++; - break; - case -ENODATA: - pr_err("sipa no data\n"); - atomic_set(&sipa_dummy->rx_busy, 0); - break; - } - break; - } - - skb_cnt++; - sipa_dummy->stats.rx_packets++; - sipa_dummy->stats.rx_bytes += skb->len; - if (real_netid < 0) { - pr_err("sipa invaild netid"); - break; - } - /* - * We should determine the real device before we do eth_types_tran, - */ - if (real_netid < 0 || real_netid >= SIPA_DUMMY_IFACE_NUM) { - pr_err("illegal real_netid %d\n", real_netid); - dev_kfree_skb_any(skb); - break; - } - netid_dev_info = dev_list[real_netid]; - if (!netid_dev_info || netid_dev_info->state == DEV_OFF) { - pr_info("netid= %d net is not DEV_ON\n", real_netid); - dev_kfree_skb_any(skb); - break; - } - - skb->dev = netid_dev_info->ndev; - sipa_eth = netdev_priv(skb->dev); - sipa_eth->stats.rx_packets++; - sipa_eth->stats.rx_bytes += skb->len; - if (sipa_eth->pdata->term_type == 0x6) { - sipa_dummy_direct_mode_prepare_skb(skb); - } else { - sipa_dummy_prepare_skb(skb); -#ifndef CONFIG_SPRD_ETHERNET - sipa_get_modem_mac(skb, sipa_eth); -#endif - } - napi_gro_receive(&sipa_dummy->napi, skb); - } - - return skb_cnt; -} - -static int sipa_dummy_rx_poll_handler(struct napi_struct *napi, int budget) -{ - int pkts = 0, num, tmp = 0; - - struct SIPA_DUMMY *sipa_dummy = container_of(napi, struct SIPA_DUMMY, napi); - -READ_AGAIN: - num = sipa_nic_get_filled_num(); - if (!num) - goto check; - if (num > budget) - num = budget; - - pkts = sipa_dummy_rx(sipa_dummy, num); - if (pkts > 0) - sipa_nic_set_tx_fifo_rp(pkts); - tmp += pkts; - - budget -= pkts; - if (!budget) - goto out; - -check: - if (!sipa_check_recv_tx_fifo_empty() || - atomic_read(&sipa_dummy->rx_evt)) { - atomic_set(&sipa_dummy->rx_evt, 0); - goto READ_AGAIN; - } - - atomic_set(&sipa_dummy->rx_busy, 0); - napi_complete(napi); - sipa_nic_restore_irq(); - if (atomic_read(&sipa_dummy->rx_evt) || - atomic_read(&sipa_dummy->rx_busy) || - !sipa_check_recv_tx_fifo_empty()) { - atomic_set(&sipa_dummy->rx_evt, 0); - napi_schedule(&sipa_dummy->napi); - } - -out: - return tmp; -} - -static void sipa_dummy_rx_handler (void *priv) -{ - struct SIPA_DUMMY *sipa_dummy = (struct SIPA_DUMMY *)priv; - - if (!sipa_dummy) { - pr_err("data is NULL\n"); - return; - } - - if (!atomic_cmpxchg(&sipa_dummy->rx_busy, 0, 1)) { - atomic_set(&sipa_dummy->rx_evt, 0); - napi_schedule(&sipa_dummy->napi); - } -} - -/* for sipa to invoke */ -void sipa_dummy_recv_trigger(void) -{ - struct SIPA_DUMMY *sipa_dummy; - - if (!dummy_dev) - return; - - sipa_dummy = netdev_priv(dummy_dev); - - atomic_set(&sipa_dummy->rx_evt, 1); - sipa_dummy_rx_handler(sipa_dummy); -} - -static int sipa_dummy_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct SIPA_DUMMY *sipa_dummy = netdev_priv(dev); - - /* update netdev statistics */ - sipa_dummy->stats.tx_packets++; - sipa_dummy->stats.tx_bytes += skb->len; - - dev_kfree_skb(skb); - return NETDEV_TX_OK; -} - -/* Open interface */ -static int sipa_dummy_open(struct net_device *dev) -{ - struct SIPA_DUMMY *sipa_dummy = netdev_priv(dev); - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - if (!ctrl) { - return -EINVAL; - } - - if(!ctrl->remote_ready) - return -EINVAL; - - pr_info("dummy open\n"); - if (!netif_carrier_ok(sipa_dummy->netdev)) { - netif_carrier_on(sipa_dummy->netdev); - } - - netif_start_queue(dev); - //napi_enable(&sipa_dummy->napi); - - napi_schedule(&sipa_dummy->napi); - return 0; -} - -/* Close interface */ -static int sipa_dummy_close(struct net_device *dev) -{ - //struct SIPA_DUMMY *sipa_dummy = netdev_priv(dev); - pr_info("close dummy!\n"); - - //napi_disable(&sipa_dummy->napi); - netif_stop_queue(dev); - netif_carrier_off(dev); - - return 0; -} - -static struct net_device_stats *sipa_dummy_get_stats(struct net_device *dev) -{ - struct SIPA_DUMMY *sipa_dummy = netdev_priv(dev); - - return &sipa_dummy->stats; -} - -static const struct net_device_ops sipa_dummy_ops = { - .ndo_open = sipa_dummy_open, - .ndo_stop = sipa_dummy_close, - .ndo_start_xmit = sipa_dummy_start_xmit, - .ndo_get_stats = sipa_dummy_get_stats, -}; - -static void s_setup(struct net_device *dev) -{ - ether_setup(dev); -} - -static int sipa_dummy_probe(struct platform_device *pdev) -{ - struct SIPA_DUMMY *sipa_dummy; - struct net_device *netdev; - int ret; - -#ifdef NET_NAME_PREDICTABLE - netdev = alloc_netdev( - sizeof(struct SIPA_DUMMY), - "sipa_dummy0", - NET_NAME_PREDICTABLE, - s_setup); -#else - netdev = alloc_netdev( - sizeof(struct SIPA_DUMMY), - "sipa_dummy0", - s_setup); -#endif - - if (!netdev) { - pr_err("alloc_netdev() failed.\n"); - return -ENOMEM; - } - - dummy_dev = netdev; - netdev->type = ARPHRD_ETHER; - sipa_dummy = netdev_priv(netdev); - sipa_dummy->netdev = netdev; - netdev->netdev_ops = &sipa_dummy_ops; - netdev->watchdog_timeo = 1 * HZ; - netdev->irq = 0; - netdev->dma = 0; - netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM); - random_ether_addr(netdev->dev_addr); - - netif_napi_add(netdev, - &sipa_dummy->napi, - sipa_dummy_rx_poll_handler, - SIPA_DUMMY_NAPI_WEIGHT); - - /* Register new Ethernet interface */ - ret = register_netdev(netdev); - if (ret) { - pr_err("register_netdev() failed (%d)\n", ret); - netif_napi_del(&sipa_dummy->napi); - free_netdev(netdev); - return ret; - } - - /* Set link as disconnected */ - netif_carrier_off(netdev); - platform_set_drvdata(pdev, sipa_dummy); - sipa_dummy_debugfs_mknod((void *)sipa_dummy); - napi_enable(&sipa_dummy->napi); - return 0; -} - -/* Cleanup Ethernet device driver. */ -static int sipa_dummy_remove(struct platform_device *pdev) -{ - struct SIPA_DUMMY *sipa_dummy= platform_get_drvdata(pdev); - netif_stop_queue(sipa_dummy->netdev); - napi_disable(&sipa_dummy->napi); - netif_napi_del(&sipa_dummy->napi); - unregister_netdev(sipa_dummy->netdev); - free_netdev(sipa_dummy->netdev); - platform_set_drvdata(pdev, NULL); - if (!IS_ERR_OR_NULL(dummy_root)) - debugfs_remove_recursive(dummy_root); - - return 0; -} - -#ifdef SPRD_PCIE_USE_DTS -static const struct of_device_id sipa_dummy_match_table[] = { - { .compatible = "sprd,sipa_dummy"}, - { } -}; -#endif - -static struct platform_driver sipa_dummy_driver = { - .probe = sipa_dummy_probe, - .remove = sipa_dummy_remove, - .driver = { - .owner = THIS_MODULE, - .name = "sipa_dummy", -#ifdef SPRD_PCIE_USE_DTS - .of_match_table = sipa_dummy_match_table -#endif - } -}; - -#ifndef SPRD_PCIE_USE_DTS -static struct platform_device *sipa_dummy_device; - -static int sipa_dummy_platform_device_reigster(void) -{ - int retval = -ENOMEM; - - sipa_dummy_device = platform_device_alloc("sipa_dummy", -1); - if (!sipa_dummy_device) - return retval; - - retval = platform_device_add(sipa_dummy_device); - if (retval < 0) - platform_device_put(sipa_dummy_device); - - return retval; -} -#endif - - -static int sipa_dummy_debug_show(struct seq_file *m, void *v) -{ - struct SIPA_DUMMY *sipa_dummy = (struct SIPA_DUMMY *)(m->private); - - if (!sipa_dummy) { - pr_err("invalid data, sipa_dummy is NULL\n"); - return -EINVAL; - } - - seq_puts(m, "*************************************************\n"); - seq_printf(m, "DEVICE: %s rx_busy=%d rx_evt=%d\n", - sipa_dummy->netdev->name, atomic_read(&sipa_dummy->rx_busy), - atomic_read(&sipa_dummy->rx_evt)); - seq_puts(m, "*************************************************\n"); - - return 0; -} - -static int sipa_dummy_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, sipa_dummy_debug_show, inode->i_private); -} - -static const struct file_operations sipa_dummy_debug_fops = { - .open = sipa_dummy_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int sipa_dummy_debugfs_mknod(void *data) -{ - if (!dummy_root) { - pr_err("dummy dir is NULL\n"); - return -ENXIO; - } - debugfs_create_file("stats", - 0444, - dummy_root, - data, - &sipa_dummy_debug_fops); - - return 0; -} - -static void __init sipa_dummy_debugfs_init(void) -{ - dummy_root = debugfs_create_dir("sipa_dummy", NULL); - if (!dummy_root) - pr_err("failed to create sipa_dummy debugfs dir\n"); -} - -int sipa_dummy_init(void) -{ - sipa_dummy_debugfs_init(); -#ifndef SPRD_PCIE_USE_DTS - sipa_dummy_platform_device_reigster(); -#endif - return platform_driver_register(&sipa_dummy_driver); -} -EXPORT_SYMBOL(sipa_dummy_init); - -void sipa_dummy_exit(void) -{ - platform_driver_unregister(&sipa_dummy_driver); -#ifndef SPRD_PCIE_USE_DTS - platform_device_unregister(sipa_dummy_device); -#endif -} -EXPORT_SYMBOL(sipa_dummy_exit); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_eth.c b/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_eth.c deleted file mode 100644 index c790725fe..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_eth.c +++ /dev/null @@ -1,1087 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) "sipa_eth: " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sipa_eth.h" -#include "../include/sipa.h" - -#ifndef ARPHRD_RAWIP -#define ARPHRD_RAWIP ARPHRD_NONE -#endif - -#ifdef CONFIG_PINCTRL_IPQ807x -//#define CONFIG_QCA_NSS_DRV -#endif - -#if 1//def CONFIG_QCA_NSS_DRV -#define _RMNET_NSS_H_ -#define _RMENT_NSS_H_ -struct rmnet_nss_cb { - int (*nss_create)(struct net_device *dev); - int (*nss_free)(struct net_device *dev); - int (*nss_tx)(struct sk_buff *skb); -}; -static struct rmnet_nss_cb *rmnet_nss_callbacks __rcu __read_mostly; -#ifdef CONFIG_QCA_NSS_DRV -static uint __read_mostly qca_nss_enabled = 1; -module_param( qca_nss_enabled, uint, S_IRUGO); -#define rmnet_nss_dereference(nss_cb) do { \ - rcu_read_lock(); \ - nss_cb = rcu_dereference(rmnet_nss_callbacks); \ - rcu_read_unlock(); \ -} while(0) -#else -#define rmnet_nss_dereference(nss_cb) do { nss_cb = NULL; } while(0) -#endif -#endif - -/* Device status */ -#define DEV_ON 1 -#define DEV_OFF 0 - -#define SIPA_ETH_NAPI_WEIGHT 64 -#define SIPA_ETH_IFACE_PREF "seth" -#define SIPA_ETH_VPCIE_PREF "pcie" -#define SIPA_ETH_VPCIE_IDX 8 - -#define SIPA_DUMMY_IFACE_NUM 4 - -static struct dentry *root; -static int sipa_eth_debugfs_mknod(void *root, void *data); -static void sipa_eth_poll_rx_handler (void *priv); -static u64 gro_enable; - -struct sipa_eth_netid_device * dev_list[SIPA_DUMMY_IFACE_NUM]; - - -static const unsigned char dhcp_dst_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - -//static const u8 default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3}; -//static const u8 default_dev_addr[ETH_ALEN] = {0x02, 0x50, 0xf4}; - -static inline void sipa_eth_dt_stats_init(struct sipa_eth_dtrans_stats *stats) -{ - memset(stats, 0, sizeof(*stats)); -} - -static inline void sipa_eth_rx_stats_update( - struct sipa_eth_dtrans_stats *stats, u32 len) -{ - stats->rx_sum += len; - stats->rx_cnt++; -} - -static inline void sipa_eth_tx_stats_update( - struct sipa_eth_dtrans_stats *stats, u32 len) -{ - stats->tx_sum += len; - stats->tx_cnt++; -} - -static void sipa_eth_prepare_skb(struct SIPA_ETH *sipa_eth, struct sk_buff *skb) -{ - struct iphdr *iph; - struct ipv6hdr *ipv6h; - struct net_device *dev; - unsigned int real_len = 0, payload_len = 0; - bool ip_arp = true; - - dev = sipa_eth->netdev; - - skb->protocol = eth_type_trans(skb, dev); - skb_reset_network_header(skb); - - switch (ntohs(skb->protocol)) { - case ETH_P_IP: - iph = ip_hdr(skb); - real_len = ntohs(iph->tot_len); - break; - case ETH_P_IPV6: - ipv6h = ipv6_hdr(skb); - payload_len = ntohs(ipv6h->payload_len); - real_len = payload_len + sizeof(struct ipv6hdr); - break; - case ETH_P_ARP: - real_len = arp_hdr_len(dev); - break; - default: - ip_arp = false; - break; - } - - if (ip_arp) - skb_trim(skb, real_len); - - /* TODO chechsum ... */ - skb->ip_summed = CHECKSUM_NONE; - skb->dev = dev; -} - -static int sipa_eth_rx(struct SIPA_ETH *sipa_eth, int budget) -{ - struct sk_buff *skb; - struct net_device *dev; - struct sipa_eth_dtrans_stats *dt_stats; - int netid; - int skb_cnt = 0; - int ret; - - dt_stats = &sipa_eth->dt_stats; - - if (!sipa_eth) { - pr_err("no sipa_eth device\n"); - return -EINVAL; - } - - dev = sipa_eth->netdev; - atomic_set(&sipa_eth->rx_evt, 0); - while (skb_cnt < budget) { - ret = sipa_nic_rx(&netid, &skb, skb_cnt); - if (ret) { - switch (ret) { - case -ENODEV: - pr_err("fail to find dev"); - sipa_eth->stats.rx_errors++; - dt_stats->rx_fail++; - dev->stats.rx_errors++; - break; - case -ENODATA: - atomic_set(&sipa_eth->rx_busy, 0); - break; - } - break; - } - - if (!skb) { - pr_err("recv skb is null\n"); - return -EINVAL; - } - - sipa_eth_prepare_skb(sipa_eth, skb); - - sipa_eth->stats.rx_packets++; - sipa_eth->stats.rx_bytes += skb->len; - sipa_eth_rx_stats_update(dt_stats, skb->len); - napi_gro_receive(&sipa_eth->napi, skb); - //netif_receive_skb(skb); - skb_cnt++; - } - - return skb_cnt; -} - -static int sipa_eth_rx_poll_handler(struct napi_struct *napi, int budget) -{ - struct SIPA_ETH *sipa_eth = container_of(napi, struct SIPA_ETH, napi); - int tmp = 0, pkts; - - /* If the number of pkt is more than weight(64), - * we cannot read them all with a single poll. - * When the return value of poll func equals to weight(64), - * napi structure invokes the poll func one more time by - * __raise_softirq_irqoff.(See napi_poll for details) - * So do not do napi_complete in that case. - */ -READ_AGAIN: - /* For example: - * pkts = 60, tmp = 60, budget = 4 - * if rx_evt is true, we goto READ_AGAIN, - * pkts = 4, tmp = 64, budget = 0, - * then we goto out, return 64 to napi, - * In that case, we force napi to do polling again. - */ - pkts = sipa_eth_rx(sipa_eth, budget); - tmp += pkts; - budget -= pkts; - /* - * If budget is 0 here, means we has not finished reading yet, - * so we should return a weight-number(64) to napi to ask it - * do another polling. - */ - if (!budget) - goto out; - - /* Due to a cuncurrency issue, we have to do napi_complete - * cautiously. If a socket is in the process of napi polling, - * a SIPA_RECEIVE is arriving to trigger another socket to do receiving, - * we must record it because it will be blocked by rx_busy - * at the first beginning. - * Since this SIPA_RECEIVE notification is a one-shot behaviour - * in sipa_nic. if we chose to ignore this event, we may lose - * the chance to receive forever. - */ - if (atomic_read(&sipa_eth->rx_evt)) - goto READ_AGAIN; - - /* If the number of budget is more than 0, it means the pkts - * we received is smaller than napi weight(64). - * Then we are okay to do napi_complete. - */ - if (budget) { - napi_complete(napi); - /* Test in a lab, ten threads of TCP streams, - * TPUT reaches to 1Gbps, another edge case occurs, - * rx_busy might be 0, and rx_evt might be 1, - * after we do napi_complete. - * So do rx_handler manually to prevent - * sipa_eth from stopping receiving pkts. - */ - if (atomic_read(&sipa_eth->rx_evt) || - atomic_read(&sipa_eth->rx_busy)) { - pr_debug("rx evt recv after napi complete"); - atomic_set(&sipa_eth->rx_evt, 0); - napi_schedule(&sipa_eth->napi); - } - } - -out: - return tmp; -} - -/* Attention, The whole RX is deprecated, we use sipa_dummy to rx. */ -static void sipa_eth_poll_rx_handler (void *priv) -{ - struct SIPA_ETH *sipa_eth = (struct SIPA_ETH *)priv; - - if (!sipa_eth) { - pr_err("data is NULL\n"); - return; - } - - if (!atomic_cmpxchg(&sipa_eth->rx_busy, 0, 1)) { - atomic_set(&sipa_eth->rx_evt, 0); - napi_schedule(&sipa_eth->napi); - /* Trigger a NET_RX_SOFTIRQ softirq directly, - * or there will be a delay - */ - //raise_softirq(NET_RX_SOFTIRQ); - } -} - -static void sipa_eth_flowctrl_handler(void *priv, int flowctrl) -{ - struct SIPA_ETH *sipa_eth = (struct SIPA_ETH *)priv; - struct net_device *dev = sipa_eth->netdev; - - if (flowctrl) { - netif_stop_queue(dev); - } else if (netif_queue_stopped(dev)) { - netif_wake_queue(dev); - } -} - -static void sipa_eth_notify_cb(void *priv, enum sipa_evt_type evt, - unsigned int data) -{ - struct SIPA_ETH *sipa_eth = (struct SIPA_ETH *)priv; - - switch (evt) { - case SIPA_RECEIVE: - atomic_set(&sipa_eth->rx_evt, 1); - sipa_eth_poll_rx_handler(priv); - break; - case SIPA_LEAVE_FLOWCTRL: - pr_info("SIPA LEAVE FLOWCTRL\n"); - sipa_eth_flowctrl_handler(priv, 0); - break; - case SIPA_ENTER_FLOWCTRL: - pr_info("SIPA ENTER FLOWCTRL\n"); - sipa_eth_flowctrl_handler(priv, 1); - break; - default: - break; - } -} - -static int sipa_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct SIPA_ETH *sipa_eth = netdev_priv(dev); - struct sipa_eth_init_data *pdata = sipa_eth->pdata; - struct sipa_eth_dtrans_stats *dt_stats; - int ret = 0, dhcp = 0; - int netid; - - dt_stats = &sipa_eth->dt_stats; - if (sipa_eth->state != DEV_ON) { - pr_err("called when %s is down\n", dev->name); - dt_stats->tx_fail++; - netif_carrier_off(dev); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - netid = pdata->netid; - - - if (dev->type != ARPHRD_ETHER) { - switch (skb->data[0] & 0xf0) { - case 0x40: - { - struct iphdr *ip4h = (struct iphdr *)(&skb->data[0]); - if (ip4h->protocol == IPPROTO_UDP && ip4h->saddr == 0x00000000 && ip4h->daddr == 0xFFFFFFFF) { - dhcp = 1; - } - skb->protocol = htons(ETH_P_IP); - } - break; - case 0x60: - skb->protocol = htons(ETH_P_IPV6); - break; - default: - if(skb->protocol != htons(ETH_P_ARP)) { - pr_err("unknow skb->protocol %02x\n", skb->data[0]); - goto err; - } - skb->protocol = htons(ETH_P_ARP); - arp_hdr(skb)->ar_hrd = htons(ARPHRD_ETHER); - break; - - } - skb_push(skb, ETH_HLEN); - skb_reset_mac_header(skb); - - memcpy(eth_hdr(skb)->h_source, dev->dev_addr, ETH_ALEN); - if(dhcp) - memcpy(eth_hdr(skb)->h_dest, dhcp_dst_addr, ETH_ALEN); - else - memcpy(eth_hdr(skb)->h_dest, pdata->modem_mac, ETH_ALEN); - eth_hdr(skb)->h_proto = skb->protocol; - } - - ret = sipa_nic_tx(sipa_eth->nic_id, pdata->term_type, netid, skb); - if (unlikely(ret != 0)) { - if (ret == -EAGAIN) { - /* - * resume skb, otherwise - * we may pull this skb ETH_HLEN-bytes twice - */ - if (!pdata->mac_h) - skb_push(skb, ETH_HLEN); - dt_stats->tx_fail++; - sipa_eth->stats.tx_errors++; - /* - if (ret == -EAGAIN) { - netif_stop_queue(dev); - sipa_nic_trigger_flow_ctrl_work(sipa_eth->nic_id, ret); - } - */ - return NETDEV_TX_BUSY; - } - pr_err("fail to send skb, dev 0x%p eth 0x%p nic_id %d, ret %d\n", - dev, sipa_eth, sipa_eth->nic_id, ret); - goto err; - } - - /* update netdev statistics */ - sipa_eth->stats.tx_packets++; - sipa_eth->stats.tx_bytes += skb->len; - sipa_eth_tx_stats_update(dt_stats, skb->len); - - return NETDEV_TX_OK; - -err: - sipa_eth->netdev->stats.tx_dropped++; - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; -} - -static int sipa_eth_change_dev_list_state(struct SIPA_ETH *sipa_eth, int state) { - struct sipa_eth_netid_device *netid_dev_info; - int netid = sipa_eth->pdata->netid; - - if (strncmp(sipa_eth->netdev->name, - SIPA_ETH_VPCIE_PREF, - strlen(SIPA_ETH_VPCIE_PREF))) - return 0; - - if (netid < 0 || netid >= SIPA_DUMMY_IFACE_NUM) { - pr_info("illegal netid %d\n", netid); - return -EINVAL; - } - - netid_dev_info = dev_list[netid]; - netid_dev_info->state = state; - - pr_info("set %s netid %d %s for dummy\n", - sipa_eth->netdev->name, netid, state ? "DEV_ON" : "DEV_OFF"); - return 0; -} - -/* Open interface */ -static int sipa_eth_open(struct net_device *dev) -{ - struct SIPA_ETH *sipa_eth = netdev_priv(dev); - struct sipa_eth_init_data *pdata = sipa_eth->pdata; - int ret = 0; - - pr_info("dev 0x%p eth 0x%p open %s netid %d term %d mac_h %d\n", - dev, sipa_eth, dev->name, pdata->netid, pdata->term_type, - pdata->mac_h); - ret = sipa_nic_open( - pdata->term_type, - pdata->netid, - sipa_eth_notify_cb, - (void *)sipa_eth); - - if (ret < 0) - return -EINVAL; - - sipa_eth->nic_id = ret; - sipa_eth->state = DEV_ON; - sipa_eth_dt_stats_init(&sipa_eth->dt_stats); - memset(&sipa_eth->stats, 0, sizeof(sipa_eth->stats)); - - if (!netif_carrier_ok(sipa_eth->netdev)) { - pr_info("set netif_carrier_on\n"); - netif_carrier_on(sipa_eth->netdev); - } - - atomic_set(&sipa_eth->rx_busy, 0); - sipa_eth_change_dev_list_state(sipa_eth, DEV_ON); - netif_start_queue(dev); - napi_enable(&sipa_eth->napi); - - return 0; -} - -/* Close interface */ -static int sipa_eth_close(struct net_device *dev) -{ - struct SIPA_ETH *sipa_eth = netdev_priv(dev); - pr_info("close %s!\n", dev->name); - - sipa_nic_close(sipa_eth->nic_id); - sipa_eth->state = DEV_OFF; - - napi_disable(&sipa_eth->napi); - netif_stop_queue(dev); - - sipa_eth_change_dev_list_state(sipa_eth, DEV_OFF); - return 0; -} - -static struct net_device_stats *sipa_eth_get_stats(struct net_device *dev) -{ - struct SIPA_ETH *sipa_eth = netdev_priv(dev); - - return &sipa_eth->stats; -} - -/* - * For example, if an application starts a tcp connection, - * it finally invokes tcp_connect func to send out a TCP SYN. - * In a func tcp_init_nondata_skb, the skb->ip_summed is set - * to CHECKSUM_PARTIAL. Because only the pesuode header is - * calculated and stored. It expects that the netdevice - * to calculate the checksum for TCP header&TCP paylod and store - * the final checksum into tcphdr->check. - * Then __dev_queue_xmit -> validate_xmit_skb, it check the features - * of this current network card, if it with - * NETIF_F_IP_CSUM/NETIF_F_IPV6_CSUM/NETIF_F_HW_CSUM, - * skb_checksum_help func will be invoked for this calculation. - * - * So we have to implement ndo_features_check func, since we - * have any ability to calculate a checksum for a pkt. - */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 3,11,0 )) -netdev_features_t sipa_eth_features_check(struct sk_buff *skb, struct net_device *dev, - netdev_features_t features) -{ - features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM); - - return features; -} -#endif - -static const struct net_device_ops sipa_eth_ops = { - .ndo_open = sipa_eth_open, - .ndo_stop = sipa_eth_close, - .ndo_start_xmit = sipa_eth_start_xmit, - .ndo_get_stats = sipa_eth_get_stats, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 3,11,0 )) - .ndo_features_check = sipa_eth_features_check, -#endif -}; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 3,11,0 )) -static int sipa_eth_parse_dt( - struct sipa_eth_init_data **init, - struct device *dev) -{ - struct sipa_eth_init_data *pdata = NULL; - struct device_node *np = dev->of_node; - int ret; - u32 udata, id; - s32 sdata; - - if (!np) - pr_err("dev of_node np is null\n"); - - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - id = of_alias_get_id(np, "eth"); - switch (id) { - case 0 ... 7: - snprintf(pdata->name, IFNAMSIZ, "%s%d", - SIPA_ETH_IFACE_PREF, id); - break; - case 8 ... 11: - snprintf(pdata->name, IFNAMSIZ, "%s%d", - SIPA_ETH_VPCIE_PREF, id - SIPA_ETH_VPCIE_IDX); - break; - default: - pr_err("wrong alias id from dts, id %d\n", id); - return -EINVAL; - } - - ret = of_property_read_u32(np, "sprd,netid", &sdata); - if (ret) { - pr_err("read sprd,netid ret %d\n", ret); - return ret; - } - /* dts reflect */ - pdata->netid = sdata - 1; - - ret = of_property_read_u32(np, "sprd,term-type", &udata); - if (ret) { - pr_err("read sprd,term-type ret %d\n", ret); - return ret; - } - - pdata->term_type = udata; - - pdata->mac_h = of_property_read_bool(np, "sprd,mac-header"); - - *init = pdata; - pr_debug("after dt parse, name %s netid %d term-type %d mac_h %d\n", - pdata->name, pdata->netid, pdata->term_type, pdata->mac_h); - return 0; -} -#endif - -static void s_setup(struct net_device *dev) -{ -#ifndef CONFIG_SPRD_ETHERNET - ether_setup(dev); - dev->needed_headroom = 16; - - /* Raw IP mode */ - dev->header_ops = NULL; /* No header */ - dev->type = ARPHRD_RAWIP; - dev->hard_header_len = 0; - dev->flags |= IFF_NOARP | IFF_PROMISC; - dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); - dev->addr_len = ETH_ALEN; - eth_hw_addr_random(dev); -#else - ether_setup(dev); - dev->flags |= IFF_PROMISC; -#endif -} - -static ssize_t sipa_eth_get_direct_mode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct net_device *netdev = to_net_dev(dev); - struct SIPA_ETH *sipa_eth = netdev_priv(netdev); - - - if (sipa_eth->pdata->term_type == 0x0) - return sprintf(buf, "\n %s in mode: normal\n", sipa_eth->netdev->name); - else if (sipa_eth->pdata->term_type == 0x6) - return sprintf(buf, "\n %s in mode: direct\n", sipa_eth->netdev->name); - else - return sprintf(buf, "\n %s in mode: illegal\n", sipa_eth->netdev->name); -} - -static ssize_t sipa_eth_set_direct_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct net_device *netdev = to_net_dev(dev); - struct SIPA_ETH *sipa_eth = netdev_priv(netdev); - - if (!strncmp(buf, "normal", count - 1)) { - sipa_eth->pdata->term_type = 0x0; - } else if (!strncmp(buf, "direct", count - 1)) { -#ifndef CONFIG_SPRD_ETHERNET - sipa_eth->pdata->term_type = 0x6; -#else - pr_info("mode only can be set as normal when CONFIG_SPRD_ETHERNET is enabled!\n"); - return -EINVAL; -#endif - } else { - return -EINVAL; - } - - return count; -} - -static DEVICE_ATTR(mode, 0664, sipa_eth_get_direct_mode, sipa_eth_set_direct_mode); - -static struct attribute *sipa_eth_attributes[] = { - &dev_attr_mode.attr, - NULL, -}; - -static struct attribute_group sipa_eth_attribute_group = { - .attrs = sipa_eth_attributes, -}; - -static rx_handler_result_t sipa_eth_rx_handler(struct sk_buff **pskb) -{ - struct sk_buff *skb = *pskb; - struct rmnet_nss_cb *nss_cb; - - if (!skb) - return RX_HANDLER_CONSUMED; - - //printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - - /* Check this so that we dont loop around netif_receive_skb */ - - if (skb->cb[0] == 1) { - skb->cb[0] = 0; - - return RX_HANDLER_PASS; - } - - rmnet_nss_dereference(nss_cb); - if (nss_cb) { - nss_cb->nss_tx(skb); - return RX_HANDLER_CONSUMED; - } - - return RX_HANDLER_PASS; -} - -static int sipa_eth_probe(struct platform_device *pdev) -{ - struct sipa_eth_netid_device *netid_dev_info = NULL; - struct sipa_eth_init_data *pdata = pdev->dev.platform_data; - struct net_device *netdev; - struct SIPA_ETH *sipa_eth; - char ifname[IFNAMSIZ]; - struct rmnet_nss_cb *nss_cb; - int ret; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 3,11,0 )) - if (pdev->dev.of_node && !pdata) { - ret = sipa_eth_parse_dt(&pdata, &pdev->dev); - if (ret) { - pr_err("failed to parse device tree, ret=%d\n", ret); - return ret; - } - pdev->dev.platform_data = pdata; - } -#endif - - rmnet_nss_dereference(nss_cb); - strlcpy(ifname, pdata->name, IFNAMSIZ); -#ifdef NET_NAME_PREDICTABLE - netdev = alloc_netdev( - sizeof(struct SIPA_ETH), - ifname, - NET_NAME_PREDICTABLE, - s_setup); -#else - netdev = alloc_netdev( - sizeof(struct SIPA_ETH), - ifname, - s_setup); -#endif - - if (!netdev) { - pr_err("alloc_netdev() failed.\n"); - return -ENOMEM; - } - - sipa_eth = netdev_priv(netdev); - sipa_eth_dt_stats_init(&sipa_eth->dt_stats); - sipa_eth->netdev = netdev; - sipa_eth->pdata = pdata; - atomic_set(&sipa_eth->rx_busy, 0); - atomic_set(&sipa_eth->rx_evt, 0); - netdev->netdev_ops = &sipa_eth_ops; - netdev->watchdog_timeo = 1 * HZ; - netdev->irq = 0; - netdev->dma = 0; - netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM); - random_ether_addr(netdev->dev_addr); - netdev->sysfs_groups[0] = &sipa_eth_attribute_group; - - netif_napi_add(netdev, - &sipa_eth->napi, - sipa_eth_rx_poll_handler, - SIPA_ETH_NAPI_WEIGHT); - - /* Register new Ethernet interface */ - ret = register_netdev(netdev); - if (ret) { - pr_err("register_netdev() failed (%d)\n", ret); - netif_napi_del(&sipa_eth->napi); - free_netdev(netdev); - return ret; - } - - sipa_eth->state = DEV_OFF; - /* Set link as disconnected */ - netif_carrier_off(netdev); - platform_set_drvdata(pdev, sipa_eth); - sipa_eth_debugfs_mknod(root, (void *)sipa_eth); - - if (!strncmp(netdev->name, SIPA_ETH_VPCIE_PREF, strlen(SIPA_ETH_VPCIE_PREF))) { - netid_dev_info = kzalloc(sizeof(*netid_dev_info), GFP_ATOMIC); - if (!netid_dev_info) - return -ENOMEM; - - if (nss_cb) { - int rc = nss_cb->nss_create(netdev); - if (rc) { - /* Log, but don't fail the device creation */ - netdev_err(netdev, "Device will not use NSS path: %d\n", rc); - } else { - netdev_info(netdev, "NSS context created\n"); - rtnl_lock(); - netdev_rx_handler_register(netdev, sipa_eth_rx_handler, NULL); - rtnl_unlock(); - } - } - - netid_dev_info->ndev = netdev; - netid_dev_info->napi = sipa_eth->napi; - netid_dev_info->state = DEV_OFF; - netid_dev_info->netid = pdata->netid; - dev_list[pdata->netid] = netid_dev_info; - } - //sysfs_create_group(&pdev->dev.kobj, &sipa_eth_attribute_group); - return 0; -} - -/* Cleanup Ethernet device driver. */ -static int sipa_eth_remove(struct platform_device *pdev) -{ - struct SIPA_ETH *sipa_eth = platform_get_drvdata(pdev); - struct rmnet_nss_cb *nss_cb; - rx_handler_func_t *rx_handler; - struct sipa_eth_init_data *pdata = pdev->dev.platform_data; - - - rmnet_nss_dereference(nss_cb); - rcu_read_lock(); - rx_handler = rcu_dereference(sipa_eth->netdev->rx_handler); - rcu_read_unlock(); - if (nss_cb && rx_handler == sipa_eth_rx_handler) { - rtnl_lock(); - netdev_rx_handler_unregister(sipa_eth->netdev); - rtnl_unlock(); - nss_cb->nss_free(sipa_eth->netdev); - } - - netif_napi_del(&sipa_eth->napi); - unregister_netdev(sipa_eth->netdev); - - if(dev_list[pdata->netid]) { - kfree(dev_list[pdata->netid]); - dev_list[pdata->netid] = NULL; - } - - if (!IS_ERR_OR_NULL(sipa_eth->subroot)) - debugfs_remove_recursive(sipa_eth->subroot); - free_netdev(sipa_eth->netdev); - return 0; -} - -#ifdef SPRD_PCIE_USE_DTS -static const struct of_device_id sipa_eth_match_table[] = { - { .compatible = "sprd,sipa_eth"}, - { } -}; -#endif - -static struct platform_driver sipa_eth_driver = { - .probe = sipa_eth_probe, - .remove = sipa_eth_remove, - .driver = { - .owner = THIS_MODULE, - .name = SIPA_ETH_IFACE_PREF, -#ifdef SPRD_PCIE_USE_DTS - .of_match_table = sipa_eth_match_table -#endif - } -}; - -#ifndef SPRD_PCIE_USE_DTS -static struct platform_device *sipa_eth_pdev[SIPA_ETH_NUM]; -static struct sipa_eth_init_data *sipa_eth_data[SIPA_ETH_NUM]; - -static int sipa_eth_platform_device_reigster(void) -{ - int retval = -ENOMEM; - int i; - - for(i = 0; i < SIPA_ETH_NUM; i++) { - sipa_eth_pdev[i] = platform_device_alloc(SIPA_ETH_IFACE_PREF, i); - if (!sipa_eth_pdev[i]) { - i--; - while (i >= 0) - platform_device_put(sipa_eth_pdev[i--]); - return retval; - } - } - - for (i = 0; i < SIPA_ETH_NUM; i++) { - sipa_eth_data[i] = kzalloc(sizeof(struct sipa_eth_init_data), GFP_KERNEL); - if (!sipa_eth_data[i]) { - retval = -ENOMEM; - goto err_add_pdata; - } - - snprintf(sipa_eth_data[i]->name, IFNAMSIZ, "%s%d", - SIPA_ETH_VPCIE_PREF, i); -#ifndef CONFIG_SPRD_ETHERNET - sipa_eth_data[i]->term_type = 0x6; -#else - sipa_eth_data[i]->term_type = 0x0; -#endif - sipa_eth_data[i]->netid = i; - sipa_eth_data[i]->mac_h = true; - - retval = platform_device_add_data(sipa_eth_pdev[i], sipa_eth_data[i], - sizeof(struct sipa_eth_init_data)); - if (retval) - goto err_add_pdata; - } - - for (i = 0; i < SIPA_ETH_NUM; i++) { - retval = platform_device_add(sipa_eth_pdev[i]); - if (retval < 0) { - i--; - while (i >= 0) - platform_device_del(sipa_eth_pdev[i]); - goto err_add_pdata; - } - } - - return retval; -err_add_pdata: - for (i = 0; i < SIPA_ETH_NUM; i++) { - if(sipa_eth_data[i]) - kfree(sipa_eth_data[i]); - } - for (i = 0; i < SIPA_ETH_NUM; i++) - platform_device_put(sipa_eth_pdev[i]); - return retval; -} - -static void sipa_eth_platform_device_unreigster(void) -{ - int i; - - for (i = 0; i < SIPA_ETH_NUM; i++) { - struct sipa_eth_init_data *init_data; - - init_data = dev_get_platdata(&sipa_eth_pdev[i]->dev); - platform_device_unregister(sipa_eth_pdev[i]); - } - - if (!IS_ERR_OR_NULL(root)) - debugfs_remove_recursive(root); - -} -#endif - -static int sipa_eth_debug_show(struct seq_file *m, void *v) -{ - struct SIPA_ETH *sipa_eth = (struct SIPA_ETH *)(m->private); - struct sipa_eth_dtrans_stats *stats; - struct sipa_eth_init_data *pdata; - int i; - - if (!sipa_eth) { - pr_err("invalid data, sipa_eth is NULL\n"); - return -EINVAL; - } - pdata = sipa_eth->pdata; - stats = &sipa_eth->dt_stats; - - seq_puts(m, "*************************************************\n"); - seq_printf(m, "DEVICE: %s, term_type %d, netid %d, state %s mac_h %d\n", - pdata->name, pdata->term_type, pdata->netid, - sipa_eth->state == DEV_ON ? "UP" : "DOWN", pdata->mac_h); - seq_puts(m, "\nRX statistics:\n"); - seq_printf(m, "rx_sum=%u, rx_cnt=%u\n", - stats->rx_sum, - stats->rx_cnt); - seq_printf(m, "rx_fail=%u\n", - stats->rx_fail); - - seq_printf(m, "rx_busy=%d\n", atomic_read(&sipa_eth->rx_busy)); - seq_printf(m, "rx_evt=%d\n", atomic_read(&sipa_eth->rx_evt)); - - seq_puts(m, "\nTX statistics:\n"); - seq_printf(m, "tx_sum=%u, tx_cnt=%u\n", - stats->tx_sum, - stats->tx_cnt); - seq_printf(m, "tx_fail=%u\n", - stats->tx_fail); - - for (i = 0; i < SIPA_DUMMY_IFACE_NUM; i++) { - if(dev_list[i] == NULL) { - break; - } - seq_printf(m, "dev %s, netid %d state %d\n", - dev_list[i]->ndev->name, dev_list[i]->netid, dev_list[i]->state); - } - - seq_puts(m, "*************************************************\n"); - - return 0; -} - -static int sipa_eth_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, sipa_eth_debug_show, inode->i_private); -} - -static const struct file_operations sipa_eth_debug_fops = { - .open = sipa_eth_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int debugfs_gro_enable_get(void *data, u64 *val) -{ - *val = *(u64 *)data; - return 0; -} - -static int debugfs_gro_enable_set(void *data, u64 val) -{ - *(u64 *)data = val; - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(fops_gro_enable, - debugfs_gro_enable_get, - debugfs_gro_enable_set, - "%llu\n"); - -static int sipa_eth_debugfs_mknod(void *root, void *data) -{ - struct SIPA_ETH *sipa_eth = (struct SIPA_ETH *)data; - struct dentry *subroot; - - if (!sipa_eth) - return -ENODEV; - - if (!root) - return -ENXIO; - subroot = debugfs_create_dir(sipa_eth->netdev->name, (struct dentry *)root); - if (!subroot) - return -ENOMEM; - - sipa_eth->subroot = subroot; - debugfs_create_file("stats", - 0444, - subroot, - data, - &sipa_eth_debug_fops); - - debugfs_create_file("gro_enable", - 0600, - (struct dentry *)root, - &gro_enable, - &fops_gro_enable); - - return 0; -} - -static void __init sipa_eth_debugfs_init(void) -{ - root = debugfs_create_dir(SIPA_ETH_IFACE_PREF, NULL); - if (!root) - pr_err("failed to create sipa_eth debugfs dir\n"); -} - -#ifdef CONFIG_QCA_NSS_DRV -/* - EXTRA_CFLAGS="-I$(STAGING_DIR)/usr/include/qca-nss-drv $(EXTRA_CFLAGS)" - qsdk/qca/src/data-kernel/drivers/rmnet-nss/rmnet_nss.c -*/ -#include "rmnet_nss.c" -#endif - -int sipa_eth_init(void) -{ - sipa_eth_debugfs_init(); - - RCU_INIT_POINTER(rmnet_nss_callbacks, NULL); -#ifdef CONFIG_QCA_NSS_DRV - if (qca_nss_enabled) - rmnet_nss_init(); -#endif - -#ifndef SPRD_PCIE_USE_DTS - sipa_eth_platform_device_reigster(); -#endif - return platform_driver_register(&sipa_eth_driver); -} -EXPORT_SYMBOL(sipa_eth_init); - -void sipa_eth_exit(void) -{ - int i; -#ifdef CONFIG_QCA_NSS_DRV - if (qca_nss_enabled) - rmnet_nss_exit(); -#endif - platform_driver_unregister(&sipa_eth_driver); -#ifndef SPRD_PCIE_USE_DTS - sipa_eth_platform_device_unreigster(); -#endif - for (i = 0; i < SIPA_ETH_NUM; i++) { - if(sipa_eth_data[i]){ - kfree(sipa_eth_data[i]); - } - } -} -EXPORT_SYMBOL(sipa_eth_exit); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_eth.h b/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_eth.h deleted file mode 100644 index 0519225fd..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_eth.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef _SIPA_ETH_H_ -#define _SIPA_ETH_H_ - -#include "../include/sipa.h" -#include - -#define SIPA_ETH_NUM 2 -#define SIPA_DUMMY_IFACE_NUM 4 - -/* Struct of data transfer statistics */ -struct sipa_eth_dtrans_stats { - u32 rx_sum; - u32 rx_cnt; - u32 rx_fail; - - u32 tx_sum; - u32 tx_cnt; - u32 tx_fail; -}; - -/* Device instance data. */ -struct SIPA_ETH { - int state; - atomic_t rx_busy; - atomic_t rx_evt; - struct net_device *netdev;/* Linux net device */ - enum sipa_nic_id nic_id; - struct napi_struct napi;/* Napi instance */ - /* Record data_transfer statistics */ - struct sipa_eth_dtrans_stats dt_stats; - struct net_device_stats stats;/* Net statistics */ - struct sipa_eth_init_data *pdata;/* Platform data */ - struct dentry *subroot; -}; - -struct sipa_eth_init_data { - char name[IFNAMSIZ]; - unsigned char modem_mac[ETH_ALEN]; - u32 term_type; - s32 netid; - bool mac_h; -}; - -struct sipa_eth_netid_device { - int state; - int netid; - struct net_device *ndev; - struct napi_struct napi;/* Napi instance */ - /* Record data_transfer statistics */ - struct net_device_stats stats;/* Net statistics */ -}; - -/* Device instance data. */ -struct SIPA_DUMMY { - atomic_t rx_busy; - atomic_t rx_evt; - struct net_device *netdev;/* Linux net device */ - struct napi_struct napi;/* Napi instance */ - struct net_device_stats stats;/* Net statistics */ -}; - -void sipa_dummy_recv_trigger(void); - -#endif - diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_nic.c b/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_nic.c deleted file mode 100644 index 6a69b0de1..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_nic.c +++ /dev/null @@ -1,332 +0,0 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only 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 the - * GNU General Public License for more details. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../include/sipa.h" -#include "sipa_core.h" - -#define SIPA_CP_SRC ((1 << SIPA_TERM_CP0) | \ - (1 << SIPA_TERM_CP1) | (1 << SIPA_TERM_VCP) | \ - (1 << 0x19) | (1 << 0x18)) - -struct sipa_nic_statics_info { - u32 src_mask; - int netid; -}; - -static struct sipa_nic_statics_info s_spia_nic_statics[SIPA_NIC_MAX] = { - { - .src_mask = SIPA_CP_SRC, - .netid = 0, - }, - { - .src_mask = SIPA_CP_SRC, - .netid = 1, - }, - { - .src_mask = SIPA_CP_SRC, - .netid = 2, - }, - { - .src_mask = SIPA_CP_SRC, - .netid = 3, - }, - { - .src_mask = SIPA_CP_SRC, - .netid = 4, - }, - { - .src_mask = SIPA_CP_SRC, - .netid = 5, - }, - { - .src_mask = SIPA_CP_SRC, - .netid = 6, - }, - { - .src_mask = SIPA_CP_SRC, - .netid = 7, - }, - { - .src_mask = SIPA_CP_SRC, - .netid = 8, - }, - { - .src_mask = SIPA_CP_SRC, - .netid = 9, - }, -}; - -int sipa_nic_open(enum sipa_term_type src, int netid, - sipa_notify_cb cb, void *priv) -{ - struct sipa_nic *nic = NULL; - struct sk_buff *skb; - enum sipa_nic_id nic_id = SIPA_NIC_MAX; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - if (!ctrl) { - return -EINVAL; - } - - if(!ctrl->remote_ready) - return -EINVAL; - - nic_id = netid; - dev_info(ctrl->dev, "open nic_id = %d\n", nic_id); - if (nic_id == SIPA_NIC_MAX) - return -EINVAL; - - if (ctrl->nic[nic_id]) { - nic = ctrl->nic[nic_id]; - if (atomic_read(&nic->status) == NIC_OPEN) - return -EBUSY; - while ((skb = skb_dequeue(&nic->rx_skb_q)) != NULL) - dev_kfree_skb_any(skb); - } else { - nic = kzalloc(sizeof(*nic), GFP_KERNEL); - if (!nic) - return -ENOMEM; - ctrl->nic[nic_id] = nic; - skb_queue_head_init(&nic->rx_skb_q); - } - - atomic_set(&nic->status, NIC_OPEN); - nic->nic_id = nic_id; - nic->send_ep = &ctrl->ep; - nic->need_notify = 0; - nic->src_mask = s_spia_nic_statics[nic_id].src_mask; - nic->netid = netid; - nic->cb = cb; - nic->cb_priv = priv; - nic->continue_notify = true; - - /* every receiver may receive cp packets */ - //sipa_receiver_add_nic(ctrl->receiver, nic); - sipa_skb_sender_add_nic(ctrl->sender, nic); - - return nic_id; -} -EXPORT_SYMBOL(sipa_nic_open); - -void sipa_nic_close(enum sipa_nic_id nic_id) -{ - struct sipa_nic *nic = NULL; - struct sk_buff *skb; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - if (!ctrl) { - dev_err(ctrl->dev, "sipa driver may not register\n"); - return; - } - - if (nic_id == SIPA_NIC_MAX || !ctrl->nic[nic_id]) - return; - - nic = ctrl->nic[nic_id]; - nic->continue_notify = false; - atomic_set(&nic->status, NIC_CLOSE); - /* free all pending skbs */ - while ((skb = skb_dequeue(&nic->rx_skb_q)) != NULL) - dev_kfree_skb_any(skb); - - sipa_skb_sender_remove_nic(ctrl->sender, nic); - dev_info(ctrl->dev, "close nic_id = %d\n", nic_id); -} -EXPORT_SYMBOL(sipa_nic_close); - -void sipa_nic_notify_evt(struct sipa_nic *nic, enum sipa_evt_type evt) -{ - struct sipa_core *ipa = sipa_get_ctrl_pointer(); - if (!ipa->remote_ready) { - return; - } - - if (nic->cb) - nic->cb(nic->cb_priv, evt, 0); -} -EXPORT_SYMBOL(sipa_nic_notify_evt); - -void sipa_nic_check_flow_ctrl(void) -{ - int i; - struct sipa_nic *nic; - struct sipa_core *ipa = sipa_get_ctrl_pointer(); - - for (i = 0; i < SIPA_NIC_MAX; i++) { - nic = ipa->nic[i]; - if (nic && nic->rm_flow_ctrl) { - nic->rm_flow_ctrl = false; - nic->cb(nic->cb_priv, SIPA_LEAVE_FLOWCTRL, 0); - } - } -} -EXPORT_SYMBOL(sipa_nic_check_flow_ctrl); - -void sipa_nic_try_notify_recv(struct sipa_nic *nic) -{ - if (atomic_read(&nic->status) == NIC_CLOSE) - return; - - if (nic->cb) - nic->cb(nic->cb_priv, SIPA_RECEIVE, 0); -} -EXPORT_SYMBOL(sipa_nic_try_notify_recv); - -void sipa_nic_push_skb(struct sipa_nic *nic, struct sk_buff *skb) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - atomic_inc(&ctrl->recv_cnt); - skb_queue_tail(&nic->rx_skb_q, skb); - if (nic->rx_skb_q.qlen == 1 || nic->continue_notify) - nic->need_notify = 1; -} -EXPORT_SYMBOL(sipa_nic_push_skb); - -int sipa_nic_tx(enum sipa_nic_id nic_id, enum sipa_term_type dst, - int netid, struct sk_buff *skb) -{ - int ret; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - if (!ctrl || !ctrl->sender) { - dev_err(ctrl->dev, "sipa driver may not register\n"); - return -EINVAL; - } - - if (!ctrl->remote_ready) { - ctrl->nic[nic_id]->rm_flow_ctrl = true; -// dev_err(ctrl->dev, "remote ipa not ready\n"); - return -EINPROGRESS; - } - - ret = sipa_skb_sender_send_data(ctrl->sender, skb, dst, netid); -// if (ret == -EAGAIN) -// ctrl->nic[nic_id]->flow_ctrl_status = true; - - return ret; -} -EXPORT_SYMBOL(sipa_nic_tx); - -int sipa_nic_rx(int *netid, struct sk_buff **out_skb, int index) -{ - struct sk_buff *skb; - - skb = sipa_recv_skb(netid, index); - *out_skb = skb; - - return (skb) ? 0 : -ENODATA; -} -EXPORT_SYMBOL(sipa_nic_rx); - -int sipa_nic_rx_has_data(enum sipa_nic_id nic_id) -{ - struct sipa_nic *nic; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - if (!ctrl) { - pr_err("sipa driver may not register\n"); - return -EINVAL; - } - if (!ctrl->nic[nic_id] || - atomic_read(&ctrl->nic[nic_id]->status) == NIC_CLOSE) - return 0; - - nic = ctrl->nic[nic_id]; - - return (!!nic->rx_skb_q.qlen); -} -EXPORT_SYMBOL(sipa_nic_rx_has_data); - -int sipa_nic_trigger_flow_ctrl_work(enum sipa_nic_id nic_id, int err) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - if (!ctrl) { - pr_err("sipa driver may not register\n"); - return -EINVAL; - } - - if (!ctrl->sender) - return -ENODEV; - - switch (err) { - case -EAGAIN: - //ctrl->sender->free_notify_net = true; - schedule_work(&ctrl->flow_ctrl_work); - break; - default: - dev_warn(ctrl->dev, - "don't have this flow ctrl err type\n"); - break; - } - - return 0; -} -EXPORT_SYMBOL(sipa_nic_trigger_flow_ctrl_work); - -u32 sipa_nic_get_filled_num(void) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - enum sipa_cmn_fifo_index id = ctrl->receiver->ep->recv_fifo->fifo_id; - - if (!ctrl->remote_ready) { - dev_err(ctrl->dev, "remote sipa not ready %d\n", - ctrl->remote_ready); - return 0; - } - - return ctrl->hal_ops.recv_node_from_tx_fifo(ctrl->dev, id, - ctrl->cmn_fifo_cfg, -1); -} -EXPORT_SYMBOL(sipa_nic_get_filled_num); - -void sipa_nic_restore_irq(void) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - enum sipa_cmn_fifo_index id = ctrl->receiver->ep->recv_fifo->fifo_id; - - if (!ctrl->remote_ready) { - dev_err(ctrl->dev, "remote sipa not ready %d\n", - ctrl->remote_ready); - return; - } - - ctrl->hal_ops.clr_tout_th_intr(id, ctrl->cmn_fifo_cfg); - ctrl->hal_ops.set_intr_eb(id, ctrl->cmn_fifo_cfg, true, - SIPA_FIFO_THRESHOLD_IRQ_EN | - SIPA_FIFO_DELAY_TIMER_IRQ_EN); -} -EXPORT_SYMBOL(sipa_nic_restore_irq); - -void sipa_nic_set_tx_fifo_rp(u32 rptr) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - enum sipa_cmn_fifo_index id = ctrl->receiver->ep->recv_fifo->fifo_id; - - if (!ctrl->remote_ready) { - dev_err(ctrl->dev, "remote sipa not ready %d\n", - ctrl->remote_ready); - return; - } - - ctrl->hal_ops.set_tx_fifo_rp(id, ctrl->cmn_fifo_cfg, rptr); -} -EXPORT_SYMBOL(sipa_nic_set_tx_fifo_rp); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/Makefile b/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/Makefile deleted file mode 100644 index dd44ed63a..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y += sipa_common_fifo_hal.o sipa_fifo_irq_hal.o diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_common_fifo_hal.c b/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_common_fifo_hal.c deleted file mode 100644 index 512196825..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_common_fifo_hal.c +++ /dev/null @@ -1,1234 +0,0 @@ -#include -#include - -#include "../../include/sipa.h" -#include "../sipa_core.h" -#include "sipa_fifo_phy.h" - -#define PTR_MASK(depth) (depth | (depth - 1)) - -static inline int -ipa_put_pkt_to_cache_rx_fifo(struct device *dev, - struct sipa_cmn_fifo_cfg_tag *fifo_cfg, - struct sipa_node_description_tag *desc, - u32 num) -{ - dma_addr_t dma_addr; - u32 tmp = 0, tmp1 = 0, ret = 0, index = 0, left_cnt = 0; - ssize_t node_size = sizeof(struct sipa_node_description_tag); - struct sipa_node_description_tag *node = - (struct sipa_node_description_tag *) - fifo_cfg->rx_fifo.virtual_addr; - - dma_addr = fifo_cfg->rx_fifo.fifo_base_addr_l; - - left_cnt = fifo_cfg->rx_fifo.depth - - ipa_phy_get_rx_fifo_filled_depth(fifo_cfg->fifo_reg_base); - - if (!left_cnt) - return -ENOSPC; - - if (left_cnt < num) - num = left_cnt; - - index = fifo_cfg->rx_fifo.wr & (fifo_cfg->rx_fifo.depth - 1); - if (index + num <= fifo_cfg->rx_fifo.depth) { - memcpy(node + index, desc, node_size * num); - } else { - tmp = fifo_cfg->rx_fifo.depth - index; - memcpy(node + index, desc, tmp * node_size); - tmp1 = num - tmp; - memcpy(node, desc + tmp, tmp1 * node_size); - } - - fifo_cfg->rx_fifo.wr = (fifo_cfg->rx_fifo.wr + num) & - PTR_MASK(fifo_cfg->rx_fifo.depth); - smp_wmb(); - ret = ipa_phy_update_rx_fifo_wptr(fifo_cfg->fifo_reg_base, - fifo_cfg->rx_fifo.wr); - - if (!ret) - pr_err("sipa_phy_update_rx_fifo_rptr fail\n"); - - return num; -} - -static inline u32 -ipa_recv_pkts_from_tx_fifo(struct device *dev, - struct sipa_cmn_fifo_cfg_tag *fifo_cfg, - u32 num) -{ - return ipa_phy_get_tx_fifo_filled_depth(fifo_cfg->fifo_reg_base); -} - -static int ipa_common_fifo_hal_open(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - void *cookie) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo = NULL; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("sipa don't have this id %d\n", id); - return -EINVAL; - } - - if (ipa_term_fifo->state) { - pr_err("sipa fifo_id = %d has already opened state = %d\n", - ipa_term_fifo->fifo_id, ipa_term_fifo->state); - return -EBUSY; - } - - ipa_phy_set_rx_fifo_total_depth(ipa_term_fifo->fifo_reg_base, - ipa_term_fifo->rx_fifo.depth); - ipa_phy_set_rx_fifo_addr(ipa_term_fifo->fifo_reg_base, - ipa_term_fifo->rx_fifo.fifo_base_addr_l, - ipa_term_fifo->rx_fifo.fifo_base_addr_h); - - ipa_phy_set_tx_fifo_total_depth(ipa_term_fifo->fifo_reg_base, - ipa_term_fifo->tx_fifo.depth); - ipa_phy_set_tx_fifo_addr(ipa_term_fifo->fifo_reg_base, - ipa_term_fifo->tx_fifo.fifo_base_addr_l, - ipa_term_fifo->tx_fifo.fifo_base_addr_h); - - ipa_phy_set_cur_term_num(ipa_term_fifo->fifo_reg_base, - ipa_term_fifo->cur); - ipa_phy_set_dst_term_num(ipa_term_fifo->fifo_reg_base, - ipa_term_fifo->dst); - - ipa_phy_update_rx_fifo_rptr(ipa_term_fifo->fifo_reg_base, 0); - ipa_phy_update_rx_fifo_wptr(ipa_term_fifo->fifo_reg_base, 0); - ipa_phy_update_tx_fifo_rptr(ipa_term_fifo->fifo_reg_base, 0); - ipa_phy_update_tx_fifo_wptr(ipa_term_fifo->fifo_reg_base, 0); - ipa_phy_clear_stop_receive(ipa_term_fifo->fifo_reg_base); - - ipa_term_fifo->rx_fifo.rd = 0; - ipa_term_fifo->rx_fifo.wr = 0; - ipa_term_fifo->tx_fifo.rd = 0; - ipa_term_fifo->tx_fifo.wr = 0; - - ipa_term_fifo->fifo_name = cookie; - ipa_term_fifo->state = true; - - return 0; -} - -static int ipa_common_fifo_hal_close(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("sipa don't have this id %d\n", id); - return -EINVAL; - } - - ipa_phy_set_rx_fifo_total_depth(ipa_term_fifo->fifo_reg_base, 0); - ipa_phy_set_tx_fifo_total_depth(ipa_term_fifo->fifo_reg_base, 0); - - ipa_phy_update_rx_fifo_rptr(ipa_term_fifo->fifo_reg_base, 0); - ipa_phy_update_rx_fifo_wptr(ipa_term_fifo->fifo_reg_base, 0); - ipa_phy_update_tx_fifo_rptr(ipa_term_fifo->fifo_reg_base, 0); - ipa_phy_update_tx_fifo_wptr(ipa_term_fifo->fifo_reg_base, 0); - - ipa_term_fifo->rx_fifo.rd = 0; - ipa_term_fifo->rx_fifo.wr = 0; - ipa_term_fifo->tx_fifo.rd = 0; - ipa_term_fifo->tx_fifo.wr = 0; - - ipa_term_fifo->state = 0; - - return 0; -} - -static int -ipa_common_fifo_hal_set_rx_depth(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 depth) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("sipa don't have this id %d\n", id); - return -EINVAL; - } - - return ipa_phy_set_rx_fifo_total_depth(ipa_term_fifo->fifo_reg_base, - depth); -} - -static u32 -ipa_common_fifo_hal_get_rx_depth(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("sipa don't have this id %d\n", id); - return 0; - } - - return ipa_phy_get_rx_fifo_total_depth(ipa_term_fifo->fifo_reg_base); -} - -static int -ipa_common_fifo_hal_set_tx_depth(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 depth) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("sipa don't have this id %d\n", id); - return 0; - } - - return ipa_phy_set_tx_fifo_total_depth(ipa_term_fifo->fifo_reg_base, - depth); -} - -static u32 -ipa_common_fifo_hal_get_tx_depth(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("sipa don't have this id %d\n", id); - return 0; - } - - return ipa_phy_get_tx_fifo_total_depth(ipa_term_fifo->fifo_reg_base); -} - -static int -ipa_common_fifo_hal_set_intr_drop_packet(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, sipa_irq_notify_cb cb) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("sipa don't have this id %d\n", id); - return -EINVAL; - } - - if (enable) - return ipa_phy_enable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_DROP_PACKET_OCCUR_INT_EN); - else - return ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_DROP_PACKET_OCCUR_INT_EN); -} - -static int -ipa_common_fifo_hal_set_intr_error_code(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, sipa_irq_notify_cb cb) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("sipa don't have this id %d\n", id); - return -EINVAL; - } - - if (enable) - return ipa_phy_enable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_ERRORCODE_IN_TX_FIFO_EN); - else - return ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_ERRORCODE_IN_TX_FIFO_EN); -} - -static int -ipa_common_fifo_hal_set_intr_timeout(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, u32 time, - sipa_irq_notify_cb cb) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("sipa don't have this id %d\n", id); - return -EINVAL; - } - - if (enable) { - ret = ipa_phy_set_tx_fifo_interrupt_delay_timer( - ipa_term_fifo->fifo_reg_base, - time); - if (ret) - ret = ipa_phy_enable_int_bit( - ipa_term_fifo->fifo_reg_base, - IPA_TXFIFO_INT_DELAY_TIMER_SW_EN); - else - pr_err("fifo(%d) set timeout threshold fail\n", id); - } else { - ret = ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TXFIFO_INT_DELAY_TIMER_SW_EN); - } - - return ret; -} - -static int -ipa_common_fifo_hal_set_hw_intr_timeout(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, u32 time, - sipa_irq_notify_cb cb) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - if (enable) { - ret = ipa_phy_set_tx_fifo_interrupt_delay_timer( - ipa_term_fifo->fifo_reg_base, time); - if (!ret) - ret = ipa_phy_enable_int_bit( - ipa_term_fifo->fifo_reg_base, - IPA_TX_FIFO_DELAY_TIMER_EN); - else - pr_err("fifo(%d) set timeout threshold fail\n", id); - } else { - ret = ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TX_FIFO_DELAY_TIMER_EN); - } - - return ret; -} - -static int -ipa_common_fifo_hal_set_intr_threshold(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, u32 cnt, - sipa_irq_notify_cb cb) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - if (enable) { - ret = ipa_phy_set_tx_fifo_interrupt_threshold( - ipa_term_fifo->fifo_reg_base, cnt); - if (!ret) { - ret = ipa_phy_enable_int_bit( - ipa_term_fifo->fifo_reg_base, - IPA_TXFIFO_INT_THRESHOLD_ONESHOT_EN); - } else { - pr_err("fifo(%d) set threshold fail\n", id); - } - } else { - ret = - ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TXFIFO_INT_THRESHOLD_ONESHOT_EN); - } - - return ret; -} - -static int -ipa_common_fifo_hal_set_hw_intr_thres(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, u32 cnt, - sipa_irq_notify_cb cb) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - if (enable) { - ret = ipa_phy_set_tx_fifo_interrupt_threshold( - ipa_term_fifo->fifo_reg_base, cnt); - if (!ret) - ret = ipa_phy_enable_int_bit( - ipa_term_fifo->fifo_reg_base, - IPA_TX_FIFO_THRESHOLD_EN); - else - pr_err("fifo(%d) set threshold fail\n", id); - } else { - ret = ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TX_FIFO_THRESHOLD_EN); - } - - return ret; -} - -static int -ipa_common_fifo_hal_set_src_dst_term(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 src, u32 dst) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - ret = ipa_phy_set_cur_term_num(ipa_term_fifo->fifo_reg_base, src); - if (ret) { - pr_err("fifo %d set cur failed\n", id); - return ret; - } - - ret = ipa_phy_set_dst_term_num(ipa_term_fifo->fifo_reg_base, dst); - if (ret) { - pr_err("fifo %d set dst failed\n", id); - return ret; - } - - return 0; -} - -static int -ipa_common_fifo_hal_enable_local_flowctrl_intr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag * - cfg_base, u32 enable, - u32 irq_mode, - sipa_irq_notify_cb cb) -{ - int ret; - u32 irq; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - switch (irq_mode) { - case 0: - irq = IPA_RX_FIFO_INT_EXIT_FLOW_CTRL_EN; - break; - case 1: - irq = IPA_RX_FIFO_INT_ENTER_FLOW_CTRL_EN; - break; - case 2: - irq = IPA_RX_FIFO_INT_EXIT_FLOW_CTRL_EN | - IPA_RX_FIFO_INT_ENTER_FLOW_CTRL_EN; - break; - default: - pr_err("don't have this %d irq type\n", irq_mode); - return -EINVAL; - } - - if (enable) { - ret = ipa_phy_enable_int_bit(ipa_term_fifo->fifo_reg_base, irq); - if (ret) { - pr_err("fifo_id = %d irq_mode = %d set failed\n", - id, irq); - return ret; - } - } else { - ret = ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - irq); - } - - return ret; -} - -static int -ipa_common_fifo_hal_enable_remote_flowctrl_intr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag * - cfg_base, u32 work_mode, - u32 tx_entry_watermark, - u32 tx_exit_watermark, - u32 rx_entry_watermark, - u32 rx_exit_watermark) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - ret = ipa_phy_set_tx_fifo_exit_flow_ctrl_watermark( - ipa_term_fifo->fifo_reg_base, tx_exit_watermark); - if (unlikely(!ret)) { - pr_err("fifo_id = %d tx_exit_watermark(0x%x) failed\n", - id, tx_exit_watermark); - return ret; - } - - ret = ipa_phy_set_tx_fifo_entry_flow_ctrl_watermark( - ipa_term_fifo->fifo_reg_base, tx_entry_watermark); - if (unlikely(!ret)) { - pr_err("fifo_id = %d tx_entry_watermark(0x%x) failed\n", - id, tx_entry_watermark); - return ret; - } - - ret = ipa_phy_set_rx_fifo_exit_flow_ctrl_watermark( - ipa_term_fifo->fifo_reg_base, rx_exit_watermark); - if (unlikely(!ret)) { - pr_err("fifo_id = %d rx_exit_watermark(0x%x) failed\n", - id, rx_exit_watermark); - return ret; - } - - ret = ipa_phy_set_rx_fifo_entry_flow_ctrl_watermark( - ipa_term_fifo->fifo_reg_base, rx_entry_watermark); - if (unlikely(!ret)) { - pr_err("fifo_id = %d rx_entry_watermark(0x%x) failed\n", - id, rx_entry_watermark); - return ret; - } - - ret = ipa_phy_set_flow_ctrl_config(ipa_term_fifo->fifo_reg_base, - work_mode); - - return ret; -} - -static int -ipa_common_fifo_hal_set_interrupt_intr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, - sipa_irq_notify_cb cb) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - if (enable) { - ret = ipa_phy_enable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TX_FIFO_INTR_SW_BIT_EN); - } else { - ret = ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TX_FIFO_INTR_SW_BIT_EN); - } - - return ret; -} - -static int -ipa_common_fifo_hal_set_intr_txfifo_overflow(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag * - cfg_base, u32 enable, - sipa_irq_notify_cb cb) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - if (enable) { - ret = ipa_phy_enable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TXFIFO_OVERFLOW_EN); - } else { - ret = ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TXFIFO_OVERFLOW_EN); - } - - return ret; -} - -static int -ipa_common_fifo_hal_set_intr_txfifo_full(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, sipa_irq_notify_cb cb) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - if (enable) { - ret = ipa_phy_enable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TXFIFO_FULL_INT_EN); - } else { - ret = ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TXFIFO_FULL_INT_EN); - } - - return ret; -} - -/** - * Description: Receive Node from tx fifo. - * Input: - * @id: The FIFO id that need to be operated. - * @pkt: The node that need to be stored address. - * @num: The num of receive. - * OUTPUT: - * @The num that has be received from tx fifo successful. - * Note: - */ -static int -ipa_common_fifo_hal_put_node_to_rx_fifo(struct device *dev, - enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - struct sipa_node_description_tag *node, - u32 force_intr, u32 num) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - return ipa_put_pkt_to_cache_rx_fifo(dev, ipa_term_fifo, - node, num); -} - -static u32 -ipa_common_fifo_hal_get_left_cnt(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base) -{ - u32 left_cnt; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo = NULL; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return 0; - } - - left_cnt = - ipa_phy_get_tx_fifo_total_depth(ipa_term_fifo->fifo_reg_base) - - ipa_phy_get_tx_fifo_filled_depth(ipa_term_fifo->fifo_reg_base); - - return left_cnt; -} - -/* - * Description: Send Node to rx fifo. - * Input: - * id: The FIFO id that need to be operated. - * pkt: The node address that need send to rx fifo. - * num: The number of need to send. - * OUTPUT: - * The number that has get from tx fifo successful. - * Note: - */ -static u32 -ipa_common_fifo_hal_recv_node_from_tx_fifo(struct device *dev, - enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag * - cfg_base, u32 num) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return 0; - } - - return ipa_recv_pkts_from_tx_fifo(dev, ipa_term_fifo, num); -} - -static void -ipa_common_fifo_hal_get_rx_ptr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 *wr, u32 *rd) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return; - } - - if (rd) - *rd = ipa_phy_get_rx_fifo_rptr(ipa_term_fifo->fifo_reg_base); - if (wr) - *wr = ipa_phy_get_rx_fifo_wptr(ipa_term_fifo->fifo_reg_base); -} - -static void -ipa_common_fifo_hal_get_tx_ptr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 *wr, u32 *rd) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return; - } - - if (rd) - *rd = ipa_phy_get_tx_fifo_rptr(ipa_term_fifo->fifo_reg_base); - if (wr) - *wr = ipa_phy_get_tx_fifo_wptr(ipa_term_fifo->fifo_reg_base); -} - -static void -ipa_common_fifo_hal_get_filled_depth(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 *rx_filled, u32 *tx_filled) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - void __iomem *reg_base; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return; - } - - reg_base = ipa_term_fifo->fifo_reg_base; - if (tx_filled) - *tx_filled = ipa_phy_get_tx_fifo_filled_depth(reg_base); - if (rx_filled) - *rx_filled = ipa_phy_get_rx_fifo_filled_depth(reg_base); -} - -static u32 -ipa_common_fifo_hal_get_tx_full_status(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return 0; - } - - return ipa_phy_get_tx_fifo_full_status(ipa_term_fifo->fifo_reg_base); -} - -static u32 -ipa_common_fifo_hal_get_tx_empty_status(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return 0; - } - - return ipa_phy_get_tx_fifo_empty_status(ipa_term_fifo->fifo_reg_base); -} - -static u32 -ipa_common_fifo_hal_get_rx_full_status(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return 0; - } - - return ipa_phy_get_rx_fifo_full_status(ipa_term_fifo->fifo_reg_base); -} - -static u32 -ipa_common_fifo_hal_get_rx_empty_status(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return 0; - } - - return ipa_phy_get_rx_fifo_empty_status(ipa_term_fifo->fifo_reg_base); -} - -static bool -ipa_common_fifo_hal_set_rx_fifo_wptr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 wptr) -{ - u32 ret; - u32 rx_wptr; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return false; - } - - rx_wptr = ipa_phy_get_rx_fifo_wptr(ipa_term_fifo->fifo_reg_base); - - if (wptr != rx_wptr) { - wptr = wptr & PTR_MASK(ipa_term_fifo->rx_fifo.depth); - ipa_term_fifo->rx_fifo.wr = wptr; - ret = ipa_phy_update_rx_fifo_wptr(ipa_term_fifo->fifo_reg_base, - wptr); - if (!ret) { - pr_err("fifo id = %d update rx fifo wptr = 0x%x failed !!!", - id, wptr); - return false; - } - } - - return true; -} - -static bool -ipa_common_fifo_hal_set_tx_fifo_wptr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 wptr) -{ - u32 ret; - u32 tx_wptr; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return false; - } - - tx_wptr = ipa_phy_get_tx_fifo_wptr(ipa_term_fifo->fifo_reg_base); - - if (wptr != tx_wptr) { - wptr = wptr & PTR_MASK(ipa_term_fifo->rx_fifo.depth); - ipa_term_fifo->tx_fifo.wr = wptr; - ret = ipa_phy_update_tx_fifo_wptr(ipa_term_fifo->fifo_reg_base, - wptr); - if (!ret) { - pr_err("fifo id = %d update tx fifo wptr = 0x%x failed !!!", - id, wptr); - return false; - } - } - - return true; -} - -static int -ipa_common_fifo_hal_set_rx_tx_fifo_ptr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 rx_rd, u32 rx_wr, - u32 tx_rd, u32 tx_wr) -{ - int ret = 0, ret1 = 0; - u32 rx_rptr = 0, rx_wptr = 0; - u32 tx_rptr = 0, tx_wptr = 0; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - tx_wptr = ipa_phy_get_tx_fifo_wptr(ipa_term_fifo->fifo_reg_base); - tx_rptr = ipa_phy_get_tx_fifo_rptr(ipa_term_fifo->fifo_reg_base); - rx_wptr = ipa_phy_get_rx_fifo_wptr(ipa_term_fifo->fifo_reg_base); - rx_rptr = ipa_phy_get_rx_fifo_rptr(ipa_term_fifo->fifo_reg_base); - - if (rx_rd != rx_rptr) { - rx_rd = rx_rd & PTR_MASK(ipa_term_fifo->rx_fifo.depth); - ipa_term_fifo->rx_fifo.rd = rx_rd; - ret = ipa_phy_update_rx_fifo_rptr(ipa_term_fifo->fifo_reg_base, - rx_rd); - if (!ret) { - ret1 = -EIO; - pr_err("update rx fifo rptr = 0x%x failed !!!", rx_rd); - } - } - - if (rx_wr != rx_wptr) { - rx_wr = rx_wr & PTR_MASK(ipa_term_fifo->rx_fifo.depth); - ipa_term_fifo->rx_fifo.wr = rx_wr; - ret = ipa_phy_update_rx_fifo_wptr(ipa_term_fifo->fifo_reg_base, - rx_wr); - if (!ret) { - ret1 = -EIO; - pr_err("update rx fifo wptr = 0x%x failed !!!", rx_wr); - } - } - - if (tx_rd != tx_rptr) { - tx_rd = tx_rd & PTR_MASK(ipa_term_fifo->rx_fifo.depth); - ipa_term_fifo->tx_fifo.rd = tx_rd; - ret = ipa_phy_update_tx_fifo_rptr(ipa_term_fifo->fifo_reg_base, - tx_rd); - if (!ret) { - ret1 = -EIO; - pr_err("update tx fifo rptr = 0x%x failed !!!", tx_rd); - } - } - - if (tx_wr != tx_wptr) { - tx_wr = tx_wr & PTR_MASK(ipa_term_fifo->rx_fifo.depth); - ipa_term_fifo->tx_fifo.wr = tx_wr; - ret = ipa_phy_update_tx_fifo_wptr(ipa_term_fifo->fifo_reg_base, - tx_wr); - if (!ret) { - ret1 = -EIO; - pr_err("update tx fifo wptr = 0x%x failed !!!", tx_wr); - } - } - - return ret1; -} - -static int -ipa_common_fifo_hal_ctrl_receive(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - bool stop) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - if (stop) - return ipa_phy_stop_receive(ipa_term_fifo->fifo_reg_base); - else - return ipa_phy_clear_stop_receive(ipa_term_fifo->fifo_reg_base); -} - -static struct sipa_node_description_tag * -ipa_common_fifo_hal_get_tx_fifo_rp(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 index) -{ - u32 tmp; - struct sipa_cmn_fifo_cfg_tag *fifo_cfg; - struct sipa_node_description_tag *node; - - if (unlikely(id >= SIPA_FIFO_MAX)) - return NULL; - - fifo_cfg = cfg_base + id; - node = (struct sipa_node_description_tag *) - fifo_cfg->tx_fifo.virtual_addr; - - if (unlikely(!node)) - return NULL; - - tmp = (fifo_cfg->tx_fifo.rd + index) & (fifo_cfg->tx_fifo.depth - 1); - - return node + tmp; -} - -static struct sipa_node_description_tag * -ipa_common_fifo_hal_get_rx_fifo_wr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 index) -{ - u32 tmp; - struct sipa_cmn_fifo_cfg_tag *fifo_cfg; - struct sipa_node_description_tag *node; - - if (unlikely(id >= SIPA_FIFO_MAX)) - return NULL; - - fifo_cfg = cfg_base + id; - node = (struct sipa_node_description_tag *) - fifo_cfg->rx_fifo.virtual_addr; - - if (unlikely(!node)) - return NULL; - - if (index >= fifo_cfg->rx_fifo.depth) - return NULL; - - tmp = (fifo_cfg->rx_fifo.wr + index) & (fifo_cfg->rx_fifo.depth - 1); - - return node + tmp; -} - -static int ipa_common_fifo_hal_set_tx_fifo_rp(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag * - cfg_base, u32 tx_rd) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *fifo_cfg; - - if (unlikely(id >= SIPA_FIFO_MAX)) - return -EINVAL; - - fifo_cfg = cfg_base + id; - fifo_cfg->tx_fifo.rd = (fifo_cfg->tx_fifo.rd + tx_rd) & - PTR_MASK(fifo_cfg->tx_fifo.depth); - ret = ipa_phy_update_tx_fifo_rptr(fifo_cfg->fifo_reg_base, - fifo_cfg->tx_fifo.rd); - - if (ret) { - pr_err("update tx fifo rptr fail !!!\n"); - return -EINVAL; - } - - return 0; -} - -static int ipa_common_fifo_hal_set_rx_fifo_wr(struct device *dev, - enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag * - cfg_base, u32 num) -{ - int ret; - dma_addr_t dma_addr; - struct sipa_cmn_fifo_cfg_tag *fifo_cfg; - u32 tmp = 0, tmp1 = 0, index = 0, left_cnt = 0; - ssize_t node_size = sizeof(struct sipa_node_description_tag); - - if (unlikely(id >= SIPA_FIFO_MAX)) - return -EINVAL; - - fifo_cfg = cfg_base + id; - dma_addr = fifo_cfg->rx_fifo.fifo_base_addr_l; - - left_cnt = fifo_cfg->rx_fifo.depth - - ipa_phy_get_rx_fifo_filled_depth(fifo_cfg->fifo_reg_base); - - if (!left_cnt) - return -ENOSPC; - - if (left_cnt < num) - num = left_cnt; - - index = fifo_cfg->rx_fifo.wr & (fifo_cfg->rx_fifo.depth - 1); - if (index + num <= fifo_cfg->rx_fifo.depth) { - dma_sync_single_for_device(dev, dma_addr + index * node_size, - node_size * num, DMA_TO_DEVICE); - } else { - tmp = fifo_cfg->rx_fifo.depth - index; - dma_sync_single_for_device(dev, dma_addr + index * node_size, - node_size * tmp, DMA_TO_DEVICE); - tmp1 = num - tmp; - dma_sync_single_for_device(dev, dma_addr, - node_size * tmp1, DMA_TO_DEVICE); - } - - fifo_cfg->rx_fifo.wr = (fifo_cfg->rx_fifo.wr + num) & - PTR_MASK(fifo_cfg->rx_fifo.depth); - ret = ipa_phy_update_rx_fifo_wptr(fifo_cfg->fifo_reg_base, - fifo_cfg->rx_fifo.wr); - - if (ret) { - pr_err("update rx fifo rptr fail !!!\n"); - return -EIO; - } - - return 0; -} - -static int ipa_common_fifo_set_intr_eb(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - bool eb, u32 type) -{ - struct sipa_cmn_fifo_cfg_tag *fifo_cfg; - - if (unlikely(id >= SIPA_FIFO_MAX)) - return -EINVAL; - - fifo_cfg = cfg_base + id; - - if (eb) - return ipa_phy_enable_int_bit(fifo_cfg->fifo_reg_base, type); - else - return ipa_phy_disable_int_bit(fifo_cfg->fifo_reg_base, type); -} - -static void ipa_common_fifo_clr_tout_th_intr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag * - cfg_base) -{ - struct sipa_cmn_fifo_cfg_tag *fifo_cfg; - - if (unlikely(id >= SIPA_FIFO_MAX)) - return; - - fifo_cfg = cfg_base + id; - - ipa_phy_clear_int(fifo_cfg->fifo_reg_base, - IPA_TX_FIFO_TIMER_CLR_BIT | - IPA_TX_FIFO_THRESHOLD_CLR_BIT); -} - -void sipa_fifo_ops_init(struct sipa_fifo_hal_ops *ops) -{ - ops->open = ipa_common_fifo_hal_open; - - ops->close = ipa_common_fifo_hal_close; - - ops->enable_remote_flowctrl_intr = - ipa_common_fifo_hal_enable_remote_flowctrl_intr; - - ops->enable_local_flowctrl_intr = - ipa_common_fifo_hal_enable_local_flowctrl_intr; - - ops->get_left_cnt = ipa_common_fifo_hal_get_left_cnt; - - ops->put_node_to_rx_fifo = - ipa_common_fifo_hal_put_node_to_rx_fifo; - - ops->recv_node_from_tx_fifo = - ipa_common_fifo_hal_recv_node_from_tx_fifo; - - ops->set_intr_drop_packet = - ipa_common_fifo_hal_set_intr_drop_packet; - - ops->set_intr_error_code = - ipa_common_fifo_hal_set_intr_error_code; - - ops->set_intr_threshold = - ipa_common_fifo_hal_set_intr_threshold; - - ops->set_intr_timeout = - ipa_common_fifo_hal_set_intr_timeout; - - ops->set_hw_intr_thres = - ipa_common_fifo_hal_set_hw_intr_thres; - - ops->set_hw_intr_timeout = - ipa_common_fifo_hal_set_hw_intr_timeout; - - ops->set_interrupt_intr = - ipa_common_fifo_hal_set_interrupt_intr; - - ops->set_intr_txfifo_full = - ipa_common_fifo_hal_set_intr_txfifo_full; - - ops->set_intr_txfifo_overflow = - ipa_common_fifo_hal_set_intr_txfifo_overflow; - - ops->set_rx_depth = - ipa_common_fifo_hal_set_rx_depth; - - ops->set_tx_depth = - ipa_common_fifo_hal_set_tx_depth; - - ops->get_rx_depth = - ipa_common_fifo_hal_get_rx_depth; - - ops->get_tx_depth = - ipa_common_fifo_hal_get_tx_depth; - - ops->get_tx_ptr = - ipa_common_fifo_hal_get_tx_ptr; - - ops->get_rx_ptr = - ipa_common_fifo_hal_get_rx_ptr; - - ops->get_filled_depth = - ipa_common_fifo_hal_get_filled_depth; - - ops->get_tx_empty_status = - ipa_common_fifo_hal_get_tx_empty_status; - - ops->get_tx_full_status = - ipa_common_fifo_hal_get_tx_full_status; - - ops->get_rx_empty_status = - ipa_common_fifo_hal_get_rx_empty_status; - - ops->get_rx_full_status = - ipa_common_fifo_hal_get_rx_full_status; - - ops->set_rx_tx_fifo_ptr = - ipa_common_fifo_hal_set_rx_tx_fifo_ptr; - - ops->set_tx_fifo_wptr = - ipa_common_fifo_hal_set_tx_fifo_wptr; - - ops->set_rx_fifo_wptr = - ipa_common_fifo_hal_set_rx_fifo_wptr; - - ops->set_src_dst_term = - ipa_common_fifo_hal_set_src_dst_term; - - ops->ctrl_receive = - ipa_common_fifo_hal_ctrl_receive; - - ops->set_tx_fifo_rp = ipa_common_fifo_hal_set_tx_fifo_rp; - ops->get_tx_fifo_rp = ipa_common_fifo_hal_get_tx_fifo_rp; - ops->get_rx_fifo_wr = ipa_common_fifo_hal_get_rx_fifo_wr; - ops->set_rx_fifo_wr = ipa_common_fifo_hal_set_rx_fifo_wr; - - ops->set_intr_eb = ipa_common_fifo_set_intr_eb; - ops->clr_tout_th_intr = ipa_common_fifo_clr_tout_th_intr; -} -EXPORT_SYMBOL(sipa_fifo_ops_init); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_fifo_irq_hal.c b/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_fifo_irq_hal.c deleted file mode 100644 index 36fa1dcc0..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_fifo_irq_hal.c +++ /dev/null @@ -1,74 +0,0 @@ -#include "../../include/sipa.h" - -#include "../sipa_core.h" -#include "sipa_fifo_phy.h" - -static void ipa_fifo_traverse_int_bit(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *ipa_cfg) -{ - void __iomem *fifo_base; - u32 clr_sts = 0; - u32 int_status = 0; - - fifo_base = ipa_cfg->fifo_reg_base; - int_status = ipa_phy_get_fifo_all_int_sts(fifo_base); - - if (!(int_status & IPA_INT_STS_GROUP)) - return; - - if (int_status & IPA_INT_EXIT_FLOW_CTRL_STS) { - ipa_cfg->exit_flow_ctrl_cnt++; - clr_sts |= IPA_EXIT_FLOW_CONTROL_CLR_BIT; - } - - if (int_status & IPA_INT_ERRORCODE_IN_TX_FIFO_STS) - clr_sts |= IPA_ERROR_CODE_INTR_CLR_BIT; - - if (int_status & IPA_INT_ENTER_FLOW_CTRL_STS) { - ipa_cfg->enter_flow_ctrl_cnt++; - clr_sts |= IPA_ENTRY_FLOW_CONTROL_CLR_BIT; - } - - if (int_status & IPA_INT_INTR_BIT_STS) - clr_sts |= IPA_TX_FIFO_INTR_CLR_BIT; - - if (int_status & IPA_INT_THRESHOLD_STS || - int_status & IPA_INT_DELAY_TIMER_STS) { - ipa_phy_disable_int_bit(ipa_cfg->fifo_reg_base, - IPA_TX_FIFO_THRESHOLD_EN | - IPA_TX_FIFO_DELAY_TIMER_EN); - clr_sts |= IPA_TX_FIFO_THRESHOLD_CLR_BIT | - IPA_TX_FIFO_TIMER_CLR_BIT; - } - - if (int_status & IPA_INT_DROP_PACKT_OCCUR) - clr_sts |= IPA_DROP_PACKET_INTR_CLR_BIT; - - if (int_status & IPA_INT_TXFIFO_OVERFLOW_STS) - clr_sts |= IPA_TX_FIFO_OVERFLOW_CLR_BIT; - - if (int_status & IPA_INT_TXFIFO_FULL_INT_STS) - clr_sts |= IPA_TX_FIFO_FULL_INT_CLR_BIT; - - if (ipa_cfg->irq_cb) - ipa_cfg->irq_cb(ipa_cfg->priv, int_status, id); - else - pr_err("Don't register this fifo(%d) irq callback\n", id); - - ipa_phy_clear_int(ipa_cfg->fifo_reg_base, clr_sts); -} - -int sipa_int_callback_func(int evt, void *cookie) -{ - struct sipa_core *ipa = sipa_get_ctrl_pointer(); - - if (ipa->remote_ready) { - ipa_fifo_traverse_int_bit(SIPA_FIFO_PCIE_DL, - &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_DL]); - ipa_fifo_traverse_int_bit(SIPA_FIFO_PCIE_UL, - &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_UL]); - } - - return 0; -} -EXPORT_SYMBOL(sipa_int_callback_func); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_fifo_phy.h b/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_fifo_phy.h deleted file mode 100644 index d578585c2..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_fifo_phy.h +++ /dev/null @@ -1,1413 +0,0 @@ -#ifndef _IPA_CP0_FIFO_PHY_H_ -#define _IPA_CP0_FIFO_PHY_H_ - -#include - -/* Common fifo reg */ -#define IPA_COMMON_RX_FIFO_DEPTH 0x00UL -#define IPA_COMMON_RX_FIFO_WR 0x04UL -#define IPA_COMMON_RX_FIFO_RD 0x08UL -#define IPA_COMMON_TX_FIFO_DEPTH 0x0CUL -#define IPA_COMMON_TX_FIFO_WR 0x10UL -#define IPA_COMMON_TX_FIFO_RD 0x14UL -#define IPA_COMMON_RX_FIFO_ADDRL 0x18UL -#define IPA_COMMON_RX_FIFO_ADDRH 0x1CUL -#define IPA_COMMON_TX_FIFO_ADDRL 0x20UL -#define IPA_COMMON_TX_FIFO_ADDRH 0x24UL -#define IPA_PERFETCH_FIFO_CTL 0x28UL -#define IPA_INT_GEN_CTL_TX_FIFO_VALUE 0x2CUL -#define IPA_INT_GEN_CTL_EN 0x30UL -#define IPA_DROP_PACKET_CNT 0x34UL -#define IPA_FLOW_CTRL_CONFIG 0x38UL -#define IPA_TX_FIFO_FLOW_CTRL 0x3CUL -#define IPA_RX_FIFO_FLOW_CTRL 0x40UL -#define IPA_RX_FIFO_FULL_NEG_PULSE_NUM 0x44UL -#define IPA_INT_GEN_CTL_CLR 0x48UL -#define IPA_INTR_RX_FIFO_FULL_ADDR_HIGH 0x4CUL -#define IPA_INTR_MEM_WR_ADDR_LOW 0x50UL -#define IPA_RXFIFO_FULL_MEM_WR_ADDR_LOW 0x54UL -#define IPA_INTR_MEM_WR_PATTERN 0x58UL -#define IPA_RX_FIFO_FULL_MEM_WR_PATTERN 0x5CUL -#define IPA_TX_FIFO_WR_INIT 0x60UL -#define IPA_COMMON_RX_FIFO_AXI_STS 0x64UL -#define IPA_ERRCODE_INT_ADDR_LOW 0x68UL -#define IPA_ERRCODE_INT_PATTERN 0x6CUL - -/* Fifo interrupt enable bit */ -#define IPA_TXFIFO_INT_THRESHOLD_ONESHOT_EN BIT(11) -#define IPA_TXFIFO_INT_THRESHOLD_SW_EN BIT(10) -#define IPA_TXFIFO_INT_DELAY_TIMER_SW_EN BIT(9) -#define IPA_TXFIFO_FULL_INT_EN BIT(8) -#define IPA_TXFIFO_OVERFLOW_EN BIT(7) -#define IPA_ERRORCODE_IN_TX_FIFO_EN BIT(6) -#define IPA_DROP_PACKET_OCCUR_INT_EN BIT(5) -#define IPA_RX_FIFO_INT_EXIT_FLOW_CTRL_EN BIT(4) -#define IPA_RX_FIFO_INT_ENTER_FLOW_CTRL_EN BIT(3) -#define IPA_TX_FIFO_INTR_SW_BIT_EN BIT(2) -#define IPA_TX_FIFO_THRESHOLD_EN BIT(1) -#define IPA_TX_FIFO_DELAY_TIMER_EN BIT(0) -#define IPA_INT_EN_BIT_GROUP 0x00000FFFUL - -/* Fifo interrupt status bit */ -#define IPA_INT_TX_FIFO_THRESHOLD_SW_STS BIT(22) -#define IPA_INT_EXIT_FLOW_CTRL_STS BIT(20) -#define IPA_INT_ENTER_FLOW_CTRL_STS BIT(19) -#define IPA_INT_TXFIFO_FULL_INT_STS BIT(18) -#define IPA_INT_TXFIFO_OVERFLOW_STS BIT(17) -#define IPA_INT_ERRORCODE_IN_TX_FIFO_STS BIT(16) -#define IPA_INT_INTR_BIT_STS BIT(15) -#define IPA_INT_THRESHOLD_STS BIT(14) -#define IPA_INT_DELAY_TIMER_STS BIT(13) -#define IPA_INT_DROP_PACKT_OCCUR BIT(12) -#define IPA_INT_STS_GROUP 0x5FF000UL - -/* Fifo interrupt clear bit */ -#define IPA_TX_FIFO_TIMER_CLR_BIT BIT(0) -#define IPA_TX_FIFO_THRESHOLD_CLR_BIT BIT(1) -#define IPA_TX_FIFO_INTR_CLR_BIT BIT(2) -#define IPA_ENTRY_FLOW_CONTROL_CLR_BIT BIT(3) -#define IPA_EXIT_FLOW_CONTROL_CLR_BIT BIT(4) -#define IPA_DROP_PACKET_INTR_CLR_BIT BIT(5) -#define IPA_ERROR_CODE_INTR_CLR_BIT BIT(6) -#define IPA_TX_FIFO_OVERFLOW_CLR_BIT BIT(7) -#define IPA_TX_FIFO_FULL_INT_CLR_BIT BIT(8) -#define IPA_INT_STS_CLR_GROUP 0x000001FFUL - -#define NODE_DESCRIPTION_SIZE 128UL - -/** - * Description: set rx fifo total depth. - * Input: - * @fifo_base: Need to set total depth of the fifo, - * the base address of the FIFO. - * @depth: the size of depth. - * return: - * 0: set successfully. - * non-zero: set failed. - * Note: - */ -static inline int ipa_phy_set_rx_fifo_total_depth(void __iomem *fifo_base, - u32 depth) -{ - u32 tmp; - - if (depth > 0xFFFF) - return -EINVAL; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_DEPTH); - tmp &= 0x0000FFFFUL; - tmp |= (depth << 16); - writel_relaxed(tmp, fifo_base + IPA_COMMON_RX_FIFO_DEPTH); - tmp = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_DEPTH); - if ((tmp & 0xFFFF0000UL) == tmp) - return 0; - else - return -EINVAL; -} - -/** - * Description: get rx fifo total depth. - * Input: - * @fifo_base: Need to get total depth of the fifo, the base address of the - * FIFO. - * return: The size of toal depth. - * Note: - */ -static inline u32 ipa_phy_get_rx_fifo_total_depth(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_DEPTH); - - return (tmp >> 16) & 0x0000FFFFUL; -} - -/** - * Description: get rx fifo filled depth. - * Input: - * @fifo_base: Need to get filled depth of the FIFO, the base address of the - * FIFO. - * return: - * TRUE: The size of rx filled depth - * Note: - */ -static inline u32 ipa_phy_get_rx_fifo_filled_depth(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_DEPTH); - - return tmp & 0x0000FFFFUL; -} - -/** - * Description: get rx fifo full status. - * Input: - * @fifo_base: Need to get rx fifo full status of the FIFO, the base address - * of the FIFO. - * return: - * 1: rx fifo full. - * 0: rx fifo not full. - * Note: - */ -static inline u32 ipa_phy_get_rx_fifo_full_status(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_WR); - - return tmp & 0x1UL; -} - -/** - * Description: update rx fifo write pointer. - * Input: - * @fifo_base: Need to update rx fifo write pointer of the FIFO, the base - * address of the FIFO. - * return: - * 0: update rx fifo write pointer successfully, - * non-zero: update rx fifo write pointer failed. - * Note: - */ -static inline int ipa_phy_update_rx_fifo_wptr(void __iomem *fifo_base, - u32 wptr) -{ - u32 tmp = 0; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_COMMON_RX_FIFO_WR; - - if (wptr > 0xFFFFUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0x0000FFFFUL; - tmp |= (wptr << 16); - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if ((tmp >> 16) == wptr) - return 0; - else - return -EIO; -} - -/** - * Description: get rx fifo write pointer. - * Input: - * @fifo_base: Need to get rx fifo write pointer of the FIFO, the base - * address of the FIFO. - * return: - * The write pointer of rx fifo. - * Note: - */ -static inline u32 ipa_phy_get_rx_fifo_wptr(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_WR); - - return (tmp >> 16); -} - -/** - * Description: update rx fifo read pointer. - * Input: - * @fifo_base: Need to update rx fifo read pointer of the FIFO, the base - * address of the FIFO. - * return: - * 0: update rx fifo read pointer successfully, - * non-zero: update rx fifo read pointer failed. - * Note: - */ -static inline int ipa_phy_update_rx_fifo_rptr(void __iomem *fifo_base, - u32 rptr) -{ - u32 tmp = 0; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_COMMON_RX_FIFO_RD; - - if (rptr > 0xFFFFUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0x0000FFFFUL; - tmp |= (rptr << 16); - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - - if ((tmp >> 16) == rptr) - return 0; - else - return -EIO; -} - -/** - * Description: get rx fifo read pointer. - * Input: - * @fifo_base: Need to get rx fifo read pointer of the FIFO, the base - * address of the FIFO. - * return: - * The read pointer of rx fifo. - * Note: - */ -static inline u32 ipa_phy_get_rx_fifo_rptr(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_RD); - - return (tmp >> 16); -} - -/** - * Description: get rx fifo empty status. - * Input: - * @fifo_base: Need to get rx fifo empty status of the FIFO, the base - * address of the FIFO. - * return: - * The empty status of rx fifo. - * Note: - */ -static inline u32 ipa_phy_get_rx_fifo_empty_status(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_RD); - - return tmp & 0x1UL; -} - -/** - * Description: set tx fifo total depth. - * Input: - * @fifo_base: Need to set tx fifo empty status of the FIFO, the base - * address of the FIFO. - * return: - * 0: set tx fifo total depth successfully. - * non-zero: set tx fifo total_depth failed. - * Note: - */ -static inline int ipa_phy_set_tx_fifo_total_depth(void __iomem *fifo_base, - u32 depth) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_COMMON_TX_FIFO_DEPTH; - - if (depth > 0xFFFFUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0x0000FFFFUL; - tmp |= (depth << 16); - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if ((tmp >> 16) == depth) - return 0; - else - return -EIO; -} - -/** - * Description: get tx fifo total depth. - * Input: - * @fifo_base: Need to get tx fifo empty status of the FIFO, the base - * address of the FIFO. - * return: - * The total depth of tx fifo. - * Note: - */ -static inline u32 ipa_phy_get_tx_fifo_total_depth(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_DEPTH); - - return ((tmp >> 16) & 0x0000FFFF); -} - -/** - * Description: get tx fifo filled depth. - * Input: - * @fifo_base: Need to get tx fifo filled depth of the FIFO, the base - * address of the FIFO. - * return: - * The tx fifo filled depth. - * Note: - */ -static inline u32 ipa_phy_get_tx_fifo_filled_depth(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_DEPTH); - - return (tmp & 0x0000FFFFUL); -} - -/** - * Description: get tx fifo full status. - * Input: - * @fifo_base: Need to get tx fifo full status of the FIFO, the base - * address of the FIFO. - * return: - * The full status of tx fifo. - * Note: - */ -static inline u32 ipa_phy_get_tx_fifo_full_status(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_WR); - - return (tmp & 0x1UL); -} - -/** - * Description: get tx fifo empty status. - * Input: - * @fifo_base: Need to get tx fifo empty status of the FIFO, the base - * address of the FIFO. - * return: - * The empty status of tx fifo. - * Note: - */ -static inline u32 ipa_phy_get_tx_fifo_empty_status(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_RD); - - return (tmp & 0x1UL); -} - -/** - * Description: update tx fifo write pointer. - * Input: - * @fifo_base: Need to update tx fifo write pointer of the FIFO, the base - * address of the FIFO. - * return: - * 0: update tx fifo write pointer successfully. - * non-zero: update tx fifo write pointer failed. - * Note: - */ -static inline int ipa_phy_update_tx_fifo_wptr(void __iomem *fifo_base, - u32 wptr) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_TX_FIFO_WR_INIT; - - if (wptr > 0xFFFFUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0x0000FFFFUL; - tmp |= (wptr << 16); - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - tmp |= 0x2; - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0xFFFFFFFDUL; - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - - if ((tmp >> 16) == wptr) - return 0; - else - return -EIO; -} - -/** - * Description: get tx fifo write pointer. - * Input: - * @fifo_base: Need to get tx fifo write pointer of the FIFO, the base - * address of the FIFO. - * return: - * The write pointer of tx fifo. - * Note: - */ -static inline u32 ipa_phy_get_tx_fifo_wptr(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_WR); - - return (tmp >> 16); -} - -/** - * Description: update tx fifo read pointer. - * Input: - * @fifo_base: Need to update tx fifo read pointer of the FIFO, the base - * address of the FIFO. - * return: - * 0: update tx fifo read pointer successfully. - * non-zero: update tx fifo read pointer failed. - * Note: - */ -static inline int ipa_phy_update_tx_fifo_rptr(void __iomem *fifo_base, - u32 rptr) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_COMMON_TX_FIFO_RD; - - if (rptr > 0xFFFFUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0x0000FFFF; - tmp |= (rptr << 16); - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - - if ((tmp >> 16) == rptr) - return 0; - else - return -EIO; -} - -/** - * Description: get tx fifo write pointer. - * Input: - * @fifo_base: Need to get tx fifo write pointer of the FIFO, the base - * address of the FIFO. - * return: - * The write pointer of rx fifo. - * Note: - */ -static inline u32 ipa_phy_get_tx_fifo_rptr(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_RD); - - return (tmp >> 16); -} - -/** - * Description: set rx fifo address of iram. - * Input: - * @fifo_base: Need to set rx fifo address of the FIFO, the base - * address of the FIFO. - * @addr_l: low 32 bit. - * @addr_h: high 8 bit. - * return: - * 0: update rx fifo address of iram successfully. - * non-zero: update rx fifo address of iram failed. - * Note: - */ -static inline int ipa_phy_set_rx_fifo_addr(void __iomem *fifo_base, - u32 addr_l, u32 addr_h) -{ - u32 tmp_l, tmp_h; - - writel_relaxed(addr_l, fifo_base + IPA_COMMON_RX_FIFO_ADDRL); - writel_relaxed(addr_h, fifo_base + IPA_COMMON_RX_FIFO_ADDRH); - - tmp_l = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_ADDRL); - tmp_h = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_ADDRH); - - if ((tmp_l == addr_l) && (tmp_h == addr_h)) - return 0; - else - return -EIO; -} - -/** - * Description: get rx fifo address of iram. - * Input: - * @fifo_base: Need to get rx fifo address of the FIFO, the base - * address of the FIFO. - * @addr_l: low 32 bit. - * @addr_h: high 8 bit. - * return: - * void. - * Note: - */ -static inline void ipa_phy_get_rx_fifo_addr(void __iomem *fifo_base, - u32 *addr_l, u32 *addr_h) -{ - *addr_l = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_ADDRL); - *addr_h = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_ADDRH); -} - -/** - * Description: set tx fifo address of iram. - * Input: - * @fifo_base: Need to set tx fifo address of the FIFO, the base - * address of the FIFO. - * @addr_l: low 32 bit. - * @addr_h: high 8 bit. - * return: - * 0: update tx fifo address of iram successfully. - * non-zero: update tx fifo address of iram failed. - * Note: - */ -static inline int ipa_phy_set_tx_fifo_addr(void __iomem *fifo_base, - u32 addr_l, u32 addr_h) -{ - u32 tmp_l, tmp_h; - - writel_relaxed(addr_l, fifo_base + IPA_COMMON_TX_FIFO_ADDRL); - writel_relaxed(addr_h, fifo_base + IPA_COMMON_TX_FIFO_ADDRH); - - tmp_l = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_ADDRL); - tmp_h = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_ADDRH); - - if ((tmp_l == addr_l) && (tmp_h == addr_h)) - return 0; - else - return -EIO; -} - -/** - * Description: get tx fifo address of iram. - * Input: - * @fifo_base: Need to get tx fifo address of the FIFO, the base - * address of the FIFO. - * @addr_l: low 32 bit. - * @addr_h: high 8 bit. - * return: - * void. - * Note: - */ -static inline void ipa_phy_get_tx_fifo_addr(void __iomem *fifo_base, - u32 *addr_l, u32 *addr_h) -{ - *addr_l = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_ADDRL); - *addr_h = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_ADDRH); -} - -/** - * Description: Enable interrupt bit. - * Input: - * @fifo_base: Need to enable interrupr bit of the FIFO, the base - * address of the FIFO. - * @int_bit: The interrupt bit that need to enable. - * return: - * 0: Enable successfully. - * non-zero: Enable successfully. - * Note: - */ -static inline int ipa_phy_enable_int_bit(void __iomem *fifo_base, - u32 int_bit) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_INT_GEN_CTL_EN; - - tmp = readl_relaxed(fifo_reg_addr); - tmp |= int_bit; - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - - if ((tmp & int_bit) == int_bit) - return 0; - else - return -EIO; -} - -/** - * Description: Disable interrupt bit. - * Input: - * @fifo_base: Need to Disable interrupr bit of the FIFO, the base - * address of the FIFO. - * @int_bit: The interrupt bit that need to disable. - * return: - * 0: Disable successfully. - * non-zero: Disable failed. - * Note: - */ -static inline int ipa_phy_disable_int_bit(void __iomem *fifo_base, - u32 int_bit) -{ - u32 tmp = 0; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_INT_GEN_CTL_EN; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= (~int_bit); - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= int_bit; - - if (tmp) { - pr_err("Disable interrupt bit = 0x%x set failed!\n", - int_bit); - return -EIO; - } - - return 0; -} - -static inline u32 ipa_phy_get_all_intr_enable_status(void __iomem *fifo_base) -{ - u32 tmp = 0; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_INT_GEN_CTL_EN; - - tmp = readl_relaxed(fifo_reg_addr); - - tmp &= IPA_INT_EN_BIT_GROUP; - - return tmp; -} - -/** - * Description: Get specified interrupt bit status. - * Input: - * @fifo_base: Need to get interrupt bit of the FIFO, the base - * address of the FIFO. - * @int_bit: The specified interrupt bit that need to get. - * return: - * 0: interrupt bit enable. - * non-zero: interrupt bit disable. - * Note: - */ -static inline int ipa_phy_get_fifo_int_sts(void __iomem *fifo_base, u32 sts) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_INT_GEN_CTL_EN); - - if (tmp & sts) - return 0; - else - return -EIO; -} - -/** - * Description: Get interrupt group status. - * Input: - * @fifo_base: Need to get interrupt group status of the FIFO, the base - * address of the FIFO. - * return: - * Interrupt group status. - * Note: - */ -static inline u32 ipa_phy_get_fifo_all_int_sts(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_INT_GEN_CTL_EN); - - return (tmp & IPA_INT_STS_GROUP); -} - -/** - * Description: Clear interrupt flag, need to write 1, then write 0. - * Input: - * @fifo_base: Need to clear interrupt flag of the FIFO, the base - * address of the FIFO. - * return: - * void. - * Note: - */ -static inline void ipa_phy_clear_int(void __iomem *fifo_base, u32 clr_bit) -{ - writel_relaxed(clr_bit, fifo_base + IPA_INT_GEN_CTL_CLR); -} - -/** - * Description: Get drop packet count. - * Input: - * @fifo_base: Need to get drop packet count of the FIFO, the base - * address of the FIFO. - * return: - * Drop packet count. - * Note: - */ -static inline u32 ipa_phy_get_drop_packet_cnt(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_DROP_PACKET_CNT); - - return tmp; -} - -/** - * Description: Get tx fifo threshold interrupt. - * Input: - * @fifo_base: Need to get threshold interrupt of the FIFO, the base - * address of the FIFO. - * OUTPUT: - * threshold value. - * Note: - */ -static inline u32 ipa_phy_get_tx_fifo_interrupt_threshold(void __iomem - *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_INT_GEN_CTL_TX_FIFO_VALUE); - - return (tmp >> 16); -} - -/** - * Description: Set tx fifo interrupt threshold of value. - * Input: - * @fifo_base: Need to get threshold interrupt value of the FIFO, the base - * address of the FIFO. - * return: - * TRUE: set successfully. - * FALSE: set failed. - * Note: - */ -static inline int -ipa_phy_set_tx_fifo_interrupt_threshold(void __iomem *fifo_base, u32 threshold) -{ - u32 tmp = 0; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_INT_GEN_CTL_TX_FIFO_VALUE; - - if (threshold > 0xFFFFUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0x0000FFFFUL; - tmp |= (threshold << 16); - writel_relaxed(tmp, fifo_reg_addr); - tmp = readl_relaxed(fifo_reg_addr); - - if ((tmp >> 16) == threshold) - return 0; - else - return -EIO; -} - -/** - * Description: Get tx fifo interrupt of delay timer value. - * Input: - * @fifo_base: Need to get delay timer interrupt of the FIFO, the base - * address of the FIFO. - * OUTPUT: - * delay timer value. - * Note: - */ -static inline u32 -ipa_phy_get_tx_fifo_interrupt_delay_timer(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_INT_GEN_CTL_TX_FIFO_VALUE); - - return (tmp & 0x0000FFFFUL); -} - -/** - * Description: Set tx fifo interrupt of delay timer value. - * Input: - * @fifo_base: Need to set delay timer interrupt of the FIFO, the base - * address of the FIFO. - * @threshold: The overflow value that need to set. - * return: - * 0: Set successfully. - * non-zero: set failed. - * Note: - */ -static inline int -ipa_phy_set_tx_fifo_interrupt_delay_timer(void __iomem *fifo_base, - u32 threshold) -{ - u32 tmp = 0; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_INT_GEN_CTL_TX_FIFO_VALUE; - - if (threshold > 0xFFFFUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0xFFFF0000UL; - tmp |= threshold; - writel_relaxed(tmp, fifo_reg_addr); - tmp = readl_relaxed(fifo_reg_addr); - - if ((tmp & 0x0000FFFF) == threshold) - return 0; - else - return -EIO; -} - -/** - * Description: Get current term number. - * Input: - * @fifo_base: Need to get current term number of the FIFO, the base - * address of the FIFO. - * return: - * Current term number. - * Note: - */ -static inline u32 ipa_phy_get_cur_term_num(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_PERFETCH_FIFO_CTL); - - return ((tmp & 0x0003E000UL) >> 13); -} - -/** - * Description: Set current term number. - * Input: - * @fifo_base: Need to set current term number of the FIFO, the base - * address of the FIFO. - * return: - * 0: Set successfully. - * non-zero: Set failed. - * Note: - */ -static inline int ipa_phy_set_cur_term_num(void __iomem *fifo_base, - u32 num) -{ - u32 tmp = 0; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_PERFETCH_FIFO_CTL; - - if (num > 0x1FUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0xFFFC1FFFUL; - tmp |= (num << 13); - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if (((tmp & 0x0003E000) >> 13) == num) - return 0; - else - return -EIO; -} - -/** - * Description: Get dst term number. - * Input: - * @fifo_base: Need to get dst term number of the FIFO, the base - * address of the FIFO. - * return: - * Dst term number. - * Note: - */ -static inline u32 ipa_phy_get_dst_term_num(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_PERFETCH_FIFO_CTL); - - return ((tmp & 0x00001F00UL) >> 8); -} - -/** - * Description: Set dst term number. - * Input: - * @fifo_base: Need to set dst term number of the FIFO, the base - * address of the FIFO. - * return: - * 0: Set successfully. - * non-zero: Set failed. - * Note: - */ -static inline int ipa_phy_set_dst_term_num(void __iomem *fifo_base, - u32 num) -{ - u32 tmp = 0; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_PERFETCH_FIFO_CTL; - if (num > 0x1FUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0xFFFFE0FFUL; - tmp |= (num << 8); - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if (((tmp & 0x00001F00UL) >> 8) == num) - return 0; - else - return -EIO; -} - -/** - * Description: Get prefetch fifo priority. - * Input: - * @fifo_base: Need to get prefetch fifo priority of the FIFO, the base - * address of the FIFO. - * return: - * Prefetch fifo priority. - * Note: - */ -static inline u32 ipa_phy_get_prefetch_fifo_priority(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_PERFETCH_FIFO_CTL); - - return ((tmp & 0x000000F0UL) >> 4); -} - -/** - * Description: Set prefetch fifo priority. - * Input: - * @fifo_base: Need to set prefetch fifo priority of the FIFO, the base - * address of the FIFO. - * return: - * 0: Set successfully. - * non-zero: Set failed. - * Note: - */ -static inline int ipa_phy_set_prefetch_fifo_priority(void __iomem *fifo_base, - u32 pri) -{ - u32 tmp = 0; - void __iomem *fifo_reg_base; - - fifo_reg_base = fifo_base + IPA_PERFETCH_FIFO_CTL; - - if (pri > 0xFUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_base); - tmp &= 0xFFFFFF0FUL; - tmp |= (pri << 4); - writel_relaxed(tmp, fifo_reg_base); - - tmp = readl_relaxed(fifo_reg_base); - if (((tmp & 0x000000F0UL) >> 4) == pri) - return 0; - else - return -EIO; -} - -/** - * Description: Get prefetch threshold. - * Input: - * @fifo_base: Need to get prefetch threshold of the FIFO, the base - * address of the FIFO. - * return: - * Prefetch threshold. - * Note: - */ -static inline u32 ipa_phy_get_prefetch_threshold(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_PERFETCH_FIFO_CTL); - - return (tmp & 0xFUL); -} - -/** - * Description: Set prefetch threshold. - * Input: - * @fifo_base: Need to get threshold of the FIFO, the base - * address of the FIFO. - * return: - * 0: Set successfully. - * non-zero: Set failed. - * Note: - */ -static inline int ipa_phy_set_prefetch_threshold(void __iomem *fifo_base, - u32 threshold) -{ - u32 tmp = 0; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_PERFETCH_FIFO_CTL; - - if (threshold > 0xFUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0xFFFFFFF0UL; - tmp |= threshold; - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if ((tmp & 0xFUL) == threshold) - return 0; - else - return -EIO; -} - -/** - * Description: Set stop receive bit. - * Input: - * @fifo_base: Need to set stop receive bit of the FIFO, the base - * address of the FIFO. - * return: - * 0: Set successfully. - * non-zero: Set failed. - * Note: - */ -static inline int ipa_phy_stop_receive(void __iomem *fifo_base) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_FLOW_CTRL_CONFIG; - - tmp = readl_relaxed(fifo_reg_addr); - tmp |= 0x8; - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if (tmp & 0x8) - return 0; - else - return -EIO; -} - -/** - * Description: Clear stop receive bit. - * Input: - * @fifo_base: Need to clear stop receive bit of the FIFO, the base - * address of the FIFO. - * return: - * 0: clear successfully. - * non-zero: clear failed. - * Note: - */ -static inline int ipa_phy_clear_stop_receive(void __iomem *fifo_base) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_FLOW_CTRL_CONFIG; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0xFFFFFFF7; - writel_relaxed(tmp, fifo_reg_addr); - tmp = readl_relaxed(fifo_reg_addr); - - if (!(tmp & 0x8)) - return 0; - else - return -EIO; -} - -/** - * Description: recover fifo work. - * Input: - * @fifo_base: Need to be recovered of the FIFO, the base - * address of the FIFO. - * return: - * 0: Recover successfully. - * non-zero: Recover failed. - * Note: - */ -static inline int ipa_phy_flow_ctrl_recover(void __iomem *fifo_base) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_FLOW_CTRL_CONFIG; - - tmp = readl_relaxed(fifo_reg_addr); - tmp |= 0x4UL; - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if (tmp & 0x4UL) { - tmp &= 0xFFFFFFFBUL; - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if (!(tmp & 0x4UL)) - return 0; - else - return -EIO; - } else { - return -EINVAL; - } -} - -/** - * Description: Set flow ctrl mode. - * Input: - * @fifo_base: Need to set flow ctrl mode of the FIFO, the base - * address of the FIFO. - * return: - * 0: Set successfully. - * non-zero: Set failed. - * Note: - */ -static inline int ipa_phy_set_flow_ctrl_config(void __iomem *fifo_base, - u32 config) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_FLOW_CTRL_CONFIG; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0xFFFFFFFC; - tmp |= config; - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if ((tmp & 0x00000003) == config) - return 0; - else - return -EIO; -} - -/** - * Description: Get flow ctrl mode. - * Input: - * @fifo_base: Need to get flow ctrl mode of the FIFO, the base - * address of the FIFO. - * return: - * Flow ctrl config - * Note: - */ -static inline u32 ipa_phy_get_flow_ctrl_config(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_FLOW_CTRL_CONFIG); - - return (tmp & 0x00000003); -} - -/** - * Description: Set tx fifo exit flow ctrl watermark. - * Input: - * @fifo_base: Need to be set of the FIFO, the base - * address of the FIFO. - * @watermark: The need to be set. - * return: - * 0: Set successfully. - * non-zero: Set failed. - * Note: - */ -static inline int -ipa_phy_set_tx_fifo_exit_flow_ctrl_watermark(void __iomem *fifo_base, - u32 watermark) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_TX_FIFO_FLOW_CTRL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0x0000FFFFUL; - tmp |= (watermark << 16); - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if ((tmp >> 16) == watermark) - return 0; - else - return -EIO; -} - -/** - * Description: Get tx fifo exit flow ctrl watermark. - * Input: - * @fifo_base: Need to be get of the FIFO, the base - * address of the FIFO. - * return: - * Tx fifo exit watermark. - * Note: - */ -static inline u32 -ipa_phy_get_tx_fifo_exit_flow_ctrl_watermark(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_TX_FIFO_FLOW_CTRL); - - return (tmp >> 16); -} - -/** - * Description: Set tx fifo entry flow ctrl watermark. - * Input: - * @fifo_base: Need to be set of the FIFO, the base - * address of the FIFO. - * @watermark: The need to be set. - * return: - * 0: Set successfully. - * non-zero: Set failed. - * Note: - */ -static inline int -ipa_phy_set_tx_fifo_entry_flow_ctrl_watermark(void __iomem *fifo_base, - u32 watermark) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_TX_FIFO_FLOW_CTRL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0xFFFF0000UL; - tmp |= watermark; - writel_relaxed(tmp, fifo_reg_addr); - tmp = readl_relaxed(fifo_reg_addr); - - if ((tmp & 0x0000FFFFUL) == watermark) - return 0; - else - return -EIO; -} - -/** - * Description: Get tx fifo entry flow ctrl watermark. - * Input: - * @fifo_base: Need to be get of the FIFO, the base - * address of the FIFO. - * return: - * @The value of tx fifo entry watermark. - * Note: - */ -static inline u32 -ipa_phy_get_tx_fifo_entry_flow_ctrl_watermark(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_TX_FIFO_FLOW_CTRL); - - return (tmp & 0x0000FFFF); -} - -/** - * Description: Set rx fifo exit flow ctrl watermark. - * Input: - * @fifo_base: Need to be set of the FIFO, the base - * address of the FIFO. - * @watermark: The value of rx fifo exit watermark. - * return: - * 0: Set successfully. - * non-zero: Set failed. - * Note: - */ -static inline int -ipa_phy_set_rx_fifo_exit_flow_ctrl_watermark(void __iomem *fifo_base, - u32 watermark) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_RX_FIFO_FLOW_CTRL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0x0000FFFFUL; - tmp |= (watermark << 16); - writel_relaxed(tmp, fifo_reg_addr); - tmp = readl_relaxed(fifo_reg_addr); - - if ((tmp >> 16) == watermark) - return 0; - else - return -EIO; -} - -/** - * Description: Get rx fifo exit flow ctrl watermark. - * Input: - * @fifo_base: Need to be get of the FIFO, the base - * address of the FIFO. - * return: - * The value of rx fifo exit watermark. - * Note: - */ -static inline u32 -ipa_phy_get_rx_fifo_exit_flow_ctrl_watermark(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_RX_FIFO_FLOW_CTRL); - - return (tmp >> 16); -} - -/** - * Description: Set rx fifo entry flow ctrl watermark. - * Input: - * @fifo_base: Need to be set of the FIFO, the base - * address of the FIFO. - * @watermark: The value of rx fifo entry watermark. - * return: - * TRUE: Set successfully. - * FALSE: Set failed. - * Note: - */ -static inline int -ipa_phy_set_rx_fifo_entry_flow_ctrl_watermark(void __iomem *fifo_base, - u32 watermark) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_RX_FIFO_FLOW_CTRL; - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0xFFFF0000UL; - tmp |= watermark; - writel_relaxed(tmp, fifo_reg_addr); - tmp = readl_relaxed(fifo_reg_addr); - - if ((tmp & 0x0000FFFFUL) == watermark) - return 0; - else - return -EIO; -} - -/** - * Description: Get rx fifo entry flow ctrl watermark. - * Input: - * @fifo_base: Need to be get of the FIFO, the base - * address of the FIFO. - * return: - * The value of rx fifo entry watermark. - * Note: - */ -static inline u32 -ipa_phy_get_rx_fifo_entry_flow_ctrl_watermark(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_RX_FIFO_FLOW_CTRL); - - return (tmp & 0x0000FFFF); -} - -/** - * Description: Get rx_axi_read_cmd_sts - * return: - * rx_axi_read_cmd_sts. - * Note: - */ -static inline u32 ipa_phy_get_rx_fifo_axi_sts(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_AXI_STS); - - return (tmp & 0x00000003); -} -#endif diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_skb_recv.c b/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_skb_recv.c deleted file mode 100644 index 63c60b98b..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_skb_recv.c +++ /dev/null @@ -1,674 +0,0 @@ -/* - * Copyright (C) 2020 Unisoc Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,4,60 )) -#include -#include -#endif - - -#include "../include/sipa.h" -#include "sipa_core.h" -#include "sipa_eth.h" - -#define SIPA_RECV_BUF_LEN 1600 -#define SIPA_RECV_RSVD_LEN 128 - -static int put_recv_array_node(struct sipa_skb_array *p, - struct sk_buff *skb, u64 *dma_addr) -{ - u32 pos; - - if ((p->wp - p->rp) < p->depth) { - pos = p->wp & (p->depth - 1); - p->array[pos].skb = skb; - p->array[pos].dma_addr = *dma_addr; - /* - * Ensure that we put the item to the fifo before - * we update the fifo wp. - */ - smp_wmb(); - p->wp++; - return 0; - } else { - return -1; - } -} - -static int get_recv_array_node(struct sipa_skb_array *p, - struct sk_buff **skb, u64 *dma_addr) -{ - u32 pos; - - if (p->rp != p->wp) { - pos = p->rp & (p->depth -1); - *skb = p->array[pos].skb; - *dma_addr = p->array[pos].dma_addr; - /* - * Ensure that we remove the item from the fifo before - * we update the fifo rp. - */ - smp_wmb(); - p->rp++; - return 0; - } else { - return -1; - } -} - -static int create_recv_array(struct sipa_skb_array *p, u32 depth) -{ - p->array = kzalloc(sizeof(*p->array) * depth, - GFP_KERNEL); - if (!p->array) - return -ENOMEM; - p->rp = 0; - p->wp = 0; - p->depth = depth; - - return 0; -} - -static void destroy_recv_array(struct sipa_skb_array *p) -{ - kfree(p->array); - - p->array = NULL; - p->rp = 0; - p->wp = 0; - p->depth = 0; -} - -static struct sk_buff *alloc_recv_skb(u32 req_len, u8 rsvd) -{ - struct sk_buff *skb; - u32 hr; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - skb = __dev_alloc_skb(req_len + rsvd, GFP_KERNEL | GFP_NOWAIT); - if (!skb) { - dev_err(ctrl->dev, "failed to alloc skb!\n"); - return NULL; - } - - /* save skb ptr to skb->data */ - hr = skb_headroom(skb); - if (hr < rsvd) - skb_reserve(skb, rsvd - hr); - - return skb; -} - -static void sipa_prepare_free_node_init(struct sipa_skb_receiver *receiver, - u32 cnt) -{ - struct sk_buff *skb; - u32 tmp, fail_cnt = 0; - int i; - u32 success_cnt = 0; - u64 dma_addr; - struct sipa_node_description_tag *node; -#if defined (__BIG_ENDIAN_BITFIELD) - struct sipa_node_description_tag node_tmp; -#endif - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - struct sipa_cmn_fifo_cfg_tag *cmn = receiver->ep->recv_fifo; - - for (i = 0; i < cnt; i++) { - skb = alloc_recv_skb(SIPA_RECV_BUF_LEN, receiver->rsvd); - if (!skb) { - fail_cnt++; - break; - } - - tmp = skb_headroom(skb); - if (unlikely(tmp > SIPA_RECV_RSVD_LEN)) { - tmp -= SIPA_RECV_RSVD_LEN; - skb_put(skb, SIPA_RECV_BUF_LEN - tmp); - skb_push(skb, tmp); - } else { - skb_put(skb, SIPA_RECV_BUF_LEN); - } - - dma_addr = (u64)dma_map_single(ctrl->pci_dev, - skb->head, - SIPA_RECV_BUF_LEN + - skb_headroom(skb), - DMA_FROM_DEVICE); - if (dma_mapping_error(ctrl->pci_dev, (dma_addr_t)dma_addr)) { - dev_kfree_skb_any(skb); - dev_err(ctrl->dev, - "prepare free node dma map err\n"); - fail_cnt++; - break; - } - - node = ctrl->hal_ops.get_rx_fifo_wr(cmn->fifo_id, - ctrl->cmn_fifo_cfg, - i); - if (!node) { - dma_unmap_single(ctrl->pci_dev, dma_addr, - SIPA_RECV_BUF_LEN + - skb_headroom(skb), - DMA_FROM_DEVICE); - dev_kfree_skb_any(skb); - dev_err(ctrl->dev, - "get node fail index = %d\n", i); - fail_cnt++; - break; - } - - dma_addr += ctrl->pcie_mem_offset; -#if defined (__BIG_ENDIAN_BITFIELD) - memset(&node_tmp, 0, sizeof(node_tmp)); - node_tmp.address = dma_addr; - node_tmp.length = skb->len; - node_tmp.offset = skb_headroom(skb); - node_tmp.dst = ctrl->ep.recv_fifo->dst; - node_tmp.src = ctrl->ep.recv_fifo->cur; - node_tmp.intr = 0; - node_tmp.net_id = 0; - node_tmp.err_code = 0; - sipa_set_node_desc((u8 *)node, (u8 *)&node_tmp); -#else - node->address = dma_addr; - node->length = skb->len; - node->offset = skb_headroom(skb); - node->dst = ctrl->ep.recv_fifo->dst; - node->src = ctrl->ep.recv_fifo->cur; - node->intr = 0; - node->net_id = 0; - node->err_code = 0; -#endif - if (dma_addr == 0 || node->address == 0) - pr_info("cnt = %d, i = %d, dma_addr 0x%llx, node->address 0x%llx\n", - cnt, i, dma_addr, (long long unsigned int)node->address); - put_recv_array_node(&receiver->recv_array, skb, &dma_addr); - success_cnt++; - } - if (fail_cnt) - dev_err(ctrl->dev, - "fail_cnt = %d success_cnt = %d\n", - fail_cnt, success_cnt); -} - -static void fill_free_fifo(struct sipa_skb_receiver *receiver, u32 cnt) -{ - struct sk_buff *skb; - u32 tmp, fail_cnt = 0; - int i; - u32 success_cnt = 0, depth; - u64 dma_addr; - struct sipa_node_description_tag *node; -#if defined (__BIG_ENDIAN_BITFIELD) - struct sipa_node_description_tag node_tmp; -#endif - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - struct sipa_cmn_fifo_cfg_tag *cmn = receiver->ep->recv_fifo; - - depth = cmn->rx_fifo.depth; - if (cnt > (depth - depth / 4)) { -// dev_warn(ctrl->dev, "free node is not enough,need fill %d\n", cnt); - receiver->rx_danger_cnt++; - } - - for (i = 0; i < cnt; i++) { - skb = alloc_recv_skb(SIPA_RECV_BUF_LEN, receiver->rsvd); - if (!skb) { - fail_cnt++; - break; - } - - tmp = skb_headroom(skb); - if (unlikely(tmp > SIPA_RECV_RSVD_LEN)) { - tmp -= SIPA_RECV_RSVD_LEN; - skb_put(skb, SIPA_RECV_BUF_LEN - tmp); - skb_push(skb, tmp); - } else { - skb_put(skb, SIPA_RECV_BUF_LEN); - } - - dma_addr = (u64)dma_map_single(ctrl->pci_dev, - skb->head, - SIPA_RECV_BUF_LEN + - skb_headroom(skb), - DMA_FROM_DEVICE); - if (dma_mapping_error(ctrl->pci_dev, (dma_addr_t)dma_addr)) { - dev_kfree_skb_any(skb); - dev_err(ctrl->dev, - "prepare free node dma map err\n"); - fail_cnt++; - break; - } - node = ctrl->hal_ops.get_rx_fifo_wr(cmn->fifo_id, - ctrl->cmn_fifo_cfg, - i); - if (!node) { - dma_unmap_single(ctrl->pci_dev, dma_addr, - SIPA_RECV_BUF_LEN + - skb_headroom(skb), - DMA_FROM_DEVICE); - dev_kfree_skb_any(skb); - dev_err(ctrl->dev, - "get node fail index = %d\n", i); - fail_cnt++; - break; - } - - dma_addr += ctrl->pcie_mem_offset; -#if defined (__BIG_ENDIAN_BITFIELD) - memset(&node_tmp, 0, sizeof(node_tmp)); - node_tmp.address = dma_addr; - node_tmp.length = skb->len; - node_tmp.offset = skb_headroom(skb); - node_tmp.dst = ctrl->ep.recv_fifo->dst; - node_tmp.src = ctrl->ep.recv_fifo->cur; - node_tmp.intr = 0; - node_tmp.net_id = 0; - node_tmp.err_code = 0; - sipa_set_node_desc((u8 *)node, (u8 *)&node_tmp); -#else - node->address = dma_addr; - node->length = skb->len; - node->offset = skb_headroom(skb); - node->dst = ctrl->ep.recv_fifo->dst; - node->src = ctrl->ep.recv_fifo->cur; - node->intr = 0; - node->net_id = 0; - node->err_code = 0; -#endif - - put_recv_array_node(&receiver->recv_array, skb, &dma_addr); - success_cnt++; - } - - if (success_cnt) { - ctrl->hal_ops.set_rx_fifo_wr(ctrl->pci_dev, - cmn->fifo_id, - ctrl->cmn_fifo_cfg, - success_cnt); - if (atomic_read(&receiver->need_fill_cnt) > 0) - atomic_sub(success_cnt, - &receiver->need_fill_cnt); - } - - if (fail_cnt) - dev_err(ctrl->dev, - "fill free fifo fail_cnt = %d\n", fail_cnt); -} - -static void sipa_fill_free_node(struct sipa_skb_receiver *receiver, u32 cnt) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - ctrl->hal_ops.set_rx_fifo_wr(ctrl->pci_dev, - receiver->ep->recv_fifo->fifo_id, - ctrl->cmn_fifo_cfg, cnt); - - if (atomic_read(&receiver->need_fill_cnt) > 0) - dev_info(ctrl->dev, - "a very serious problem, mem cover may appear\n"); - - atomic_set(&receiver->need_fill_cnt, 0); -} - -static void sipa_receiver_notify_cb(void *priv, enum sipa_irq_evt_type evt, - unsigned long data) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - struct sipa_skb_receiver *receiver = (struct sipa_skb_receiver *)priv; - - if (evt & SIPA_RECV_WARN_EVT) { - dev_dbg(ctrl->dev, - "sipa maybe poor resources evt = 0x%x\n", evt); - receiver->tx_danger_cnt++; - } - - sipa_dummy_recv_trigger(); -} - -static void sipa_free_recv_skb(struct sipa_skb_receiver *receiver) -{ - u64 addr = 0; - struct sk_buff *recv_skb = NULL; - while(!get_recv_array_node(&receiver->recv_array, &recv_skb, &addr)) - { - dev_kfree_skb_any(recv_skb); - } -} - -struct sk_buff *sipa_recv_skb(int *netid, int index) -{ - int ret = -1; - u32 retry_cnt = 10; - u64 addr = 0; - struct sk_buff *recv_skb = NULL; -#if defined (__BIG_ENDIAN_BITFIELD) - struct sipa_node_description_tag node; -#else - struct sipa_node_description_tag *node; -#endif - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - struct sipa_skb_receiver *receiver = ctrl->receiver; - enum sipa_cmn_fifo_index id = receiver->ep->recv_fifo->fifo_id; - - ret = get_recv_array_node(&receiver->recv_array, - &recv_skb, &addr); -read_again: -#if defined (__BIG_ENDIAN_BITFIELD) - sipa_get_node_desc((u8 *)ctrl->hal_ops.get_tx_fifo_rp(id, - ctrl->cmn_fifo_cfg, index), &node); -#else - node = ctrl->hal_ops.get_tx_fifo_rp(id, ctrl->cmn_fifo_cfg, index); -#endif - -#if defined (__BIG_ENDIAN_BITFIELD) - if (!node.address) { -#else - if (!node->address) { -#endif - if (retry_cnt--) { - udelay(1); - goto read_again; - } - -#if defined (__BIG_ENDIAN_BITFIELD) - dev_err(ctrl->dev, "phy addr is null = %llx\n", - (u64)node.address); -#else - dev_err(ctrl->dev, "phy addr is null = %llx\n", - (u64)node->address); -#endif - if(!ret) { - dma_unmap_single(ctrl->pci_dev, (dma_addr_t)(addr - ctrl->pcie_mem_offset), - SIPA_RECV_BUF_LEN + skb_headroom(recv_skb), - DMA_FROM_DEVICE); - dev_kfree_skb_any(recv_skb); - atomic_add(1, &receiver->need_fill_cnt); - ctrl->hal_ops.set_tx_fifo_rp(id, ctrl->cmn_fifo_cfg, 1); - dev_err(ctrl->dev, - "recv addr is null, but recv_array addr:0x%llx\n", - addr); - } - return NULL; - } - - retry_cnt = 10; -check_again: - if (ret) { -#if defined (__BIG_ENDIAN_BITFIELD) - dev_err(ctrl->dev, - "recv addr:0x%llx, but recv_array is empty\n", - (u64)node.address); -#else - dev_err(ctrl->dev, - "recv addr:0x%llx, but recv_array is empty\n", - (u64)node->address); -#endif - return NULL; -#if defined (__BIG_ENDIAN_BITFIELD) - } else if (addr != node.address && retry_cnt) { -#else - } else if (addr != node->address && retry_cnt) { -#endif - retry_cnt--; - udelay(1); -#if defined (__BIG_ENDIAN_BITFIELD) - sipa_get_node_desc((u8 *)ctrl->hal_ops.get_tx_fifo_rp(id, - ctrl->cmn_fifo_cfg, index), &node); -#endif - goto check_again; -#if defined (__BIG_ENDIAN_BITFIELD) - } else if (addr != node.address && !retry_cnt) { -#else - } else if (addr != node->address && !retry_cnt) { -#endif - dma_unmap_single(ctrl->pci_dev, (dma_addr_t)(addr - ctrl->pcie_mem_offset), - SIPA_RECV_BUF_LEN + skb_headroom(recv_skb), - DMA_FROM_DEVICE); - dev_kfree_skb_any(recv_skb); - atomic_add(1, &receiver->need_fill_cnt); - dev_err(ctrl->dev, - "recv addr:0x%llx, but recv_array addr:0x%llx not equal\n", -#if defined (__BIG_ENDIAN_BITFIELD) - (u64)node.address, addr); -#else - (u64)node->address, addr); -#endif - ctrl->hal_ops.set_tx_fifo_rp(id, ctrl->cmn_fifo_cfg, 1); - return NULL; - } - dma_unmap_single(ctrl->pci_dev, (dma_addr_t)(addr - ctrl->pcie_mem_offset), - SIPA_RECV_BUF_LEN + skb_headroom(recv_skb), - DMA_FROM_DEVICE); - - atomic_add(1, &receiver->need_fill_cnt); - if (atomic_read(&receiver->need_fill_cnt) > 0x30) - wake_up(&receiver->fill_recv_waitq); - -#if defined (__BIG_ENDIAN_BITFIELD) - *netid = node.net_id; -#else - *netid = node->net_id; -#endif - return recv_skb; -} -EXPORT_SYMBOL(sipa_recv_skb); - -static int fill_recv_thread(void *data) -{ - int ret; - struct sipa_skb_receiver *receiver = (struct sipa_skb_receiver *)data; - struct sched_param param = {.sched_priority = 92}; - unsigned long flags; - - sched_setscheduler(current, SCHED_RR, ¶m); - - while (!kthread_should_stop()) { - ret = wait_event_interruptible(receiver->fill_recv_waitq, - (atomic_read(&receiver->need_fill_cnt) > 0) || receiver->run == 0); - spin_lock_irqsave(&receiver->exit_lock, flags); - if(receiver->run == 0) { - spin_unlock_irqrestore(&receiver->exit_lock, flags); - break; - } - spin_unlock_irqrestore(&receiver->exit_lock, flags); - if (!ret) - fill_free_fifo(receiver, atomic_read(&receiver->need_fill_cnt)); - } - - sipa_free_recv_skb(receiver); - if (receiver->recv_array.array) - destroy_recv_array(&receiver->recv_array); - - kfree(receiver); - return 0; -} - -bool sipa_check_recv_tx_fifo_empty(void) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - enum sipa_cmn_fifo_index id = ctrl->receiver->ep->recv_fifo->fifo_id; - - if (!ctrl->remote_ready) - return true; - - return ctrl->hal_ops.get_tx_empty_status(id, ctrl->cmn_fifo_cfg); -} -EXPORT_SYMBOL(sipa_check_recv_tx_fifo_empty); - -void sipa_receiver_open_cmn_fifo(struct sipa_skb_receiver *receiver) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - struct sipa_cmn_fifo_cfg_tag *fifo_cfg = receiver->ep->recv_fifo; - - if (unlikely(!ctrl || !receiver)) { - pr_err("ctrl %p receiver %p not ready\n", ctrl, receiver); - return; - } - - ctrl->hal_ops.open(fifo_cfg->fifo_id, ctrl->cmn_fifo_cfg, NULL); - sipa_fill_free_node(receiver, fifo_cfg->rx_fifo.depth); - - ctrl->hal_ops.set_hw_intr_thres(fifo_cfg->fifo_id, - ctrl->cmn_fifo_cfg, - true, 64, NULL); - /* timeout = 1 / ipa_sys_clk * 1024 * value */ - ctrl->hal_ops.set_hw_intr_timeout(fifo_cfg->fifo_id, - ctrl->cmn_fifo_cfg, - true, 0x32, NULL); - -// ctrl->hal_ops.set_intr_txfifo_full(fifo_cfg->fifo_id, -// ctrl->cmn_fifo_cfg, -// true, NULL); -} -EXPORT_SYMBOL(sipa_receiver_open_cmn_fifo); - -static void sipa_receiver_init(struct sipa_skb_receiver *receiver, u32 rsvd) -{ - u32 depth; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - enum sipa_cmn_fifo_index fifo_id = receiver->ep->recv_fifo->fifo_id; - - dev_info(ctrl->dev, - "fifo_id = %d rx_fifo depth = 0x%x\n", - receiver->ep->recv_fifo->fifo_id, - receiver->ep->recv_fifo->rx_fifo.depth); - - ctrl->cmn_fifo_cfg[fifo_id].irq_cb = - (sipa_irq_notify_cb)sipa_receiver_notify_cb; - ctrl->cmn_fifo_cfg[fifo_id].priv = receiver; - - /* reserve space for dma flushing cache issue */ - receiver->rsvd = rsvd; - depth = receiver->ep->recv_fifo->rx_fifo.depth; - - sipa_prepare_free_node_init(receiver, depth); -} - -void sipa_receiver_add_nic(struct sipa_skb_receiver *receiver, - struct sipa_nic *nic) -{ - int i; - unsigned long flags; - - for (i = 0; i < receiver->nic_cnt; i++) - if (receiver->nic_array[i] == nic) - return; - spin_lock_irqsave(&receiver->lock, flags); - if (receiver->nic_cnt < SIPA_NIC_MAX) - receiver->nic_array[receiver->nic_cnt++] = nic; - spin_unlock_irqrestore(&receiver->lock, flags); -} -EXPORT_SYMBOL(sipa_receiver_add_nic); - -void sipa_reinit_recv_array(struct sipa_skb_receiver *receiver) -{ - if (!receiver) { - pr_err("sipa receiver is null\n"); - return; - } - - if (!receiver->recv_array.array) { - pr_err("sipa p->array is null\n"); - return; - } - - receiver->recv_array.rp = 0; - receiver->recv_array.wp = receiver->recv_array.depth; -} - -int create_sipa_skb_receiver(struct sipa_endpoint *ep, - struct sipa_skb_receiver **receiver_pp) -{ - int ret; - struct sipa_skb_receiver *receiver = NULL; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - receiver = kzalloc(sizeof(*receiver), GFP_KERNEL); - if (!receiver) - return -ENOMEM; - - receiver->ep = ep; - receiver->rsvd = SIPA_RECV_RSVD_LEN; - - atomic_set(&receiver->need_fill_cnt, 0); - - ret = create_recv_array(&receiver->recv_array, - receiver->ep->recv_fifo->rx_fifo.depth); - if (ret) { - dev_err(ctrl->dev, - "create_sipa_sipa_receiver: recv_array kzalloc err.\n"); - kfree(receiver); - return -ENOMEM; - } - - spin_lock_init(&receiver->lock); - spin_lock_init(&receiver->exit_lock); - init_waitqueue_head(&receiver->fill_recv_waitq); - - sipa_receiver_init(receiver, SIPA_RECV_RSVD_LEN); - receiver->run = 1; - receiver->fill_thread = kthread_create(fill_recv_thread, receiver, - "sipa-fill"); - if (IS_ERR(receiver->fill_thread)) { - dev_err(ctrl->dev, "Failed to create kthread: ipa-fill\n"); - ret = PTR_ERR(receiver->fill_thread); - kfree(receiver->recv_array.array); - kfree(receiver); - return ret; - } - - wake_up_process(receiver->fill_thread); - - *receiver_pp = receiver; - return 0; -} -EXPORT_SYMBOL(create_sipa_skb_receiver); - -void destroy_sipa_skb_receiver(struct sipa_skb_receiver *receiver) -{ - unsigned long flags; - - spin_lock_irqsave(&receiver->exit_lock, flags); - receiver->run = 0; - wake_up_interruptible_all(&receiver->fill_recv_waitq); - spin_unlock_irqrestore(&receiver->exit_lock, flags); -} -EXPORT_SYMBOL(destroy_sipa_skb_receiver); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_skb_send.c b/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_skb_send.c deleted file mode 100644 index f70bd16d3..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipa/sipa_skb_send.c +++ /dev/null @@ -1,556 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,4,60 )) -#include -#include -#endif - - -#include "sipa_phy_v0/sipa_fifo_phy.h" -#include "../include/sipa.h" -#include "sipa_core.h" -#include "sipa_eth.h" - -#define SIPA_RECEIVER_BUF_LEN 1600 - -static void sipa_inform_evt_to_nics(struct sipa_skb_sender *sender, - enum sipa_evt_type evt) -{ - - struct sipa_nic *nic; - unsigned long flags; - spin_lock_irqsave(&sender->nic_lock, flags); - - if(SIPA_LEAVE_FLOWCTRL == evt){ - if(sender->free_notify_net == true){ - pr_info("%s, not leave flowctl, free_notify_net is true\n", __func__); - return; - } - - if(sender->ep_cover_net == true){ - pr_info("%s, not leave flowctl, ep_cover_net is true\n", __func__); - return; - } - - pr_info("%s, leave flowctl\n", __func__); - list_for_each_entry(nic, &sender->nic_list, list) { - if (nic->flow_ctrl_status == true) { - nic->flow_ctrl_status = false; - sipa_nic_notify_evt(nic, evt); - } - } - }else{ - pr_info("%s, enter flowctl\n", __func__); - list_for_each_entry(nic, &sender->nic_list, list) { - if (nic->flow_ctrl_status == false) { - nic->flow_ctrl_status = true; - sipa_nic_notify_evt(nic, evt); - } - } - } - - spin_unlock_irqrestore(&sender->nic_lock, flags); -} - -static void sipa_sender_notify_cb(void *priv, enum sipa_irq_evt_type evt, - unsigned long data) -{ - unsigned long flags; - struct sipa_skb_sender *sender = (struct sipa_skb_sender *)priv; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - if (evt & SIPA_RECV_WARN_EVT) { - dev_err(ctrl->dev, - "sipa overflow on ep\n"); - sender->no_free_cnt++; - } - - if (evt & SIPA_IRQ_ENTER_FLOW_CTRL) { - spin_lock_irqsave(&sender->send_lock, flags); - pr_info("sipa_sender_notify_cb set ep_cover_net true!!!!!\n"); - sender->enter_flow_ctrl_cnt++; - sender->ep_cover_net = true; - sipa_inform_evt_to_nics(sender, SIPA_ENTER_FLOWCTRL); - spin_unlock_irqrestore(&sender->send_lock, flags); - } - - if (evt & SIPA_IRQ_EXIT_FLOW_CTRL) { - spin_lock_irqsave(&sender->send_lock, flags); - sender->exit_flow_ctrl_cnt++; - sender->ep_cover_net = false; - sipa_inform_evt_to_nics(sender, SIPA_LEAVE_FLOWCTRL); - spin_unlock_irqrestore(&sender->send_lock, flags); - } - wake_up(&sender->free_waitq); -} - -static void sipa_free_sent_items(struct sipa_skb_sender *sender) -{ - bool status = false; - unsigned long flags; - u32 i, num, success_cnt = 0, retry_cnt = 10, failed_cnt = 0; - struct sipa_skb_dma_addr_node *iter, *_iter; -#if defined (__BIG_ENDIAN_BITFIELD) - struct sipa_node_description_tag node; -#else - struct sipa_node_description_tag *node; -#endif - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - enum sipa_cmn_fifo_index id = sender->ep->send_fifo->fifo_id; - u32 tx_wr, tx_rd, rx_wr, rx_rd; - int exit_flow = 0; - struct sipa_cmn_fifo_cfg_tag *fifo_cfg; - void __iomem *fifo_base; - u32 clr_sts = 0; - u32 int_status = 0; - u32 read_count = 0; - - num = ctrl->hal_ops.recv_node_from_tx_fifo(ctrl->dev, id, - ctrl->cmn_fifo_cfg, -1); - for (i = 0; i < num; i++) { - retry_cnt = 10; -#if defined (__BIG_ENDIAN_BITFIELD) - sipa_get_node_desc((u8 *)ctrl->hal_ops.get_tx_fifo_rp(id, - ctrl->cmn_fifo_cfg, i), &node); -#else - node = ctrl->hal_ops.get_tx_fifo_rp(id, ctrl->cmn_fifo_cfg, i); -#endif - -#if defined (__BIG_ENDIAN_BITFIELD) - if (node.err_code) - dev_err(ctrl->dev, "have node transfer err = %d\n", - node.err_code); -#else - if (node->err_code) - dev_err(ctrl->dev, "have node transfer err = %d\n", - node->err_code); -#endif - -check_again: - spin_lock_irqsave(&sender->send_lock, flags); - if (list_empty(&sender->sending_list)) { - ctrl->hal_ops.get_rx_ptr(SIPA_FIFO_PCIE_UL, ctrl->cmn_fifo_cfg, &rx_wr, &rx_rd); - ctrl->hal_ops.get_tx_ptr(SIPA_FIFO_PCIE_UL, ctrl->cmn_fifo_cfg, &tx_wr, &tx_rd); - dev_err(ctrl->dev, "fifo id %d: send list is empty, old tx_wr=%x tx_rd=%x, rx_wr=%x, rx_rd=%x, left_cnt=%d\n", - sender->ep->send_fifo->fifo_id, tx_wr, tx_rd, rx_wr, rx_rd, atomic_read(&sender->left_cnt)); - - spin_unlock_irqrestore(&sender->send_lock, flags); - goto sipa_free_end; - } - - list_for_each_entry_safe(iter, _iter, &sender->sending_list, list) { -#if defined (__BIG_ENDIAN_BITFIELD) - if (iter->dma_addr == node.address) { -#else - if (iter->dma_addr == node->address) { -#endif - list_del(&iter->list); - list_add_tail(&iter->list, - &sender->pair_free_list); - status = true; - break; - } - } - spin_unlock_irqrestore(&sender->send_lock, flags); - - if (status) { - dma_unmap_single(ctrl->pci_dev, - (dma_addr_t)(iter->dma_addr - ctrl->pcie_mem_offset), - iter->skb->len + - skb_headroom(iter->skb), - DMA_TO_DEVICE); - - dev_kfree_skb_any(iter->skb); - success_cnt++; - status = false; - } else { - if (retry_cnt--) { -#if defined (__BIG_ENDIAN_BITFIELD) - sipa_get_node_desc((u8 *)ctrl->hal_ops.get_tx_fifo_rp(id, - ctrl->cmn_fifo_cfg, i), &node); -#endif - //dev_err(ctrl->dev, "free send skb warning, retry_cnt = %d\n", retry_cnt); - goto check_again; - } - failed_cnt++; - } - } - if(failed_cnt >0){ - dev_err(ctrl->dev, "can't find matching nodes num=%d\n", failed_cnt); - } - - ctrl->hal_ops.set_tx_fifo_rp(id, ctrl->cmn_fifo_cfg, i); - atomic_add(success_cnt, &sender->left_cnt); - if (num != success_cnt) - dev_err(ctrl->dev, "recv num = %d release num = %d\n", num, success_cnt); - -sipa_free_end: - if (sender->free_notify_net && atomic_read(&sender->left_cnt) > sender->ep->send_fifo->rx_fifo.depth / 4) { - sender->free_notify_net = false; - exit_flow = 1; - } - - if(sender->ep_cover_net == true){ - fifo_cfg = ctrl->cmn_fifo_cfg + sender->ep->send_fifo->fifo_id; - fifo_base = fifo_cfg->fifo_reg_base; - - int_status = ipa_phy_get_fifo_all_int_sts(fifo_base); - - if (int_status & IPA_INT_EXIT_FLOW_CTRL_STS) { - exit_flow = 1; - sender->ep_cover_net = false; - clr_sts |= IPA_EXIT_FLOW_CONTROL_CLR_BIT; - ipa_phy_clear_int(fifo_base, clr_sts); - pr_info("%s, exit flow control\n", __func__); - }else{ - pr_info("%s, still in flow control\n", __func__); - } - } - - if(exit_flow == 1){ - spin_lock_irqsave(&sender->send_lock, flags); - sipa_inform_evt_to_nics(sender, SIPA_LEAVE_FLOWCTRL); - spin_unlock_irqrestore(&sender->send_lock, flags); - } -} - -static bool sipa_sender_ck_unfree(struct sipa_skb_sender *sender) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - enum sipa_cmn_fifo_index id = sender->ep->send_fifo->fifo_id; - if (!ctrl->remote_ready) { - printk("%s: need wait remote_ready!\n", __func__); - return false; - } - - if (ctrl->hal_ops.get_tx_empty_status(id, ctrl->cmn_fifo_cfg)) { - ctrl->hal_ops.clr_tout_th_intr(id, ctrl->cmn_fifo_cfg); - ctrl->hal_ops.set_intr_eb(id, ctrl->cmn_fifo_cfg, true, - SIPA_FIFO_THRESHOLD_IRQ_EN | - SIPA_FIFO_DELAY_TIMER_IRQ_EN); - return false; - } else { - return true; - } -} - -static void sipa_free_send_skb(struct sipa_skb_sender *sender) -{ - struct sipa_skb_dma_addr_node *iter, *_iter; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - unsigned long flags; - - spin_lock_irqsave(&sender->send_lock, flags); - if (list_empty(&sender->sending_list)) { - dev_err(ctrl->dev, "fifo id %d: send list is empty\n", sender->ep->send_fifo->fifo_id); - spin_unlock_irqrestore(&sender->send_lock, flags); - return; - } - - list_for_each_entry_safe(iter, _iter, &sender->sending_list, list) { - list_del(&iter->list); - list_add_tail(&iter->list, &sender->pair_free_list); - dma_unmap_single(ctrl->pci_dev, (dma_addr_t)(iter->dma_addr - ctrl->pcie_mem_offset), - iter->skb->len + skb_headroom(iter->skb), DMA_TO_DEVICE); - dev_kfree_skb_any(iter->skb); - } - spin_unlock_irqrestore(&sender->send_lock, flags); -} - -static int sipa_free_thread(void *data) -{ - struct sipa_skb_sender *sender = (struct sipa_skb_sender *)data; - struct sched_param param = {.sched_priority = 90}; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - enum sipa_cmn_fifo_index id = sender->ep->send_fifo->fifo_id; - unsigned long flags; - struct sipa_nic *iter, *_iter; - sched_setscheduler(current, SCHED_RR, ¶m); - - while (!kthread_should_stop()) { - wait_event_interruptible(sender->free_waitq, - sender->free_notify_net || sender->run == 0 || sender->ep_cover_net || - sipa_sender_ck_unfree(sender)); - - spin_lock_irqsave(&sender->exit_lock, flags); - if(sender->run == 0) { - spin_unlock_irqrestore(&sender->exit_lock, flags); - break; - } - spin_unlock_irqrestore(&sender->exit_lock, flags); - sipa_free_sent_items(sender); - - if (!ctrl->hal_ops.get_tx_empty_status(id, ctrl->cmn_fifo_cfg)) { - usleep_range(100, 200); - //pr_info("%s, not empty\n", __func__); - } - } - - sipa_free_send_skb(sender); - kfree(sender->pair_cache); - - list_for_each_entry_safe(iter, _iter, &sender->nic_list, list) { - list_del(&iter->list); - kfree(iter); - } - - kfree(sender); - - return 0; -} - -void sipa_sender_open_cmn_fifo(struct sipa_skb_sender *sender) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - struct sipa_cmn_fifo_cfg_tag *fifo_cfg = sender->ep->send_fifo; - - if (unlikely(!ctrl || !sender)) { - pr_err("ctrl %p sender %p not ready\n", ctrl, sender); - return; - } - - fifo_cfg->irq_cb = (sipa_irq_notify_cb)sipa_sender_notify_cb; - fifo_cfg->priv = sender; - ctrl->hal_ops.open(fifo_cfg->fifo_id, ctrl->cmn_fifo_cfg, NULL); - - ctrl->hal_ops.set_hw_intr_thres(fifo_cfg->fifo_id, - ctrl->cmn_fifo_cfg, true, - 128, NULL); - ctrl->hal_ops.set_hw_intr_timeout(fifo_cfg->fifo_id, ctrl->cmn_fifo_cfg, - true, 0x64, NULL); - - ctrl->hal_ops.set_intr_txfifo_full(fifo_cfg->fifo_id, - ctrl->cmn_fifo_cfg, true, NULL); -} -EXPORT_SYMBOL(sipa_sender_open_cmn_fifo); - -int create_sipa_skb_sender(struct sipa_endpoint *ep, - struct sipa_skb_sender **sender_pp) -{ - int i, ret; - struct sipa_skb_sender *sender = NULL; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - dev_info(ctrl->dev, "sender create start\n"); - sender = kzalloc(sizeof(*sender), GFP_KERNEL); - if (!sender) { - dev_err(ctrl->dev, "alloc sender failed\n"); - return -ENOMEM; - } - - sender->pair_cache = kcalloc(ep->send_fifo->rx_fifo.depth, - sizeof(struct sipa_skb_dma_addr_node), - GFP_KERNEL); - if (!sender->pair_cache) { - dev_err(ctrl->dev, "alloc sender->pair_cache fail\n"); - kfree(sender); - return -ENOMEM; - } - - INIT_LIST_HEAD(&sender->nic_list); - INIT_LIST_HEAD(&sender->sending_list); - INIT_LIST_HEAD(&sender->pair_free_list); - spin_lock_init(&sender->nic_lock); - spin_lock_init(&sender->send_lock); - spin_lock_init(&sender->exit_lock); - for (i = 0; i < ep->send_fifo->rx_fifo.depth; i++) - list_add_tail(&((sender->pair_cache + i)->list), - &sender->pair_free_list); - - sender->ep = ep; - - atomic_set(&sender->left_cnt, ep->send_fifo->rx_fifo.depth / 4 * 3); - - init_waitqueue_head(&sender->free_waitq); - sender->run = 1; - sender->free_thread = kthread_create(sipa_free_thread, sender, - "sipa-free"); - if (IS_ERR(sender->free_thread)) { - dev_err(ctrl->dev, "Failed to create kthread: ipa-free\n"); - ret = PTR_ERR(sender->free_thread); - kfree(sender->pair_cache); - kfree(sender); - return ret; - } - - *sender_pp = sender; - wake_up_process(sender->free_thread); - return 0; -} -EXPORT_SYMBOL(create_sipa_skb_sender); - -void destroy_sipa_skb_sender(struct sipa_skb_sender *sender) -{ - unsigned long flags; - - spin_lock_irqsave(&sender->exit_lock, flags); - sender->run = 0; - wake_up_interruptible_all(&sender->free_waitq); - spin_unlock_irqrestore(&sender->exit_lock, flags); -} -EXPORT_SYMBOL(destroy_sipa_skb_sender); - -void sipa_skb_sender_add_nic(struct sipa_skb_sender *sender, - struct sipa_nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&sender->nic_lock, flags); - list_add_tail(&nic->list, &sender->nic_list); - spin_unlock_irqrestore(&sender->nic_lock, flags); -} -EXPORT_SYMBOL(sipa_skb_sender_add_nic); - -void sipa_skb_sender_remove_nic(struct sipa_skb_sender *sender, - struct sipa_nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&sender->nic_lock, flags); - list_del(&nic->list); - spin_unlock_irqrestore(&sender->nic_lock, flags); -} -EXPORT_SYMBOL(sipa_skb_sender_remove_nic); - -int sipa_skb_sender_send_data(struct sipa_skb_sender *sender, - struct sk_buff *skb, - enum sipa_term_type dst, - u8 netid) -{ - unsigned long flags; - u64 dma_addr; - struct sipa_skb_dma_addr_node *node; -#if defined (__BIG_ENDIAN_BITFIELD) - struct sipa_node_description_tag des; -#else - struct sipa_node_description_tag *des; -#endif - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - struct sipa_cmn_fifo_cfg_tag *fifo_cfg; - void __iomem *fifo_base; - u32 clr_sts = 0; - u32 int_status = 0; - - spin_lock_irqsave(&sender->send_lock, flags); - - if (sender->ep_cover_net == true){ - pr_info("%s, ep_cover_net is true, so return EAGAIN\n", __func__); - spin_unlock_irqrestore(&sender->send_lock, flags); - wake_up(&sender->free_waitq); - return -EAGAIN; - }else{ - fifo_cfg = ctrl->cmn_fifo_cfg + sender->ep->send_fifo->fifo_id; - fifo_base = fifo_cfg->fifo_reg_base; - int_status = ipa_phy_get_fifo_all_int_sts(fifo_base); - if(int_status == 0x5FF000){ - pr_err("%s: check sts failed, maybe ep is down\n", __func__); - spin_unlock_irqrestore(&sender->send_lock, flags); - return -EINPROGRESS; - } - - if (int_status & IPA_INT_ENTER_FLOW_CTRL_STS) { - pr_info("sipa_skb_sender_send_data set ep_cover_net true!!!!!\n"); - sender->ep_cover_net = true; - sender->enter_flow_ctrl_cnt++; - clr_sts |= IPA_ENTRY_FLOW_CONTROL_CLR_BIT; - ipa_phy_clear_int(fifo_base, clr_sts); - sipa_inform_evt_to_nics(sender, SIPA_ENTER_FLOWCTRL); - spin_unlock_irqrestore(&sender->send_lock, flags); - wake_up(&sender->free_waitq); - return -EAGAIN; - } - } - - if (sender->free_notify_net == true){ - pr_info("%s: free_notify_net is true, so return EAGAIN\n", __func__); - spin_unlock_irqrestore(&sender->send_lock, flags); - wake_up(&sender->free_waitq); - return -EAGAIN; - } - - if (!atomic_read(&sender->left_cnt)) { - sender->no_free_cnt++; - sender->free_notify_net = true; - sipa_inform_evt_to_nics(sender, SIPA_ENTER_FLOWCTRL); - spin_unlock_irqrestore(&sender->send_lock, flags); - wake_up(&sender->free_waitq); - return -EAGAIN; - } - - dma_addr = (u64)dma_map_single(ctrl->pci_dev, skb->head, - skb->len + skb_headroom(skb), - DMA_TO_DEVICE); - - if (unlikely(dma_mapping_error(ctrl->pci_dev, (dma_addr_t)dma_addr))) { - sender->free_notify_net = true; - sipa_inform_evt_to_nics(sender, SIPA_ENTER_FLOWCTRL); - spin_unlock_irqrestore(&sender->send_lock, flags); - wake_up(&sender->free_waitq); - return -EAGAIN; - } - - dma_addr += ctrl->pcie_mem_offset; -#if defined (__BIG_ENDIAN_BITFIELD) - memset(&des, 0, sizeof(des)); - des.address = dma_addr; - des.length = skb->len; - des.offset = skb_headroom(skb); - des.net_id = netid; - des.dst = dst; - des.src = sender->ep->send_fifo->cur; - des.err_code = 0; - des.intr = 0; - sipa_set_node_desc((u8 *)ctrl->hal_ops.get_rx_fifo_wr(sender->ep->send_fifo->fifo_id, - ctrl->cmn_fifo_cfg, 0), (u8 *)&des); -#else - des = ctrl->hal_ops.get_rx_fifo_wr(sender->ep->send_fifo->fifo_id, - ctrl->cmn_fifo_cfg, 0); - des->address = dma_addr; - des->length = skb->len; - des->offset = skb_headroom(skb); - des->net_id = netid; - des->dst = dst; - des->src = sender->ep->send_fifo->cur; - des->err_code = 0; - des->intr = 0; -#endif - node = list_first_entry(&sender->pair_free_list, - struct sipa_skb_dma_addr_node, - list); - node->skb = skb; - node->dma_addr = dma_addr; - list_del(&node->list); - list_add_tail(&node->list, &sender->sending_list); - ctrl->hal_ops.set_rx_fifo_wr(ctrl->pci_dev, - sender->ep->send_fifo->fifo_id, - ctrl->cmn_fifo_cfg, 1); - atomic_dec(&sender->left_cnt); - spin_unlock_irqrestore(&sender->send_lock, flags); - - return 0; -} -EXPORT_SYMBOL(sipa_skb_sender_send_data); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/Kconfig b/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/Kconfig deleted file mode 100644 index 9fe141954..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/Kconfig +++ /dev/null @@ -1,26 +0,0 @@ -menu "SIPC modules" - -config SPRD_SIPC - bool "Sprd IPC" - default n - select GENERIC_ALLOCATOR - help - SIPC is a module for spreadtrum AP/CP communicaiton system. - -config SPRD_SIPC_SPIPE - bool "SPRD pipe driver based on SBUF" - default n - depends on SPRD_SIPC - help - This driver is a pipe driver base on SBUF, which create - general pipes between AP & CP. - -config SPRD_SIPC_SPOOL - bool "SPRD pool driver based on SBLOCK" - default n - depends on SPRD_SIPC - help - This driver is a pool driver base on SBLOCK, which create - general pools between AP & CP. - -endmenu diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/Makefile b/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/Makefile deleted file mode 100644 index caed73a4c..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -ccflags-y += -DCONFIG_SPRD_PCIE_EP_DEVICE -DCONFIG_SPRD_SIPA - -obj-y += sipc.o smsg.o smem.o sbuf.o sblock.o sipc_debugfs.o -obj-y += spipe.o -obj-y += spool.o - diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sblock.c b/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sblock.c deleted file mode 100644 index 730f531fd..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sblock.c +++ /dev/null @@ -1,1911 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,4,60 )) -#include -#include -#endif - -#include "../include/sipc.h" -#include "sipc_priv.h" -#include "sblock.h" - -static struct sblock_mgr *sblocks[SIPC_ID_NR][SMSG_VALID_CH_NR]; - -/* put one block pack to the pool */ -void sblock_put(u8 dst, u8 channel, struct sblock *blk) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring; - unsigned long flags; - int txpos; - int index; - u8 ch_index; - struct sblock_ring_header_op *poolhd_op; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return; - } - - sblock = sblocks[dst][ch_index]; - if (!sblock) - return; - - ring = sblock->ring; - poolhd_op = &(ring->header_op.poolhd_op); - - spin_lock_irqsave(&ring->p_txlock, flags); - txpos = sblock_get_ringpos(*(poolhd_op->tx_rd_p) - 1, - poolhd_op->tx_count); - ring->p_txblks[txpos].addr = blk->addr - - sblock->smem_virt + - sblock->stored_smem_addr; - ring->p_txblks[txpos].length = poolhd_op->tx_size; - *(poolhd_op->tx_rd_p) = *(poolhd_op->tx_rd_p) - 1; - if ((int)(*(poolhd_op->tx_wt_p) - *(poolhd_op->tx_rd_p)) == 1) - wake_up_interruptible_all(&(ring->getwait)); - index = sblock_get_index((blk->addr - ring->txblk_virt), - sblock->txblksz); - ring->txrecord[index] = SBLOCK_BLK_STATE_DONE; - - spin_unlock_irqrestore(&ring->p_txlock, flags); - - /* set write mask. */ - spin_lock_irqsave(&ring->poll_lock, flags); - ring->poll_mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - /* request in sblock_get, release here */ - sipc_smem_release_resource(ring->tx_pms, dst); -} -EXPORT_SYMBOL_GPL(sblock_put); - -static bool sblock_has_data(struct sblock_mgr *sblock, bool tx) -{ - struct sblock_ring_header_op *poolhd_op; - struct sblock_ring_header_op *ringhd_op; - struct sblock_ring *ring = sblock->ring; - bool has_data; - unsigned long flags; - - /* if it is local share memory, - * check the read and write point directly. - */ - if (smsg_ipcs[sblock->dst]->smem_type == SMEM_LOCAL) { - if (tx) { - poolhd_op = &ring->header_op.poolhd_op; - return *(poolhd_op->tx_rd_p) != *(poolhd_op->tx_wt_p); - } - - ringhd_op = &ring->header_op.ringhd_op; - return *(ringhd_op->rx_wt_p) != *(ringhd_op->rx_rd_p); - } - - /* - * if it is remote share memmory read the poll_mask, this situation - * requires that the poll_mask must be accurate enough. - */ - spin_lock_irqsave(&ring->poll_lock, flags); - if (tx) - has_data = ring->poll_mask & (POLLOUT | POLLWRNORM); - else - has_data = ring->poll_mask & (POLLIN | POLLRDNORM); - spin_unlock_irqrestore(&ring->poll_lock, flags); - - return has_data; -} - -/* clean rings and recover pools */ -static int sblock_recover(u8 dst, u8 channel) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring = NULL; - struct sblock_ring_header_op *poolhd_op; - struct sblock_ring_header_op *ringhd_op; - unsigned long pflags, qflags; - int i, j, rval; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - if (!sblock) - return -ENODEV; - - ring = sblock->ring; - poolhd_op = &(ring->header_op.poolhd_op); - ringhd_op = &(ring->header_op.ringhd_op); - - sblock->state = SBLOCK_STATE_IDLE; - wake_up_interruptible_all(&ring->getwait); - wake_up_interruptible_all(&ring->recvwait); - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->rx_pms, dst, -1); - if (rval < 0) - return rval; - - spin_lock_irqsave(&ring->r_txlock, pflags); - /* clean txblks ring */ - *(ringhd_op->tx_wt_p) = *(ringhd_op->tx_rd_p); - - spin_lock_irqsave(&ring->p_txlock, qflags); - /* recover txblks pool */ - *(poolhd_op->tx_rd_p) = *(poolhd_op->tx_wt_p); - for (i = 0, j = 0; i < poolhd_op->tx_count; i++) { - if (ring->txrecord[i] == SBLOCK_BLK_STATE_DONE) { - ring->p_txblks[j].addr = i * sblock->txblksz + - poolhd_op->tx_addr; - ring->p_txblks[j].length = sblock->txblksz; - *(poolhd_op->tx_wt_p) = *(poolhd_op->tx_wt_p) + 1; - j++; - } - } - spin_unlock_irqrestore(&ring->p_txlock, qflags); - spin_unlock_irqrestore(&ring->r_txlock, pflags); - - spin_lock_irqsave(&ring->r_rxlock, pflags); - /* clean rxblks ring */ - *(ringhd_op->rx_rd_p) = *(ringhd_op->rx_wt_p); - - spin_lock_irqsave(&ring->p_rxlock, qflags); - /* recover rxblks pool */ - *(poolhd_op->rx_wt_p) = *(poolhd_op->rx_rd_p); - for (i = 0, j = 0; i < poolhd_op->rx_count; i++) { - if (ring->rxrecord[i] == SBLOCK_BLK_STATE_DONE) { - ring->p_rxblks[j].addr = i * sblock->rxblksz + - poolhd_op->rx_addr; - ring->p_rxblks[j].length = sblock->rxblksz; - *(poolhd_op->rx_wt_p) = *(poolhd_op->rx_wt_p) + 1; - j++; - } - } - spin_unlock_irqrestore(&ring->p_rxlock, qflags); - spin_unlock_irqrestore(&ring->r_rxlock, pflags); - - /* restore write mask. */ - spin_lock_irqsave(&ring->poll_lock, qflags); - ring->poll_mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&ring->poll_lock, qflags); - - /* release resource */ - sipc_smem_release_resource(ring->rx_pms, dst); - - return 0; -} - -static int sblock_host_init(struct smsg_ipc *sipc, struct sblock_mgr *sblock, - u32 txblocknum, u32 txblocksize, - u32 rxblocknum, u32 rxblocksize) -{ - volatile struct sblock_ring_header *ringhd; - volatile struct sblock_ring_header *poolhd; - struct sblock_ring_header_op *ringhd_op; - struct sblock_ring_header_op *poolhd_op; - - u32 hsize; - int i, rval = -ENOMEM; - phys_addr_t offset = 0; - u8 dst = sblock->dst; - - txblocksize = ALIGN(txblocksize, SBLOCK_ALIGN_BYTES); - rxblocksize = ALIGN(rxblocksize, SBLOCK_ALIGN_BYTES); - sblock->txblksz = txblocksize; - sblock->rxblksz = rxblocksize; - sblock->txblknum = txblocknum; - sblock->rxblknum = rxblocknum; - - pr_debug("%s: channel %d-%d, txblocksize=%#x, rxblocksize=%#x!\n", - __func__, - sblock->dst, - sblock->channel, - txblocksize, - rxblocksize); - - pr_debug("%s: channel %d-%d, txblocknum=%#x, rxblocknum=%#x!\n", - __func__, - sblock->dst, - sblock->channel, - txblocknum, - rxblocknum); - - /* allocate smem */ - hsize = sizeof(struct sblock_header); - /* for header*/ - sblock->smem_size = hsize + - /* for blks */ - txblocknum * txblocksize + rxblocknum * rxblocksize + - /* for ring */ - (txblocknum + rxblocknum) * sizeof(struct sblock_blks) + - /* for pool */ - (txblocknum + rxblocknum) * sizeof(struct sblock_blks); - - sblock->smem_addr = smem_alloc(dst, sblock->smem_size); - if (!sblock->smem_addr) { - pr_err("%s: channel %d-%d, Failed to alloc smem for sblock\n", - __func__, - sblock->dst, - sblock->channel); - return -ENOMEM; - } - - pr_debug("%s: channel %d-%d, smem_addr=%#lx, smem_size=%#x!\n", - __func__, - sblock->dst, - sblock->channel, - (unsigned long)(sblock->smem_addr + offset), - sblock->smem_size); - - sblock->dst_smem_addr = sblock->smem_addr - - sipc->smem_base + sipc->dst_smem_base; - - /* in host mode, it is client physial address. */ - sblock->stored_smem_addr = sblock->dst_smem_addr; - -#ifdef CONFIG_PHYS_ADDR_T_64BIT - offset = sipc->high_offset; - offset = offset << 32; -#endif - pr_debug("%s: channel %d-%d, offset = 0x%lx!\n", - __func__, - sblock->dst, - sblock->channel, - (unsigned long)offset); - sblock->smem_virt = shmem_ram_vmap_nocache(dst, - sblock->smem_addr + offset, - sblock->smem_size); - if (!sblock->smem_virt) { - pr_err("%s: channel %d-%d, Failed to map smem for sblock\n", - __func__, - sblock->dst, - sblock->channel); - goto sblock_host_smem_free; - } - - /* alloc ring */ - sblock->ring->txrecord = kcalloc(txblocknum, sizeof(int), GFP_KERNEL); - if (!sblock->ring->txrecord) - goto sblock_host_unmap; - - sblock->ring->rxrecord = kcalloc(rxblocknum, sizeof(int), GFP_KERNEL); - if (!sblock->ring->rxrecord) - goto sblock_host_tx_free; - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(sipc->sipc_pms, sipc->dst, -1); - if (rval < 0) - goto sblock_host_rx_free; - - /* initialize header */ - ringhd = (volatile struct sblock_ring_header *)(sblock->smem_virt); - ringhd->txblk_addr = sblock->stored_smem_addr + hsize; - ringhd->txblk_count = txblocknum; - ringhd->txblk_size = txblocksize; - ringhd->txblk_rdptr = 0; - ringhd->txblk_wrptr = 0; - ringhd->txblk_blks = ringhd->txblk_addr + - txblocknum * txblocksize + rxblocknum * rxblocksize; - ringhd->rxblk_addr = ringhd->txblk_addr + txblocknum * txblocksize; - ringhd->rxblk_count = rxblocknum; - ringhd->rxblk_size = rxblocksize; - ringhd->rxblk_rdptr = 0; - ringhd->rxblk_wrptr = 0; - ringhd->rxblk_blks = ringhd->txblk_blks + - txblocknum * sizeof(struct sblock_blks); - - poolhd = ringhd + 1; - poolhd->txblk_addr = sblock->stored_smem_addr + hsize; - poolhd->txblk_count = txblocknum; - poolhd->txblk_size = txblocksize; - poolhd->txblk_rdptr = 0; - poolhd->txblk_wrptr = 0; - poolhd->txblk_blks = ringhd->rxblk_blks + - rxblocknum * sizeof(struct sblock_blks); - poolhd->rxblk_addr = ringhd->txblk_addr + txblocknum * txblocksize; - poolhd->rxblk_count = rxblocknum; - poolhd->rxblk_size = rxblocksize; - poolhd->rxblk_rdptr = 0; - poolhd->rxblk_wrptr = 0; - poolhd->rxblk_blks = poolhd->txblk_blks + - txblocknum * sizeof(struct sblock_blks); - - pr_debug("%s: channel %d-%d, int ring!\n", - __func__, - sblock->dst, - sblock->channel); - - /* initialize ring */ - sblock->ring->header = sblock->smem_virt; - sblock->ring->txblk_virt = sblock->smem_virt + - (ringhd->txblk_addr - sblock->stored_smem_addr); - sblock->ring->r_txblks = sblock->smem_virt + - (ringhd->txblk_blks - sblock->stored_smem_addr); - sblock->ring->rxblk_virt = sblock->smem_virt + - (ringhd->rxblk_addr - sblock->stored_smem_addr); - sblock->ring->r_rxblks = sblock->smem_virt + - (ringhd->rxblk_blks - sblock->stored_smem_addr); - sblock->ring->p_txblks = sblock->smem_virt + - (poolhd->txblk_blks - sblock->stored_smem_addr); - sblock->ring->p_rxblks = sblock->smem_virt + - (poolhd->rxblk_blks - sblock->stored_smem_addr); - - for (i = 0; i < txblocknum; i++) { - sblock->ring->p_txblks[i].addr = poolhd->txblk_addr + - i * txblocksize; - sblock->ring->p_txblks[i].length = txblocksize; - sblock->ring->txrecord[i] = SBLOCK_BLK_STATE_DONE; - poolhd->txblk_wrptr++; - } - for (i = 0; i < rxblocknum; i++) { - sblock->ring->p_rxblks[i].addr = poolhd->rxblk_addr + - i * rxblocksize; - sblock->ring->p_rxblks[i].length = rxblocksize; - sblock->ring->rxrecord[i] = SBLOCK_BLK_STATE_DONE; - poolhd->rxblk_wrptr++; - } - - /* init, set write mask. */ - sblock->ring->poll_mask = POLLOUT | POLLWRNORM; - - /* init header op */ - ringhd_op = &((sblock->ring->header_op).ringhd_op); - ringhd_op->tx_rd_p = &ringhd->txblk_rdptr; - ringhd_op->tx_wt_p = &ringhd->txblk_wrptr; - ringhd_op->rx_rd_p = &ringhd->rxblk_rdptr; - ringhd_op->rx_wt_p = &ringhd->rxblk_wrptr; - ringhd_op->tx_addr = ringhd->txblk_addr; - ringhd_op->tx_count = ringhd->txblk_count; - ringhd_op->tx_size = ringhd->txblk_size; - ringhd_op->tx_blks = ringhd->txblk_blks; - ringhd_op->rx_addr = ringhd->rxblk_addr; - ringhd_op->rx_count = ringhd->rxblk_count; - ringhd_op->rx_size = ringhd->rxblk_size; - ringhd_op->rx_blks = ringhd->rxblk_blks; - poolhd_op = &((sblock->ring->header_op).poolhd_op); - poolhd_op->tx_rd_p = &poolhd->txblk_rdptr; - poolhd_op->tx_wt_p = &poolhd->txblk_wrptr; - poolhd_op->rx_rd_p = &poolhd->rxblk_rdptr; - poolhd_op->rx_wt_p = &poolhd->rxblk_wrptr; - poolhd_op->tx_addr = poolhd->txblk_addr; - poolhd_op->tx_count = poolhd->txblk_count; - poolhd_op->tx_size = poolhd->txblk_size; - poolhd_op->tx_blks = poolhd->txblk_blks; - poolhd_op->rx_addr = poolhd->rxblk_addr; - poolhd_op->rx_count = poolhd->rxblk_count; - poolhd_op->rx_size = poolhd->rxblk_size; - poolhd_op->rx_blks = poolhd->rxblk_blks; - - /* release resource */ - sipc_smem_release_resource(sipc->sipc_pms, sipc->dst); - - return 0; - -sblock_host_rx_free: - kfree(sblock->ring->rxrecord); -sblock_host_tx_free: - kfree(sblock->ring->txrecord); -sblock_host_unmap: - shmem_ram_unmap(dst, sblock->smem_virt); -sblock_host_smem_free: - smem_free(dst, sblock->smem_addr, sblock->smem_size); - - pr_err("%s: channel %d-%d, failed, ENOMEM!\n", - __func__, - sblock->dst, - sblock->channel); - - return rval; -} - -static int sblock_client_init(struct smsg_ipc *sipc, struct sblock_mgr *sblock) -{ - volatile struct sblock_ring_header *ringhd; - volatile struct sblock_ring_header *poolhd; - struct sblock_ring_header_op *ringhd_op; - struct sblock_ring_header_op *poolhd_op; - u32 hsize; - u8 dst = sblock->dst; - phys_addr_t offset = 0; - u32 txblocknum, txblocksize, rxblocknum, rxblocksize; - int rval = -ENOMEM; - -#ifdef CONFIG_PHYS_ADDR_T_64BIT - offset = sipc->high_offset; - offset = offset << 32; - pr_debug("%s: channel %d-%d, offset = 0x%llx!\n", - __func__, - sblock->dst, - sblock->channel, - offset); -#endif - - /* get blcok num and block size */ - hsize = sizeof(struct sblock_header); - sblock->smem_virt = shmem_ram_vmap_nocache(dst, - sblock->smem_addr + offset, - hsize); - if (!sblock->smem_virt) { - pr_err("%s: channel %d-%d, Failed to map smem for sblock\n", - __func__, - sblock->dst, - sblock->channel); - return -ENOMEM; - } - ringhd = (volatile struct sblock_ring_header *)(sblock->smem_virt); - /* client mode, tx <==> rx */ - txblocknum = ringhd->rxblk_count; - txblocksize = ringhd->rxblk_size; - rxblocknum = ringhd->txblk_count; - rxblocksize = ringhd->txblk_size; - - sblock->txblksz = txblocksize; - sblock->rxblksz = rxblocksize; - sblock->txblknum = txblocknum; - sblock->rxblknum = rxblocknum; - shmem_ram_unmap(dst, sblock->smem_virt); - - pr_debug("%s: channel %d-%d, txblocksize=%#x, rxblocksize=%#x!\n", - __func__, - sblock->dst, - sblock->channel, - txblocksize, - rxblocksize); - - pr_debug("%s: channel %d-%d, txblocknum=%#x, rxblocknum=%#x!\n", - __func__, - sblock->dst, - sblock->channel, - txblocknum, - rxblocknum); - - /* allocate smem */ - /* for header*/ - sblock->smem_size = hsize + - /* for blks */ - txblocknum * txblocksize + rxblocknum * rxblocksize + - /* for ring */ - (txblocknum + rxblocknum) * sizeof(struct sblock_blks) + - /* for pool */ - (txblocknum + rxblocknum) * sizeof(struct sblock_blks); - - sblock->smem_addr_debug = smem_alloc(dst, sblock->smem_size); - if (!sblock->smem_addr_debug) { - pr_err("%s: channel %d-%d, Failed to allocate smem\n", - __func__, - sblock->dst, - sblock->channel); - return -ENOMEM; - } - - pr_debug("%s: channel %d-%d, smem_addr=%#lx, smem_size=%#x!\n", - __func__, - sblock->dst, - sblock->channel, - (unsigned long)(sblock->smem_addr + offset), - sblock->smem_size); - - /* in client mode, it is own physial address. */ - sblock->stored_smem_addr = sblock->smem_addr; - - /* get smem virtual address */ - sblock->smem_virt = shmem_ram_vmap_nocache(dst, - sblock->smem_addr + offset, - sblock->smem_size); - if (!sblock->smem_virt) { - pr_err("%s: channel %d-%d, Failed to map smem for sblock!\n", - __func__, - sblock->dst, - sblock->channel); - goto sblock_client_smem_free; - } - - /* initialize ring and header */ - sblock->ring->txrecord = kcalloc(txblocknum, sizeof(int), GFP_KERNEL); - if (!sblock->ring->txrecord) - goto sblock_client_unmap; - - sblock->ring->rxrecord = kcalloc(rxblocknum, sizeof(int), GFP_KERNEL); - if (!sblock->ring->rxrecord) - goto sblock_client_tx_free; - - ringhd = (volatile struct sblock_ring_header *)(sblock->smem_virt); - poolhd = ringhd + 1; - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(sipc->sipc_pms, sipc->dst, -1); - if (rval < 0) - goto sblock_client_tx_free; - - /* client mode, tx <==> rx */ - sblock->ring->header = sblock->smem_virt; - sblock->ring->txblk_virt = sblock->smem_virt + - (ringhd->rxblk_addr - sblock->stored_smem_addr); - sblock->ring->rxblk_virt = sblock->smem_virt + - (ringhd->txblk_addr - sblock->stored_smem_addr); - sblock->ring->r_txblks = sblock->smem_virt + - (ringhd->rxblk_blks - sblock->stored_smem_addr); - sblock->ring->r_rxblks = sblock->smem_virt + - (ringhd->txblk_blks - sblock->stored_smem_addr); - sblock->ring->p_txblks = sblock->smem_virt + - (poolhd->rxblk_blks - sblock->stored_smem_addr); - sblock->ring->p_rxblks = sblock->smem_virt + - (poolhd->txblk_blks - sblock->stored_smem_addr); - - /* init header op, tx <==> rx */ - ringhd_op = &((sblock->ring->header_op).ringhd_op); - ringhd_op->tx_rd_p = &ringhd->rxblk_rdptr; - ringhd_op->tx_wt_p = &ringhd->rxblk_wrptr; - ringhd_op->rx_rd_p = &ringhd->txblk_rdptr; - ringhd_op->rx_wt_p = &ringhd->txblk_wrptr; - ringhd_op->tx_addr = ringhd->rxblk_addr; - ringhd_op->tx_count = ringhd->rxblk_count; - ringhd_op->tx_size = ringhd->rxblk_size; - ringhd_op->tx_blks = ringhd->rxblk_blks; - ringhd_op->rx_addr = ringhd->txblk_addr; - ringhd_op->rx_count = ringhd->txblk_count; - ringhd_op->rx_size = ringhd->txblk_size; - ringhd_op->rx_blks = ringhd->txblk_blks; - poolhd_op = &((sblock->ring->header_op).poolhd_op); - poolhd_op->tx_rd_p = &poolhd->rxblk_rdptr; - poolhd_op->tx_wt_p = &poolhd->rxblk_wrptr; - poolhd_op->rx_rd_p = &poolhd->txblk_rdptr; - poolhd_op->rx_wt_p = &poolhd->txblk_wrptr; - poolhd_op->tx_addr = poolhd->rxblk_addr; - poolhd_op->tx_count = poolhd->rxblk_count; - poolhd_op->tx_size = poolhd->rxblk_size; - poolhd_op->tx_blks = poolhd->rxblk_blks; - poolhd_op->rx_addr = poolhd->txblk_addr; - poolhd_op->rx_count = poolhd->txblk_count; - poolhd_op->rx_size = poolhd->txblk_size; - poolhd_op->rx_blks = poolhd->txblk_blks; - - /* release resource */ - sipc_smem_release_resource(sipc->sipc_pms, sipc->dst); - - return 0; - -sblock_client_tx_free: - kfree(sblock->ring->txrecord); -sblock_client_unmap: - shmem_ram_unmap(dst, sblock->smem_virt); -sblock_client_smem_free: - smem_free(dst, sblock->smem_addr_debug, sblock->smem_size); - - return rval; -} - -static int sblock_thread(void *data) -{ - struct sblock_mgr *sblock = data; - struct smsg mcmd, mrecv; - unsigned long flags; - int rval; - int recovery = 0; - struct smsg_ipc *sipc; - struct sblock_ring *ring; - - /* since the channel open may hang, we call it in the sblock thread */ - rval = smsg_ch_open(sblock->dst, sblock->channel, -1); - if (rval != 0) { - pr_err("Failed to open channel %d\n", - sblock->channel); - - if (sblock->pre_cfg && sblock->handler) { - sblock->handler(SBLOCK_NOTIFY_OPEN_FAILED, - sblock->data); - } - - return rval; - } - - if (sblock->pre_cfg) { - sblock->state = SBLOCK_STATE_READY; - recovery = 1; - if (sblock->handler) - sblock->handler(SBLOCK_NOTIFY_OPEN, sblock->data); - } - - /* if client, send SMSG_CMD_SBLOCK_INIT, wait SMSG_DONE_SBLOCK_INIT */ - sipc = smsg_ipcs[sblock->dst]; - if (sipc->client) { - smsg_set(&mcmd, sblock->channel, SMSG_TYPE_CMD, - SMSG_CMD_SBLOCK_INIT, 0); - smsg_send(sblock->dst, &mcmd, -1); - do { - smsg_set(&mrecv, sblock->channel, 0, 0, 0); - rval = smsg_recv(sblock->dst, &mrecv, -1); - if (rval != 0) { - sblock->thread = NULL; - return rval; - } - } while (mrecv.type != SMSG_TYPE_DONE || - mrecv.flag != SMSG_DONE_SBLOCK_INIT); - sblock->smem_addr = mrecv.value; - pr_info("%s: channel %d-%d, done_sblock_init, address=0x%x!\n", - __func__, - sblock->dst, - sblock->channel, - sblock->smem_addr); - if (sblock_client_init(sipc, sblock)) { - sblock->thread = NULL; - return 0; - } - sblock->state = SBLOCK_STATE_READY; - if (sblock->handler) - sblock->handler(SBLOCK_NOTIFY_OPEN, - sblock->data); - } - - /* handle the sblock events */ - while (!kthread_should_stop()) { - /* monitor sblock recv smsg */ - smsg_set(&mrecv, sblock->channel, 0, 0, 0); - rval = smsg_recv(sblock->dst, &mrecv, -1); - if (rval == -EIO || rval == -ENODEV) { - /* channel state is FREE */ - msleep(20); - continue; - } - - pr_debug("sblock thread recv msg: dst=%d, channel=%d, type=%d, flag=0x%04x, value=0x%08x\n", - sblock->dst, sblock->channel, - mrecv.type, mrecv.flag, mrecv.value); - - switch (mrecv.type) { - case SMSG_TYPE_OPEN: - pr_info("%s: channel %d-%d,revc open!\n", - __func__, - sblock->dst, - sblock->channel); - /* handle channel recovery */ - if (recovery) { - if (sblock->handler) - sblock->handler(SBLOCK_NOTIFY_CLOSE, - sblock->data); - sblock_recover(sblock->dst, sblock->channel); - } - smsg_open_ack(sblock->dst, sblock->channel); - if (sblock->pre_cfg) - sblock->state = SBLOCK_STATE_READY; - break; - case SMSG_TYPE_CLOSE: - /* handle channel recovery */ - smsg_close_ack(sblock->dst, sblock->channel); - if (sblock->handler) - sblock->handler(SBLOCK_NOTIFY_CLOSE, - sblock->data); - sblock->state = SBLOCK_STATE_IDLE; - break; - case SMSG_TYPE_CMD: - if (!sblock->pre_cfg) { - /* respond cmd done for sblock init */ - WARN_ON(mrecv.flag != SMSG_CMD_SBLOCK_INIT); - smsg_set(&mcmd, - sblock->channel, - SMSG_TYPE_DONE, - SMSG_DONE_SBLOCK_INIT, - sblock->dst_smem_addr); - smsg_send(sblock->dst, &mcmd, -1); - sblock->state = SBLOCK_STATE_READY; - recovery = 1; - pr_info("%s: channel %d-%d, SMSG_CMD_SBLOCK_INIT, dst address = 0x%x!\n", - __func__, - sblock->dst, - sblock->channel, - sblock->dst_smem_addr); - - if (sblock->handler) - sblock->handler(SBLOCK_NOTIFY_OPEN, - sblock->data); - } - break; - case SMSG_TYPE_EVENT: - /* handle sblock send/release events */ - switch (mrecv.flag) { - case SMSG_EVENT_SBLOCK_SEND: - ring = sblock->ring; - /* set read mask. */ - spin_lock_irqsave(&ring->poll_lock, flags); - ring->poll_mask |= POLLIN | POLLRDNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - wake_up_interruptible_all(&sblock->ring->recvwait); - if (sblock->handler) - sblock->handler(SBLOCK_NOTIFY_RECV, - sblock->data); - break; - case SMSG_EVENT_SBLOCK_RELEASE: - ring = sblock->ring; - /* set write mask. */ - spin_lock_irqsave(&ring->poll_lock, flags); - ring->poll_mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - wake_up_interruptible_all(&sblock->ring->getwait); - if (sblock->handler) - sblock->handler(SBLOCK_NOTIFY_GET, - sblock->data); - break; - default: - rval = 1; - break; - } - break; - default: - rval = 1; - break; - }; - - if (rval) { - pr_info("non-handled sblock msg: %d-%d, %d, %d, %d\n", - sblock->dst, sblock->channel, - mrecv.type, mrecv.flag, mrecv.value); - rval = 0; - } - } - - pr_info("sblock %d-%d thread stop", - sblock->dst, sblock->channel); - return rval; -} - -static void sblock_pms_init(uint8_t dst, uint8_t ch, struct sblock_ring *ring) -{ - sprintf(ring->tx_pms_name, "sblock-%d-%d-tx", dst, ch); - ring->tx_pms = sprd_pms_create(dst, ring->tx_pms_name, true); - if (!ring->tx_pms) - pr_warn("create pms %s failed!\n", ring->tx_pms_name); - - sprintf(ring->rx_pms_name, "sblock-%d-%d-rx", dst, ch); - ring->rx_pms = sprd_pms_create(dst, ring->rx_pms_name, true); - if (!ring->rx_pms) - pr_warn("create pms %s failed!\n", ring->rx_pms_name); -} - -static void sblock_pms_destroy(struct sblock_ring *ring) -{ - sprd_pms_destroy(ring->tx_pms); - sprd_pms_destroy(ring->rx_pms); - ring->tx_pms = NULL; - ring->rx_pms = NULL; -} - -static int sblock_mgr_create(uint8_t dst, - uint8_t channel, - int pre_cfg, - uint32_t tx_blk_num, uint32_t tx_blk_sz, - uint32_t rx_blk_num, uint32_t rx_blk_sz, - struct sblock_mgr **sb_mgr) -{ - struct sblock_mgr *sblock = NULL; - struct smsg_ipc *sipc = smsg_ipcs[dst]; - int ret; - - pr_debug("%s: dst=%d channel=%d\n", __func__, dst, channel); - - if (!sipc) - return -EINVAL; - - sblock = kzalloc(sizeof(struct sblock_mgr), GFP_KERNEL); - if (!sblock) - return -ENOMEM; - - sblock->ring = kzalloc(sizeof(struct sblock_ring), GFP_KERNEL); - if (!sblock->ring) { - kfree(sblock); - return -ENOMEM; - } - - sblock->dst = dst; - sblock->channel = channel; - sblock->pre_cfg = pre_cfg; - sblock->state = SBLOCK_STATE_IDLE; - - if (!sipc->client) { - ret = sblock_host_init(sipc, sblock, - tx_blk_num, tx_blk_sz, - rx_blk_num, rx_blk_sz); - if (ret) { - kfree(sblock->ring); - kfree(sblock); - return ret; - } - } - - sblock_pms_init(dst, channel, sblock->ring); - init_waitqueue_head(&sblock->ring->getwait); - init_waitqueue_head(&sblock->ring->recvwait); - spin_lock_init(&sblock->ring->r_txlock); - spin_lock_init(&sblock->ring->r_rxlock); - spin_lock_init(&sblock->ring->p_txlock); - spin_lock_init(&sblock->ring->p_rxlock); - spin_lock_init(&sblock->ring->poll_lock); - - *sb_mgr = sblock; - - return 0; -} - -int sblock_create_ex(u8 dst, u8 channel, - u32 txblocknum, u32 txblocksize, - u32 rxblocknum, u32 rxblocksize, - void (*handler)(int event, void *data), void *data) -{ - struct sblock_mgr *sblock = NULL; - int result; - u8 ch_index; - struct smsg_ipc *sipc; - struct sched_param param = {.sched_priority = 11}; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - if (dst >= SIPC_ID_NR) { - pr_err("%s: dst = %d is invalid\n", __func__, dst); - return -EINVAL; - } - - pr_debug("%s: dst=%d channel=%d\n", __func__, dst, channel); - - result = sblock_mgr_create(dst, channel, 0, - txblocknum, txblocksize, - rxblocknum, rxblocksize, - &sblock); - if (!result) { - sblock->thread = kthread_create(sblock_thread, sblock, - "sblock-%d-%d", dst, channel); - if (IS_ERR(sblock->thread)) { - pr_err("Failed to create kthread: sblock-%d-%d\n", - dst, channel); - sipc = smsg_ipcs[sblock->dst]; - if (!sipc->client) { - shmem_ram_unmap(dst, sblock->smem_virt); - smem_free(dst, - sblock->smem_addr, - sblock->smem_size); - kfree(sblock->ring->txrecord); - kfree(sblock->ring->rxrecord); - } - kfree(sblock->ring); - result = PTR_ERR(sblock->thread); - kfree(sblock); - return result; - } - - /* Prevent the thread task_struct from being destroyed. */ - get_task_struct(sblock->thread); - - sblocks[dst][ch_index] = sblock; - if ((handler != NULL) && (data != NULL)) { - result = sblock_register_notifier(dst, channel, - handler, data); - if (result < 0) { - sblock_destroy(dst, channel); - return result; - } - } - /*set the thread as a real time thread, and its priority is 11*/ - sched_setscheduler(sblock->thread, SCHED_RR, ¶m); - wake_up_process(sblock->thread); - } - - pr_debug("%s: sblock-%d-%d create over, result = %d\n", - __func__, dst, channel, result); - - return result; -} -EXPORT_SYMBOL_GPL(sblock_create_ex); - -int sblock_create(u8 dst, u8 channel, - u32 txblocknum, u32 txblocksize, - u32 rxblocknum, u32 rxblocksize) -{ - return sblock_create_ex(dst, channel, txblocknum, txblocksize, - rxblocknum, rxblocksize, NULL, NULL); -} -EXPORT_SYMBOL_GPL(sblock_create); - -int sblock_pcfg_create(u8 dst, u8 channel, - u32 tx_blk_num, u32 tx_blk_sz, - u32 rx_blk_num, u32 rx_blk_sz) -{ - struct sblock_mgr *sblock = NULL; - int result; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - if (dst >= SIPC_ID_NR) { - pr_err("sblock_create_ex: dst = %d is invalid\n", dst); - return -EINVAL; - } - - pr_debug("%s: dst=%d channel=%d\n", __func__, dst, channel); - - result = sblock_mgr_create(dst, - channel, - 1, - tx_blk_num, tx_blk_sz, - rx_blk_num, rx_blk_sz, - &sblock); - if (!result) { - struct sched_param param = {.sched_priority = 11}; - - sblock->thread = kthread_create(sblock_thread, sblock, - "sblock-%d-%d", dst, channel); - if (IS_ERR(sblock->thread)) { - struct smsg_ipc *sipc; - - pr_err("Failed to create kthread: sblock-%d-%d\n", - dst, channel); - sipc = smsg_ipcs[sblock->dst]; - if (!sipc->client) { - shmem_ram_unmap(dst, sblock->smem_virt); - smem_free(dst, - sblock->smem_addr, - sblock->smem_size); - kfree(sblock->ring->txrecord); - kfree(sblock->ring->rxrecord); - } - kfree(sblock->ring); - result = PTR_ERR(sblock->thread); - kfree(sblock); - return result; - } - - /* Prevent the thread task_struct from being destroyed. */ - get_task_struct(sblock->thread); - - sblocks[dst][ch_index] = sblock; - /* - * Set the thread as a real time thread, and its priority - * is 11. - */ - sched_setscheduler(sblock->thread, SCHED_RR, ¶m); - wake_up_process(sblock->thread); - } - - return result; -} -EXPORT_SYMBOL_GPL(sblock_pcfg_create); - -void sblock_down(u8 dst, u8 channel) -{ - struct sblock_mgr *sblock; - u8 ch_index; - int i; - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return; - } - - sblock = sblocks[dst][ch_index]; - if (sblock == NULL) - return; - - sblock->state = SBLOCK_STATE_IDLE; - if (sblock->ring) { - wake_up_interruptible_all(&sblock->ring->recvwait); - wake_up_interruptible_all(&sblock->ring->getwait); - } - pr_info("%s: channel=%d sblock down success\n", __func__, channel); - -} -EXPORT_SYMBOL_GPL(sblock_down); - -void sblock_destroy(u8 dst, u8 channel) -{ - struct sblock_mgr *sblock; - u8 ch_index; - struct smsg_ipc *sipc; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return; - } - - sblock = sblocks[dst][ch_index]; - if (sblock == NULL) - return; - - sblock->state = SBLOCK_STATE_IDLE; - smsg_ch_close(dst, channel, -1); - - /* stop sblock thread if it's created successfully and still alive */ - if (!IS_ERR_OR_NULL(sblock->thread)) { - kthread_stop(sblock->thread); - put_task_struct(sblock->thread); - sblock->thread = NULL; - } - - if (sblock->ring) { - sblock_pms_destroy(sblock->ring); - wake_up_interruptible_all(&sblock->ring->recvwait); - wake_up_interruptible_all(&sblock->ring->getwait); - /* kfree(NULL) is safe */ - /* if (sblock->ring->txrecord) */ - kfree(sblock->ring->txrecord); - /* if (sblock->ring->rxrecord) */ - kfree(sblock->ring->rxrecord); - kfree(sblock->ring); - } - if (sblock->smem_virt) - shmem_ram_unmap(dst, sblock->smem_virt); - - sipc = smsg_ipcs[dst]; - if (sipc->client) - smem_free(dst, sblock->smem_addr_debug, sblock->smem_size); - else - smem_free(dst, sblock->smem_addr, sblock->smem_size); - kfree(sblock); - - sblocks[dst][ch_index] = NULL; -} -EXPORT_SYMBOL_GPL(sblock_destroy); - -int sblock_pcfg_open(uint8_t dest, uint8_t channel, - void (*notifier)(int event, void *client), - void *client) -{ - struct sblock_mgr *sblock; - uint8_t idx; - int ret; - struct sched_param param = {.sched_priority = 11}; - - pr_debug("%s: dst=%d channel=%d\n", __func__, dest, channel); - - if (!notifier) - return -EINVAL; - - idx = sipc_channel2index(channel); - if (idx == INVALID_CHANEL_INDEX) { - pr_err("%s: invalid channel %d!\n", __func__, channel); - return -ENODEV; - } - - sblock = sblocks[dest][idx]; - if (!sblock) - return -ENODEV; - - if (!sblock->pre_cfg) - return -EINVAL; - - if (sblock->thread) { - pr_err("%s: SBLOCK %u/%u already open", - __func__, - (unsigned int)sblock->dst, - (unsigned int)sblock->channel); - return -EPROTO; - } - - ret = 0; - sblock->thread = kthread_create(sblock_thread, sblock, - "sblock-%d-%d", dest, channel); - if (IS_ERR(sblock->thread)) { - pr_err("%s: create thread error\n", __func__); - sblock->thread = NULL; - ret = -EBUSY; - } else { - /* Prevent the thread task_struct from being destroyed. */ - get_task_struct(sblock->thread); - - sblock->handler = notifier; - sblock->data = client; - /*set the thread as a real time thread, and its priority is 11*/ - sched_setscheduler(sblock->thread, SCHED_RR, ¶m); - wake_up_process(sblock->thread); - } - - return ret; -} -EXPORT_SYMBOL_GPL(sblock_pcfg_open); - -int sblock_close(uint8_t dest, uint8_t channel) -{ - return -ENOTSUPP; -} -EXPORT_SYMBOL_GPL(sblock_close); - -int sblock_register_notifier(u8 dst, u8 channel, - void (*handler)(int event, void *data), - void *data) -{ - struct sblock_mgr *sblock; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - - if (!sblock) { - pr_err("%s:sblock-%d-%d not ready!\n", __func__, dst, channel); - return -ENODEV; - } -#ifndef CONFIG_SPRD_SIPC_WCN - if (sblock->handler) { - pr_err("sblock handler already registered\n"); - return -EBUSY; - } -#endif - sblock->handler = handler; - sblock->data = data; - - return 0; -} -EXPORT_SYMBOL_GPL(sblock_register_notifier); - -int sblock_get_smem_cp_addr(uint8_t dest, uint8_t channel, - uint32_t *paddr) -{ - struct sblock_mgr *sblock; - uint8_t idx; - - if (!paddr) - return -EINVAL; - - idx = sipc_channel2index(channel); - if (idx == INVALID_CHANEL_INDEX) { - pr_err("%s: invalid channel %d!\n", __func__, channel); - return -ENODEV; - } - - sblock = sblocks[dest][idx]; - if (!sblock) - return -ENODEV; - - *paddr = sblock->dst_smem_addr; - - return 0; -} -EXPORT_SYMBOL_GPL(sblock_get_smem_cp_addr); - -int sblock_get(u8 dst, u8 channel, struct sblock *blk, int timeout) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring; - struct sblock_ring_header_op *poolhd_op; - - int txpos, index; - int rval = 0; - unsigned long flags; - u8 ch_index; - bool no_data; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - - if (!sblock || sblock->state != SBLOCK_STATE_READY) { - pr_err("%s:sblock-%d-%d not ready!\n", __func__, dst, channel); - return sblock ? -EIO : -ENODEV; - } - - ring = sblock->ring; - poolhd_op = &(ring->header_op.poolhd_op); - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->tx_pms, dst, timeout); - if (rval < 0) - return rval; - - spin_lock_irqsave(&ring->poll_lock, flags); - no_data = *(poolhd_op->tx_rd_p) == *(poolhd_op->tx_wt_p); - /* update write mask */ - if (no_data) - ring->poll_mask &= ~(POLLOUT | POLLWRNORM); - else - ring->poll_mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - /* release resource */ - sipc_smem_release_resource(ring->tx_pms, dst); - - if (no_data) { - if (timeout == 0) { - /* no wait */ - pr_err("%s: %d-%d is empty!\n", __func__, dst, channel); - rval = -ENODATA; - } else if (timeout < 0) { - /* wait forever */ - rval = wait_event_interruptible(ring->getwait, - sblock_has_data(sblock, true) || - sblock->state == SBLOCK_STATE_IDLE); - if (rval < 0) - pr_debug("%s: wait interrupted!\n", __func__); - - if (sblock->state == SBLOCK_STATE_IDLE) { - pr_err("%s: state is idle!\n", __func__); - rval = -EIO; - } - } else { - /* wait timeout */ - rval = wait_event_interruptible_timeout(ring->getwait, - sblock_has_data(sblock, true) || - sblock == SBLOCK_STATE_IDLE, - timeout); - if (rval < 0) { - pr_debug("%s: wait interrupted!\n", __func__); - } else if (rval == 0) { - pr_info("%s: wait timeout!\n", __func__); - rval = -ETIME; - } - - if (sblock->state == SBLOCK_STATE_IDLE) { - pr_info("%s: state is idle!\n", __func__); - rval = -EIO; - } - } - } - - if (rval < 0) - return rval; - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->tx_pms, dst, timeout); - if (rval < 0) - return rval; - - /* multi-gotter may cause got failure */ - spin_lock_irqsave(&ring->p_txlock, flags); - if (*(poolhd_op->tx_rd_p) != *(poolhd_op->tx_wt_p) && - sblock->state == SBLOCK_STATE_READY) { - txpos = sblock_get_ringpos(*(poolhd_op->tx_rd_p), - poolhd_op->tx_count); - blk->addr = sblock->smem_virt + - (ring->p_txblks[txpos].addr - - sblock->stored_smem_addr); - blk->length = poolhd_op->tx_size; - *(poolhd_op->tx_rd_p) = *(poolhd_op->tx_rd_p) + 1; - index = sblock_get_index((blk->addr - ring->txblk_virt), - sblock->txblksz); - ring->txrecord[index] = SBLOCK_BLK_STATE_PENDING; - } else { - /* release resource */ - sipc_smem_release_resource(ring->tx_pms, dst); - rval = sblock->state == SBLOCK_STATE_READY ? -EAGAIN : -EIO; - } - spin_unlock_irqrestore(&ring->p_txlock, flags); - - spin_lock_irqsave(&ring->poll_lock, flags); - /* update write mask */ - if (*(poolhd_op->tx_wt_p) == *(poolhd_op->tx_rd_p)) - ring->poll_mask &= ~(POLLOUT | POLLWRNORM); - else - ring->poll_mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - return rval; -} -EXPORT_SYMBOL_GPL(sblock_get); - -static int sblock_send_ex(u8 dst, u8 channel, - struct sblock *blk, bool yell) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring; - struct sblock_ring_header_op *ringhd_op; - struct smsg mevt; - int txpos, index; - int rval = 0; - unsigned long flags; - u8 ch_index; - bool send_event = false; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - - if (!sblock || sblock->state != SBLOCK_STATE_READY) { - pr_err("%s:sblock-%d-%d not ready!\n", __func__, dst, channel); - return sblock ? -EIO : -ENODEV; - } - - pr_debug("sblock_send: dst=%d, channel=%d, addr=%p, len=%d\n", - dst, channel, blk->addr, blk->length); - - ring = sblock->ring; - ringhd_op = &(ring->header_op.ringhd_op); - - spin_lock_irqsave(&ring->r_txlock, flags); - - txpos = sblock_get_ringpos(*(ringhd_op->tx_wt_p), ringhd_op->tx_count); - ring->r_txblks[txpos].addr = blk->addr - - sblock->smem_virt + - sblock->stored_smem_addr; - ring->r_txblks[txpos].length = blk->length; - pr_debug("sblock_send: channel=%d, wrptr=%d, txpos=%d, addr=%x\n", - channel, *(ringhd_op->tx_wt_p), - txpos, ring->r_txblks[txpos].addr); - *(ringhd_op->tx_wt_p) = *(ringhd_op->tx_wt_p) + 1; - - if (sblock->state == SBLOCK_STATE_READY) { - if (yell) { - send_event = true; - } else if (!ring->yell) { - if ((int)(*(ringhd_op->tx_wt_p) - - *(ringhd_op->tx_rd_p)) == 1) - ring->yell = 1; - } - } - index = sblock_get_index((blk->addr - ring->txblk_virt), - sblock->txblksz); - ring->txrecord[index] = SBLOCK_BLK_STATE_DONE; - - spin_unlock_irqrestore(&ring->r_txlock, flags); - - /* request in sblock_get, release here */ - sipc_smem_release_resource(ring->tx_pms, dst); - - /* - * smsg_send may caused schedule, - * can't be called in spinlock protected context. - */ - if (send_event) { - smsg_set(&mevt, channel, - SMSG_TYPE_EVENT, - SMSG_EVENT_SBLOCK_SEND, - 0); - rval = smsg_send(dst, &mevt, -1); - } - - return rval; -} - -int sblock_send(u8 dst, u8 channel, struct sblock *blk) -{ - return sblock_send_ex(dst, channel, blk, true); -} -EXPORT_SYMBOL_GPL(sblock_send); - -int sblock_send_prepare(u8 dst, u8 channel, struct sblock *blk) -{ - return sblock_send_ex(dst, channel, blk, false); -} -EXPORT_SYMBOL_GPL(sblock_send_prepare); - -int sblock_send_finish(u8 dst, u8 channel) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring; - struct sblock_ring_header_op *ringhd_op; - struct smsg mevt; - int rval = 0; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - if (!sblock || sblock->state != SBLOCK_STATE_READY) { - pr_err("%s:sblock-%d-%d not ready!\n", __func__, dst, channel); - return sblock ? -EIO : -ENODEV; - } - - ring = sblock->ring; - ringhd_op = &(ring->header_op.ringhd_op); - - /* must wait resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->tx_pms, dst, -1); - if (rval) - return rval; - - if (*(ringhd_op->tx_wt_p) != *(ringhd_op->tx_rd_p)) { - smsg_set(&mevt, channel, - SMSG_TYPE_EVENT, - SMSG_EVENT_SBLOCK_SEND, 0); - rval = smsg_send(dst, &mevt, -1); - } - /* release resource */ - sipc_smem_release_resource(ring->tx_pms, dst); - - return rval; -} -EXPORT_SYMBOL_GPL(sblock_send_finish); - -int sblock_receive(u8 dst, u8 channel, - struct sblock *blk, int timeout) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring; - struct sblock_ring_header_op *ringhd_op; - int rxpos, index, rval = 0; - unsigned long flags; - u8 ch_index; - bool no_data; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - - if (!sblock || sblock->state != SBLOCK_STATE_READY) { - pr_err("%s:sblock-%d-%d not ready!\n", __func__, dst, channel); - return sblock ? -EIO : -ENODEV; - } - - pr_debug("%s: dst=%d, channel=%d, timeout=%d\n", - __func__, dst, channel, timeout); - - ring = sblock->ring; - ringhd_op = &(ring->header_op.ringhd_op); - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->rx_pms, dst, timeout); - if (rval < 0) - return rval; - - pr_debug("%s: channel=%d, wrptr=%d, rdptr=%d", - __func__, channel, - *(ringhd_op->rx_wt_p), - *(ringhd_op->rx_rd_p)); - - spin_lock_irqsave(&ring->poll_lock, flags); - no_data = *(ringhd_op->rx_wt_p) == *(ringhd_op->rx_rd_p); - /* update read mask */ - if (no_data) - ring->poll_mask &= ~(POLLIN | POLLRDNORM); - else - ring->poll_mask |= POLLIN | POLLRDNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - /* release resource */ - sipc_smem_release_resource(ring->rx_pms, dst); - - if (no_data) { - if (timeout == 0) { - /* no wait */ - pr_debug("%s: %d-%d is empty!\n", - __func__, dst, channel); - rval = -ENODATA; - } else if (timeout < 0) { - /* wait forever */ - rval = wait_event_interruptible(ring->recvwait, - sblock_has_data(sblock, false)); - if (rval < 0) - pr_info("%s: wait interrupted!\n", __func__); - - if (sblock->state == SBLOCK_STATE_IDLE) { - pr_info("%s: state is idle!\n", __func__); - rval = -EIO; - } - - } else { - /* wait timeout */ - rval = wait_event_interruptible_timeout(ring->recvwait, - sblock_has_data(sblock, false), - timeout); - if (rval < 0) { - pr_info("%s: wait interrupted!\n", __func__); - } else if (rval == 0) { - pr_info("%s: wait timeout!\n", __func__); - rval = -ETIME; - } - - if (sblock->state == SBLOCK_STATE_IDLE) { - pr_info("%s: state is idle!\n", __func__); - rval = -EIO; - } - } - } - - if (rval < 0) - return rval; - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->rx_pms, dst, timeout); - if (rval < 0) - return rval; - - /* multi-receiver may cause recv failure */ - spin_lock_irqsave(&ring->r_rxlock, flags); - - if (*(ringhd_op->rx_wt_p) != *(ringhd_op->rx_rd_p) && - sblock->state == SBLOCK_STATE_READY) { - rxpos = sblock_get_ringpos(*(ringhd_op->rx_rd_p), - ringhd_op->rx_count); - blk->addr = ring->r_rxblks[rxpos].addr - - sblock->stored_smem_addr + - sblock->smem_virt; - blk->length = ring->r_rxblks[rxpos].length; - *(ringhd_op->rx_rd_p) = *(ringhd_op->rx_rd_p) + 1; - pr_debug("%s: channel=%d, rxpos=%d, addr=%p, len=%d\n", - __func__, channel, rxpos, blk->addr, blk->length); - index = sblock_get_index((blk->addr - ring->rxblk_virt), - sblock->rxblksz); - ring->rxrecord[index] = SBLOCK_BLK_STATE_PENDING; - } else { - /* release resource */ - sipc_smem_release_resource(ring->rx_pms, dst); - rval = sblock->state == SBLOCK_STATE_READY ? -EAGAIN : -EIO; - } - spin_unlock_irqrestore(&ring->r_rxlock, flags); - - spin_lock_irqsave(&ring->poll_lock, flags); - /* update read mask */ - if (*(ringhd_op->rx_wt_p) == *(ringhd_op->rx_rd_p)) - ring->poll_mask &= ~(POLLIN | POLLRDNORM); - else - ring->poll_mask |= POLLIN | POLLRDNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - return rval; -} -EXPORT_SYMBOL_GPL(sblock_receive); - -int sblock_get_arrived_count(u8 dst, u8 channel) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring; - struct sblock_ring_header_op *ringhd_op; - int blk_count = 0; - unsigned long flags; - u8 ch_index; - int rval; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - if (!sblock || sblock->state != SBLOCK_STATE_READY) { - pr_err("%s:sblock-%d-%d not ready!\n", __func__, dst, channel); - return -ENODEV; - } - - ring = sblock->ring; - ringhd_op = &(ring->header_op.ringhd_op); - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->rx_pms, dst, -1); - if (rval < 0) - return rval; - - spin_lock_irqsave(&ring->r_rxlock, flags); - blk_count = (int)(*(ringhd_op->rx_wt_p) - *(ringhd_op->rx_rd_p)); - spin_unlock_irqrestore(&ring->r_rxlock, flags); - /* release resource */ - sipc_smem_release_resource(ring->rx_pms, dst); - - return blk_count; - -} -EXPORT_SYMBOL_GPL(sblock_get_arrived_count); - -int sblock_get_free_count(u8 dst, u8 channel) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring; - struct sblock_ring_header_op *poolhd_op; - int blk_count = 0, rval; - unsigned long flags; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - if (!sblock || sblock->state != SBLOCK_STATE_READY) { - pr_err("%s:sblock-%d-%d not ready!\n", __func__, dst, channel); - return -ENODEV; - } - - ring = sblock->ring; - poolhd_op = &(ring->header_op.poolhd_op); - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->tx_pms, dst, -1); - if (rval < 0) - return rval; - - spin_lock_irqsave(&ring->p_txlock, flags); - blk_count = (int)(*(poolhd_op->tx_wt_p) - *(poolhd_op->tx_rd_p)); - spin_unlock_irqrestore(&ring->p_txlock, flags); - /* release resource */ - sipc_smem_release_resource(ring->tx_pms, dst); - - return blk_count; -} -EXPORT_SYMBOL_GPL(sblock_get_free_count); - -int sblock_release(u8 dst, u8 channel, struct sblock *blk) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring; - struct sblock_ring_header_op *poolhd_op; - struct smsg mevt; - unsigned long flags; - int rxpos; - int index; - u8 ch_index; - bool send_event = false; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - if (!sblock || sblock->state != SBLOCK_STATE_READY) { - pr_err("%s:sblock-%d-%d not ready!\n", __func__, dst, channel); - return -ENODEV; - } - - pr_debug("%s: dst=%d, channel=%d, addr=%p, len=%d\n", - __func__, dst, channel, blk->addr, blk->length); - - ring = sblock->ring; - poolhd_op = &(ring->header_op.poolhd_op); - - spin_lock_irqsave(&ring->p_rxlock, flags); - rxpos = sblock_get_ringpos(*(poolhd_op->rx_wt_p), poolhd_op->rx_count); - ring->p_rxblks[rxpos].addr = blk->addr - - sblock->smem_virt + - sblock->stored_smem_addr; - ring->p_rxblks[rxpos].length = poolhd_op->rx_size; - *(poolhd_op->rx_wt_p) = *(poolhd_op->rx_wt_p) + 1; - pr_debug("%s: addr=%x\n", __func__, ring->p_rxblks[rxpos].addr); - - if ((int)(*(poolhd_op->rx_wt_p) - *(poolhd_op->rx_rd_p)) == 1 && - sblock->state == SBLOCK_STATE_READY) { - /* send smsg to notify the peer side */ - send_event = true; - } - - index = sblock_get_index((blk->addr - ring->rxblk_virt), - sblock->rxblksz); - ring->rxrecord[index] = SBLOCK_BLK_STATE_DONE; - - spin_unlock_irqrestore(&ring->p_rxlock, flags); - - /* request in sblock_receive, release here */ - sipc_smem_release_resource(ring->rx_pms, dst); - - /* - * smsg_send may caused schedule, - * can't be called in spinlock protected context. - */ - if (send_event) { - smsg_set(&mevt, channel, - SMSG_TYPE_EVENT, - SMSG_EVENT_SBLOCK_RELEASE, - 0); - smsg_send(dst, &mevt, -1); - } - - return 0; -} -EXPORT_SYMBOL_GPL(sblock_release); - -unsigned int sblock_poll_wait(u8 dst, u8 channel, - struct file *filp, poll_table *wait) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring; - struct sblock_ring_header_op *poolhd_op; - struct sblock_ring_header_op *ringhd_op; - unsigned int mask = 0; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return mask; - } - sblock = sblocks[dst][ch_index]; - - if (!sblock) - return mask; - ring = sblock->ring; - poolhd_op = &(ring->header_op.poolhd_op); - ringhd_op = &(ring->header_op.ringhd_op); - - if (sblock->state != SBLOCK_STATE_READY) { - pr_debug("%s:sblock-%d-%d not ready to poll !\n", - __func__, dst, channel); - return mask; - } - poll_wait(filp, &ring->recvwait, wait); - poll_wait(filp, &ring->getwait, wait); - - if (sblock_has_data(sblock, true)) - mask |= POLLOUT | POLLWRNORM; - - if (sblock_has_data(sblock, false)) - mask |= POLLIN | POLLRDNORM; - - return mask; -} -EXPORT_SYMBOL_GPL(sblock_poll_wait); - -int sblock_query(u8 dst, u8 channel) -{ - struct sblock_mgr *sblock = NULL; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - if (!sblock) - return -ENODEV; - if (sblock->state != SBLOCK_STATE_READY) { - pr_debug("%s:sblock-%d-%d not ready!\n", __func__, dst, channel); - return -EINVAL; - } - return 0; -} -EXPORT_SYMBOL_GPL(sblock_query); - -#if defined(CONFIG_DEBUG_FS) -static int sblock_debug_show(struct seq_file *m, void *private) -{ - struct smsg_ipc *sipc = NULL; - struct sblock_mgr *sblock; - struct sblock_ring *ring; - struct sblock_ring_header_op *poolhd_op; - struct sblock_ring_header_op *ringhd_op; - int i, j; - - for (i = 0; i < SIPC_ID_NR; i++) { - sipc = smsg_ipcs[i]; - if (!sipc) - continue; - - /* must request resource before read or write share memory */ - if (sipc_smem_request_resource(sipc->sipc_pms, - sipc->dst, 1000) < 0) - continue; - - for (j = 0; j < SMSG_VALID_CH_NR; j++) { - sblock = sblocks[i][j]; - if (!sblock) - continue; - - sipc_debug_putline(m, '*', 170); - seq_printf(m, "sblock dst %d, channel: %3d, state: %d, smem_virt: 0x%lx, smem_addr: 0x%0x, dst_smem_addr: 0x%0x, smem_size: 0x%0x, txblksz: %d, rxblksz: %d\n", - sblock->dst, - sblock->channel, - sblock->state, - (unsigned long)sblock->smem_virt, - sblock->smem_addr, - sblock->dst_smem_addr, - sblock->smem_size, - sblock->txblksz, - sblock->rxblksz); - - /* - * in precfg channel, the ring pinter can be null - * before the the block manger has been created - * and ring->header pointer can also be null - * before the block handshake with host, - * so must add null pointer protect here. - */ - ring = sblock->ring; - if (!ring || !ring->header) - continue; - - poolhd_op = &(ring->header_op.poolhd_op); - ringhd_op = &(ring->header_op.ringhd_op); - seq_printf(m, "sblock ring: txblk_virt :0x%lx, rxblk_virt :0x%lx, poll_mask=0x%x\n", - (unsigned long)ring->txblk_virt, - (unsigned long)ring->rxblk_virt, - ring->poll_mask); - seq_printf(m, "sblock ring header: rxblk_addr :0x%0x, rxblk_rdptr :0x%0x, rxblk_wrptr :0x%0x, rxblk_size :%d, rxblk_count :%d, rxblk_blks: 0x%0x\n", - ringhd_op->rx_addr, *(ringhd_op->rx_rd_p), - *(ringhd_op->rx_wt_p), ringhd_op->rx_size, - ringhd_op->rx_count, ringhd_op->rx_blks); - seq_printf(m, "sblock ring header: txblk_addr :0x%0x, txblk_rdptr :0x%0x, txblk_wrptr :0x%0x, txblk_size :%d, txblk_count :%d, txblk_blks: 0x%0x\n", - ringhd_op->tx_addr, *(ringhd_op->tx_rd_p), - *(ringhd_op->tx_wt_p), ringhd_op->tx_size, - ringhd_op->tx_count, ringhd_op->tx_blks); - seq_printf(m, "sblock pool header: rxblk_addr :0x%0x, rxblk_rdptr :0x%0x, rxblk_wrptr :0x%0x, rxblk_size :%d, rxpool_count :%d, rxblk_blks: 0x%0x\n", - poolhd_op->rx_addr, *(poolhd_op->rx_rd_p), - *(poolhd_op->rx_wt_p), poolhd_op->rx_size, - poolhd_op->rx_count, poolhd_op->rx_blks); - seq_printf(m, "sblock pool header: txblk_addr :0x%0x, txblk_rdptr :0x%0x, txblk_wrptr :0x%0x, txblk_size :%d, txpool_count :%d, txblk_blks: 0x%0x\n", - poolhd_op->tx_addr, *(poolhd_op->tx_rd_p), - *(poolhd_op->tx_wt_p), poolhd_op->tx_size, - poolhd_op->tx_count, poolhd_op->tx_blks); - } - /* release resource */ - sipc_smem_release_resource(sipc->sipc_pms, sipc->dst); - } - - return 0; -} - -static int sblock_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, sblock_debug_show, inode->i_private); -} - -static const struct file_operations sblock_debug_fops = { - .open = sblock_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -int sblock_init_debugfs(void *root) -{ - if (!root) - return -ENXIO; - debugfs_create_file("sblock", 0444, - (struct dentry *)root, - NULL, &sblock_debug_fops); - return 0; -} -EXPORT_SYMBOL_GPL(sblock_init_debugfs); - -#endif /* CONFIG_DEBUG_FS */ - - -MODULE_AUTHOR("Chen Gaopeng"); -MODULE_DESCRIPTION("SIPC/SBLOCK driver"); -MODULE_LICENSE("GPL v2"); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sblock.h b/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sblock.h deleted file mode 100644 index 13d67afa2..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sblock.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#ifndef __SBLOCK_H -#define __SBLOCK_H - -/* flag for CMD/DONE msg type */ -#define SMSG_CMD_SBLOCK_INIT 0x1 -#define SMSG_DONE_SBLOCK_INIT 0x2 - -/* flag for EVENT msg type */ -#define SMSG_EVENT_SBLOCK_SEND 0x1 -#define SMSG_EVENT_SBLOCK_RELEASE 0x2 - -#define SBLOCK_STATE_IDLE 0 -#define SBLOCK_STATE_READY 1 - -#define SBLOCK_BLK_STATE_DONE 0 -#define SBLOCK_BLK_STATE_PENDING 1 - -struct sblock_blks { - u32 addr; /*phy address*/ - u32 length; -}; - -/* ring block header */ -struct sblock_ring_header { - /* get|send-block info */ - u32 txblk_addr; /* tx blocks start addr */ - u32 txblk_count; /* tx blocks num */ - u32 txblk_size; /* one tx block size */ - u32 txblk_blks; /* tx_ring or tx_pool start addr */ - u32 txblk_rdptr; /* tx_ring or tx_pool read point */ - u32 txblk_wrptr; /* tx_ring or tx_pool write point */ - - /* release|recv-block info */ - u32 rxblk_addr; - u32 rxblk_count; - u32 rxblk_size; - u32 rxblk_blks; - u32 rxblk_rdptr; - u32 rxblk_wrptr; -}; - -struct sblock_header { - struct sblock_ring_header ring; - struct sblock_ring_header pool; -}; - -struct sblock_ring_header_op { - /* - * this points point to share memory - * for update rdptr and wtptr on share memory - */ - volatile u32 *tx_rd_p; - volatile u32 *tx_wt_p; - volatile u32 *rx_rd_p; - volatile u32 *rx_wt_p; - - /* - * this member copy from share memory, - * because this contents will not change on share memory - */ - u32 tx_addr; /* txblk_addr */ - u32 tx_count; /* txblk_count */ - u32 tx_size; /* txblk_size */ - u32 tx_blks; /* txblk_blks */ - u32 rx_addr; - u32 rx_count; - u32 rx_size; - u32 rx_blks; -}; - -struct sblock_header_op { - struct sblock_ring_header_op ringhd_op; - struct sblock_ring_header_op poolhd_op; -}; - -struct sblock_ring { - struct sblock_header *header; - struct sblock_header_op header_op; - - struct sprd_pms *tx_pms; - struct sprd_pms *rx_pms; - char tx_pms_name[20]; - char rx_pms_name[20]; - - void *txblk_virt; /* virt of header->txblk_addr */ - void *rxblk_virt; /* virt of header->rxblk_addr */ - - /* virt of header->ring->txblk_blks */ - struct sblock_blks *r_txblks; - /* virt of header->ring->rxblk_blks */ - struct sblock_blks *r_rxblks; - /* virt of header->pool->txblk_blks */ - struct sblock_blks *p_txblks; - /* virt of header->pool->rxblk_blks */ - struct sblock_blks *p_rxblks; - - unsigned int poll_mask; - /* protect the poll_mask menber */ - spinlock_t poll_lock; - - int *txrecord; /* record the state of every txblk */ - int *rxrecord; /* record the state of every rxblk */ - int yell; /* need to notify cp */ - spinlock_t r_txlock; /* send */ - spinlock_t r_rxlock; /* recv */ - spinlock_t p_txlock; /* get */ - spinlock_t p_rxlock; /* release */ - - wait_queue_head_t getwait; - wait_queue_head_t recvwait; -}; - -struct sblock_mgr { - u8 dst; - u8 channel; - int pre_cfg; /*support in host mode only */ - u32 state; - - void *smem_virt; - u32 smem_addr; - u32 smem_addr_debug; - u32 smem_size; - u32 dst_smem_addr; - - /* - * this address stored in share memory, - * be used to calculte the block virt address. - * in host mode, it is client physial address(dst_smem_addr), - * in client mode, it is own physial address(smem_addr). - */ - u32 stored_smem_addr; - - u32 txblksz; - u32 rxblksz; - u32 txblknum; - u32 rxblknum; - - struct sblock_ring *ring; - struct task_struct *thread; - - void (*handler)(int event, void *data); - void *data; -}; - -#ifdef CONFIG_64BIT -#define SBLOCK_ALIGN_BYTES (8) -#else -#define SBLOCK_ALIGN_BYTES (4) -#endif - -static inline u32 sblock_get_index(u32 x, u32 y) -{ - return (x / y); -} - -static inline u32 sblock_get_ringpos(u32 x, u32 y) -{ - return is_power_of_2(y) ? (x & (y - 1)) : (x % y); -} -#endif diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sbuf.c b/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sbuf.c deleted file mode 100644 index 2a50b72d6..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sbuf.c +++ /dev/null @@ -1,1755 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,4,60 )) -#include -#include -#endif - -#include "../include/sipc.h" -#include "sipc_priv.h" -#include "sbuf.h" - -#if defined(CONFIG_DEBUG_FS) -#include "sipc_debugfs.h" -#endif - -#define VOLA_SBUF_SMEM volatile struct sbuf_smem_header -#define VOLA_SBUF_RING volatile struct sbuf_ring_header - -struct name_node { - struct list_head list; - char comm[TASK_COMM_LEN]; - pid_t pid; - u8 latest; -}; - -union sbuf_buf { - void *buf; - void __user *ubuf; -}; - -enum task_type { - TASK_RXWAIT = 0, - TASK_TXWAIT, - TASK_SELECT -}; - -static struct sbuf_mgr *sbufs[SIPC_ID_NR][SMSG_VALID_CH_NR]; - -static bool sbuf_has_data(struct sbuf_ring *ring, u8 dst, bool tx) -{ - struct sbuf_ring_header_op *hd_op = &ring->header_op; - bool has_data; - unsigned long flags; - - /* - * if it is local share memory, - * check the read and write point directly. - */ - if (smsg_ipcs[dst]->smem_type == SMEM_LOCAL) { - if (tx) - return (int)(BL_READL(hd_op->tx_wt_p) - BL_READL(hd_op->tx_rd_p)) < - hd_op->tx_size; - - return BL_READL(hd_op->rx_wt_p) != BL_READL(hd_op->rx_rd_p); - } - - /* - * if it is remote share memmory read the poll_mask, - * this situation requires that the poll_mask must be accurate enough. - */ - spin_lock_irqsave(&ring->poll_lock, flags); - if (tx) - has_data = ring->poll_mask & (POLLOUT | POLLWRNORM); - else - has_data = ring->poll_mask & (POLLIN | POLLRDNORM); - spin_unlock_irqrestore(&ring->poll_lock, flags); - - return has_data; -} - -static bool sbuf_is_task_pointer(const void *ptr) -{ - struct task_struct *task; - struct thread_info *thread_info; - - task = (struct task_struct *)ptr; - if (IS_ERR_OR_NULL(task) || !virt_addr_valid(task)) - return false; - -#ifndef CONFIG_THREAD_INFO_IN_TASK - /* in this case thread_info is in the same addres with stack thread_union*/ - if (IS_ERR_OR_NULL(task->stack) || !virt_addr_valid(task->stack)) - return false; -#endif - - thread_info = task_thread_info(task); - - if (IS_ERR_OR_NULL(thread_info) || !virt_addr_valid(thread_info)) - return false; - - return true; -} - -static struct task_struct *sbuf_wait_get_task( -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 4,10,0 )) - wait_queue_t *pos, -#else - wait_queue_entry_t *pos, -#endif - u32 *b_select) -{ - struct task_struct *task; - struct poll_wqueues *table; - - if (!pos->private) - return NULL; - - /* if the private is put into wait list by sbuf_read, the struct of - * pos->private is struct task_struct - * if the private is put into list by sbuf_poll, the struct of - * pos->private is struct poll_wqueues - */ - - /* firstly, try struct poll_wqueues */ - table = (struct poll_wqueues *)pos->private; - task = table->polling_task; - if (sbuf_is_task_pointer(task)) { - *b_select = 1; - return task; - } - - /* firstly, try convert it with the struct task_struct */ - task = (struct task_struct *)pos->private; - - if (sbuf_is_task_pointer(task)) { - *b_select = 0; - return task; - } - - return NULL; -} - -#if defined(SIPC_DEBUG_SBUF_RDWT_OWNER) -static void sbuf_record_rdwt_owner(struct sbuf_ring *ring, int b_rx) -{ - int b_add; - int cnt = 0; - struct name_node *pos = NULL; - struct name_node *temp = NULL; - struct list_head *owner_list; - unsigned long flags; - - b_add = 1; - owner_list = b_rx ? (&ring->rx_list) : (&ring->tx_list); - - spin_lock_irqsave(&ring->rxwait.lock, flags); - list_for_each_entry(pos, owner_list, list) { - cnt++; - if (pos->pid == current->pid) { - b_add = 0; - pos->latest = 1; - continue; - } - if (pos->latest) - pos->latest = 0; - } - spin_unlock_irqrestore(&ring->rxwait.lock, flags); - - if (b_add) { - /* delete head next */ - if (cnt == MAX_RECORD_CNT) { - temp = list_first_entry(owner_list, - struct name_node, list); - list_del(&temp->list); - kfree(temp); - } - - pos = kzalloc(sizeof(*pos), GFP_KERNEL); - if (pos) { - memcpy(pos->comm, current->comm, TASK_COMM_LEN); - pos->pid = current->pid; - pos->latest = 1; - spin_lock_irqsave(&ring->rxwait.lock, flags); - list_add_tail(&pos->list, owner_list); - spin_unlock_irqrestore(&ring->rxwait.lock, flags); - } - } -} - -static void sbuf_destroy_rdwt_owner(struct sbuf_ring *ring) -{ - struct name_node *pos, *temp; - unsigned long flags; - - spin_lock_irqsave(&ring->rxwait.lock, flags); - /* free task node */ - list_for_each_entry_safe(pos, - temp, - &ring->rx_list, - list) { - list_del(&pos->list); - kfree(pos); - } - - list_for_each_entry_safe(pos, - temp, - &ring->tx_list, - list) { - list_del(&pos->list); - kfree(pos); - } - spin_unlock_irqrestore(&ring->rxwait.lock, flags); -} -#endif - -static void sbuf_skip_old_data(struct sbuf_mgr *sbuf) -{ - struct sbuf_ring *ring = NULL; - struct sbuf_ring_header_op *hd_op = NULL; - u32 i, v; - unsigned long flags; - - ring = &sbuf->rings[0]; - /* must reques resource before read or write share memory */ - if (sipc_smem_request_resource(ring->rx_pms, sbuf->dst, -1) < 0) - return; - - for (i = 0; i < sbuf->ringnr; i++) { - ring = &sbuf->rings[i]; - hd_op = &ring->header_op; - - /* clean sbuf tx ring , sbuf tx ring no need to clear */ - /* *(hd_op->tx_wt_p) = *(hd_op->tx_rd_p); */ - /* clean sbuf rx ring */ - v = BL_READL(hd_op->rx_wt_p); - BL_WRITEL(v, hd_op->rx_rd_p); - /* restore write mask. */ - spin_lock_irqsave(&ring->poll_lock, flags); - ring->poll_mask = POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - } - ring = &sbuf->rings[0]; - /* release resource */ - sipc_smem_release_resource(ring->rx_pms, sbuf->dst); -} - -static void sbuf_pms_init(struct sbuf_ring *ring, - uint8_t dst, uint8_t ch, int index) -{ - ring->need_wake_lock = true; - sprintf(ring->tx_pms_name, "sbuf-%d-%d-%d-tx", dst, ch, index); - ring->tx_pms = sprd_pms_create(dst, ring->tx_pms_name, false); - if (!ring->tx_pms) - pr_warn("create pms %s failed!\n", ring->tx_pms_name); - - sprintf(ring->rx_pms_name, "sbuf-%d-%d-%d-rx", dst, ch, index); - ring->rx_pms = sprd_pms_create(dst, ring->rx_pms_name, false); - if (!ring->rx_pms) - pr_warn("create pms %s failed!\n", ring->rx_pms_name); -} - -static void sbuf_comm_init(struct sbuf_mgr *sbuf) -{ - u32 bufnum = sbuf->ringnr; - int i; - struct sbuf_ring *ring; - - for (i = 0; i < bufnum; i++) { - ring = &sbuf->rings[i]; - init_waitqueue_head(&ring->txwait); - init_waitqueue_head(&ring->rxwait); -#if defined(SIPC_DEBUG_SBUF_RDWT_OWNER) - INIT_LIST_HEAD(&ring->tx_list); - INIT_LIST_HEAD(&ring->rx_list); -#endif - mutex_init(&ring->txlock); - mutex_init(&ring->rxlock); - spin_lock_init(&ring->poll_lock); - spin_lock_init(&ring->rxwait.lock); - - /* init, set write mask. */ - ring->poll_mask = POLLOUT | POLLWRNORM; - sbuf_pms_init(ring, sbuf->dst, sbuf->channel, i); - } -} - -static int sbuf_host_init(struct smsg_ipc *sipc, struct sbuf_mgr *sbuf, - u32 bufnum, u32 txbufsize, u32 rxbufsize) -{ - VOLA_SBUF_SMEM *smem; - VOLA_SBUF_RING *ringhd; - struct sbuf_ring_header_op *hd_op; - int hsize, i, rval; - phys_addr_t offset = 0; - u8 dst = sbuf->dst; - struct sbuf_ring *ring; - u32 txbuf_addr; - - sbuf->ringnr = bufnum; - - /* allocate smem */ - hsize = sizeof(struct sbuf_smem_header) + - sizeof(struct sbuf_ring_header) * bufnum; - sbuf->smem_size = hsize + (txbufsize + rxbufsize) * bufnum; - sbuf->smem_addr = smem_alloc(dst, sbuf->smem_size); - if (!sbuf->smem_addr) { - pr_err("%s: channel %d-%d, Failed to allocate smem for sbuf\n", - __func__, sbuf->dst, sbuf->channel); - return -ENOMEM; - } - sbuf->dst_smem_addr = sbuf->smem_addr - sipc->smem_base + - sipc->dst_smem_base; - - pr_debug("%s: channel %d-%d, smem_addr=0x%x, smem_size=0x%x, dst_smem_addr=0x%x\n", - __func__, - sbuf->dst, - sbuf->channel, - sbuf->smem_addr, - sbuf->smem_size, - sbuf->dst_smem_addr); - -#ifdef CONFIG_PHYS_ADDR_T_64BIT - offset = sipc->high_offset; - offset = offset << 32; -#endif - - pr_info("%s: channel %d-%d, offset = 0x%lx!\n", - __func__, sbuf->dst, sbuf->channel, (unsigned long)offset); - sbuf->smem_virt = shmem_ram_vmap_nocache(dst, - sbuf->smem_addr + offset, - sbuf->smem_size); - if (!sbuf->smem_virt) { - pr_err("%s: channel %d-%d, Failed to map smem for sbuf\n", - __func__, sbuf->dst, sbuf->channel); - smem_free(dst, sbuf->smem_addr, sbuf->smem_size); - return -EFAULT; - } - - /* allocate rings description */ - sbuf->rings = kcalloc(bufnum, sizeof(struct sbuf_ring), GFP_KERNEL); - if (!sbuf->rings) { - smem_free(dst, sbuf->smem_addr, sbuf->smem_size); - shmem_ram_unmap(dst, sbuf->smem_virt); - return -ENOMEM; - } - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(sipc->sipc_pms, sipc->dst, -1); - if (rval < 0) { - smem_free(dst, sbuf->smem_addr, sbuf->smem_size); - shmem_ram_unmap(dst, sbuf->smem_virt); - kfree(sbuf->rings); - return rval; - } - - /* initialize all ring bufs */ - smem = (VOLA_SBUF_SMEM *)sbuf->smem_virt; - BL_SETL(smem->ringnr, bufnum); - for (i = 0; i < bufnum; i++) { - ringhd = (VOLA_SBUF_RING *)&smem->headers[i]; - txbuf_addr = sbuf->dst_smem_addr + hsize + - (txbufsize + rxbufsize) * i; - BL_SETL(ringhd->txbuf_addr, txbuf_addr); - BL_SETL(ringhd->txbuf_size, txbufsize); - BL_SETL(ringhd->txbuf_rdptr, 0); - BL_SETL(ringhd->txbuf_wrptr, 0); - BL_SETL(ringhd->rxbuf_addr, txbuf_addr + txbufsize); - BL_SETL(ringhd->rxbuf_size, rxbufsize); - BL_SETL(ringhd->rxbuf_rdptr, 0); - BL_SETL(ringhd->rxbuf_wrptr, 0); - - ring = &sbuf->rings[i]; - ring->header = ringhd; - ring->txbuf_virt = sbuf->smem_virt + hsize + - (txbufsize + rxbufsize) * i; - ring->rxbuf_virt = ring->txbuf_virt + txbufsize; - /* init header op */ - hd_op = &ring->header_op; - hd_op->rx_rd_p = &ringhd->rxbuf_rdptr; - hd_op->rx_wt_p = &ringhd->rxbuf_wrptr; - hd_op->rx_size = ringhd->rxbuf_size; - hd_op->tx_rd_p = &ringhd->txbuf_rdptr; - hd_op->tx_wt_p = &ringhd->txbuf_wrptr; - hd_op->tx_size = ringhd->txbuf_size; - } - - /* release resource */ - sipc_smem_release_resource(sipc->sipc_pms, sipc->dst); - - sbuf_comm_init(sbuf); - - return 0; -} - -static int sbuf_client_init(struct smsg_ipc *sipc, struct sbuf_mgr *sbuf) -{ - VOLA_SBUF_SMEM *smem; - VOLA_SBUF_RING *ringhd; - struct sbuf_ring_header_op *hd_op; - struct sbuf_ring *ring; - int hsize, i, rval; - u32 txbufsize, rxbufsize; - phys_addr_t offset = 0; - u32 bufnum; - u8 dst = sbuf->dst; - -#ifdef CONFIG_PHYS_ADDR_T_64BIT - offset = sipc->high_offset; - offset = offset << 32; - pr_info("%s: channel %d-%d, offset = 0x%llx!\n", - __func__, sbuf->dst, sbuf->channel, offset); -#endif - - /* get bufnum and bufsize */ - hsize = sizeof(struct sbuf_smem_header) + - sizeof(struct sbuf_ring_header) * 1; - sbuf->smem_virt = shmem_ram_vmap_nocache(dst, - sbuf->smem_addr + offset, - hsize); - if (!sbuf->smem_virt) { - pr_err("%s: channel %d-%d, Failed to map smem for sbuf head\n", - __func__, sbuf->dst, sbuf->channel); - return -EFAULT; - } - smem = (VOLA_SBUF_SMEM *)sbuf->smem_virt; - sbuf->ringnr = smem->ringnr; - bufnum = sbuf->ringnr; - ringhd = (VOLA_SBUF_RING *)&smem->headers[0]; - txbufsize = BL_GETL(ringhd->rxbuf_size); - rxbufsize = BL_GETL(ringhd->txbuf_size); - hsize = sizeof(struct sbuf_smem_header) + - sizeof(struct sbuf_ring_header) * bufnum; - sbuf->smem_size = hsize + (txbufsize + rxbufsize) * bufnum; - pr_debug("%s: channel %d-%d, txbufsize = 0x%x, rxbufsize = 0x%x!\n", - __func__, sbuf->dst, sbuf->channel, txbufsize, rxbufsize); - pr_debug("%s: channel %d-%d, smem_size = 0x%x, ringnr = %d!\n", - __func__, sbuf->dst, sbuf->channel, sbuf->smem_size, bufnum); - shmem_ram_unmap(dst, sbuf->smem_virt); - - /* alloc debug smem */ - sbuf->smem_addr_debug = smem_alloc(dst, sbuf->smem_size); - if (!sbuf->smem_addr_debug) { - pr_err("%s: channel %d-%d,Failed to allocate debug smem for sbuf\n", - __func__, sbuf->dst, sbuf->channel); - return -ENOMEM; - } - - /* get smem virtual address */ - sbuf->smem_virt = shmem_ram_vmap_nocache(dst, - sbuf->smem_addr + offset, - sbuf->smem_size); - if (!sbuf->smem_virt) { - pr_err("%s: channel %d-%d,Failed to map smem for sbuf\n", - __func__, sbuf->dst, sbuf->channel); - smem_free(dst, sbuf->smem_addr_debug, sbuf->smem_size); - return -EFAULT; - } - - /* allocate rings description */ - sbuf->rings = kcalloc(bufnum, sizeof(struct sbuf_ring), GFP_KERNEL); - if (!sbuf->rings) { - smem_free(dst, sbuf->smem_addr_debug, sbuf->smem_size); - shmem_ram_unmap(dst, sbuf->smem_virt); - return -ENOMEM; - } - pr_info("%s: channel %d-%d, ringns = 0x%p!\n", - __func__, sbuf->dst, sbuf->channel, sbuf->rings); - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(sipc->sipc_pms, sipc->dst, -1); - if (rval < 0) { - smem_free(dst, sbuf->smem_addr, sbuf->smem_size); - shmem_ram_unmap(dst, sbuf->smem_virt); - kfree(sbuf->rings); - return rval; - } - - /* initialize all ring bufs */ - smem = (VOLA_SBUF_SMEM *)sbuf->smem_virt; - for (i = 0; i < bufnum; i++) { - ringhd = (VOLA_SBUF_RING *)&smem->headers[i]; - ring = &sbuf->rings[i]; - ring->header = ringhd; - /* host txbuf_addr */ - ring->rxbuf_virt = sbuf->smem_virt + hsize + - (txbufsize + rxbufsize) * i; - /* host rxbuf_addr */ - ring->txbuf_virt = ring->rxbuf_virt + rxbufsize; - /* init header op , client mode, rx <==> tx */ - hd_op = &ring->header_op; - hd_op->rx_rd_p = &ringhd->txbuf_rdptr; - hd_op->rx_wt_p = &ringhd->txbuf_wrptr; - hd_op->rx_size = ringhd->txbuf_size; - hd_op->tx_rd_p = &ringhd->rxbuf_rdptr; - hd_op->tx_wt_p = &ringhd->rxbuf_wrptr; - hd_op->tx_size = ringhd->rxbuf_size; - } - - /* release resource */ - sipc_smem_release_resource(sipc->sipc_pms, sipc->dst); - - sbuf_comm_init(sbuf); - - return 0; -} - -static int sbuf_thread(void *data) -{ - struct sbuf_mgr *sbuf = data; - struct sbuf_ring *ring; - struct smsg mcmd, mrecv; - int rval, bufid; - struct smsg_ipc *sipc; - unsigned long flags; - - /* since the channel open may hang, we call it in the sbuf thread */ - rval = smsg_ch_open(sbuf->dst, sbuf->channel, -1); - if (rval != 0) { - pr_err("Failed to open channel %d\n", sbuf->channel); - /* assign NULL to thread poniter as failed to open channel */ - sbuf->thread = NULL; - return rval; - } - - /* if client, send SMSG_CMD_SBUF_INIT, wait sbuf SMSG_DONE_SBUF_INIT */ - sipc = smsg_ipcs[sbuf->dst]; - if (sipc->client) { - smsg_set(&mcmd, sbuf->channel, SMSG_TYPE_CMD, - SMSG_CMD_SBUF_INIT, 0); - smsg_send(sbuf->dst, &mcmd, -1); - do { - smsg_set(&mrecv, sbuf->channel, 0, 0, 0); - rval = smsg_recv(sbuf->dst, &mrecv, -1); - if (rval != 0) { - sbuf->thread = NULL; - return rval; - } - } while (mrecv.type != SMSG_TYPE_DONE || - mrecv.flag != SMSG_DONE_SBUF_INIT); - sbuf->smem_addr = mrecv.value; - pr_info("%s: channel %d-%d, done_sbuf_init, address = 0x%x!\n", - __func__, sbuf->dst, sbuf->channel, sbuf->smem_addr); - if (sbuf_client_init(sipc, sbuf)) { - sbuf->thread = NULL; - return 0; - } - sbuf->state = SBUF_STATE_READY; - } - - /* sbuf init done, handle the ring rx events */ - while (!kthread_should_stop()) { - /* monitor sbuf rdptr/wrptr update smsg */ - smsg_set(&mrecv, sbuf->channel, 0, 0, 0); - rval = smsg_recv(sbuf->dst, &mrecv, -1); - if (rval == -EIO) { - /* channel state is free */ - msleep(20); - continue; - } - - pr_debug("sbuf thread recv msg: dst=%d, channel=%d, type=%d, flag=0x%04x, value=0x%08x\n", - sbuf->dst, - sbuf->channel, - mrecv.type, - mrecv.flag, - mrecv.value); - - switch (mrecv.type) { - case SMSG_TYPE_OPEN: - pr_info("%s: channel %d-%d, state=%d, recv open msg!\n", - __func__, sbuf->dst, - sbuf->channel, sbuf->state); - if (sipc->client) - break; - - /* if channel state is already reay, reopen it - * (such as modem reset), we must skip the old - * buf data , than give open ack and reset state - * to idle - */ - if (sbuf->state == SBUF_STATE_READY) { - sbuf_skip_old_data(sbuf); - sbuf->state = SBUF_STATE_IDLE; - } - /* handle channel open */ - smsg_open_ack(sbuf->dst, sbuf->channel); - break; - case SMSG_TYPE_CLOSE: - /* handle channel close */ - sbuf_skip_old_data(sbuf); - smsg_close_ack(sbuf->dst, sbuf->channel); - sbuf->state = SBUF_STATE_IDLE; - break; - case SMSG_TYPE_CMD: - pr_info("%s: channel %d-%d state = %d, recv cmd msg, flag = %d!\n", - __func__, sbuf->dst, sbuf->channel, - sbuf->state, mrecv.flag); - if (sipc->client) - break; - - /* respond cmd done for sbuf init only state is idle */ - if (sbuf->state == SBUF_STATE_IDLE && - mrecv.flag == SMSG_CMD_SBUF_INIT) { - smsg_set(&mcmd, - sbuf->channel, - SMSG_TYPE_DONE, - SMSG_DONE_SBUF_INIT, - sbuf->dst_smem_addr); - smsg_send(sbuf->dst, &mcmd, -1); - sbuf->state = SBUF_STATE_READY; - for (bufid = 0; bufid < sbuf->ringnr; bufid++) { - ring = &sbuf->rings[bufid]; - if (ring->handler) - ring->handler(SBUF_NOTIFY_READY, - ring->data); - } - } - break; - case SMSG_TYPE_EVENT: - bufid = mrecv.value; - WARN_ON(bufid >= sbuf->ringnr); - ring = &sbuf->rings[bufid]; - switch (mrecv.flag) { - case SMSG_EVENT_SBUF_RDPTR: - if (ring->need_wake_lock) - sprd_pms_request_wakelock_period(ring->tx_pms, - 500); - /* set write mask. */ - spin_lock_irqsave(&ring->poll_lock, flags); - ring->poll_mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - wake_up_interruptible_all(&ring->txwait); - if (ring->handler) - ring->handler(SBUF_NOTIFY_WRITE, - ring->data); - break; - case SMSG_EVENT_SBUF_WRPTR: - /* set read mask. */ - spin_lock_irqsave(&ring->poll_lock, flags); - ring->poll_mask |= POLLIN | POLLRDNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - if (ring->need_wake_lock) - sprd_pms_request_wakelock_period(ring->rx_pms, - 500); - wake_up_interruptible_all(&ring->rxwait); - if (ring->handler) - ring->handler(SBUF_NOTIFY_READ, - ring->data); - break; - default: - rval = 1; - break; - } - break; - default: - rval = 1; - break; - }; - - if (rval) { - pr_info("non-handled sbuf msg: %d-%d, %d, %d, %d\n", - sbuf->dst, - sbuf->channel, - mrecv.type, - mrecv.flag, - mrecv.value); - rval = 0; - } - /* unlock sipc channel wake lock */ - smsg_ch_wake_unlock(sbuf->dst, sbuf->channel); - } - - return 0; -} - - -int sbuf_create(u8 dst, u8 channel, u32 bufnum, u32 txbufsize, u32 rxbufsize) -{ - struct sbuf_mgr *sbuf; - u8 ch_index; - int ret; - struct smsg_ipc *sipc = NULL; - struct sched_param param = {.sched_priority = 10}; - - sipc = smsg_ipcs[dst]; - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - pr_debug("%s dst=%d, chanel=%d, bufnum=%d, txbufsize=0x%x, rxbufsize=0x%x\n", - __func__, - dst, - channel, - bufnum, - txbufsize, - rxbufsize); - - if (dst >= SIPC_ID_NR || !sipc) { - pr_err("%s: dst = %d is invalid\n", __func__, dst); - return -EINVAL; - } - - sbuf = kzalloc(sizeof(*sbuf), GFP_KERNEL); - if (!sbuf) - return -ENOMEM; - - sbuf->state = SBUF_STATE_IDLE; - sbuf->dst = dst; - sbuf->channel = channel; - - /* The dst smem type is pcie, need force send smsg in sbuf_write. */ - if (sipc->type == SIPC_BASE_PCIE && sipc->smem_type == SMEM_LOCAL) - sbuf->force_send = true; - - if (!sipc->client) { - ret = sbuf_host_init(sipc, sbuf, bufnum, txbufsize, rxbufsize); - if (ret) { - kfree(sbuf); - return ret; - } - } - - sbuf->thread = kthread_create(sbuf_thread, sbuf, - "sbuf-%d-%d", dst, channel); - if (IS_ERR(sbuf->thread)) { - pr_err("Failed to create kthread: sbuf-%d-%d\n", dst, channel); - if (!sipc->client) { - kfree(sbuf->rings); - shmem_ram_unmap(dst, sbuf->smem_virt); - smem_free(dst, sbuf->smem_addr, sbuf->smem_size); - } - ret = PTR_ERR(sbuf->thread); - kfree(sbuf); - return ret; - } - - sbufs[dst][ch_index] = sbuf; - - /*set the thread as a real time thread, and its priority is 10*/ - sched_setscheduler(sbuf->thread, SCHED_FIFO, ¶m); - wake_up_process(sbuf->thread); - - return 0; -} -EXPORT_SYMBOL_GPL(sbuf_create); - -void sbuf_set_no_need_wake_lock(u8 dst, u8 channel, u32 bufnum) -{ - u8 ch_index; - struct sbuf_mgr *sbuf; - struct sbuf_ring *ring = NULL; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return; - } - - sbuf = sbufs[dst][ch_index]; - if (!sbuf || sbuf->ringnr <= bufnum) - return; - - ring = &sbuf->rings[bufnum]; - ring->need_wake_lock = false; -} -EXPORT_SYMBOL_GPL(sbuf_set_no_need_wake_lock); - - -void sbuf_down(u8 dst, u8 channel) -{ - struct sbuf_mgr *sbuf; - u8 ch_index; - int i; - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return; - } - - sbuf = sbufs[dst][ch_index]; - if (!sbuf) - return; - sbuf->state = SBUF_STATE_IDLE; - if (sbuf->rings) { - for (i = 0; i < sbuf->ringnr; i++) { - wake_up_interruptible_all(&sbuf->rings[i].txwait); - wake_up_interruptible_all(&sbuf->rings[i].rxwait); - } - } - pr_info("%s: channel=%d sbuf down success\n", __func__, channel); -} - -void sbuf_destroy(u8 dst, u8 channel) -{ - struct sbuf_mgr *sbuf; - int i; - u8 ch_index; - struct smsg_ipc *sipc; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return; - } - - sbuf = sbufs[dst][ch_index]; - if (!sbuf) - return; - - sbuf->state = SBUF_STATE_IDLE; - smsg_ch_close(dst, channel, -1); - - /* stop sbuf thread if it's created successfully and still alive */ - if (!IS_ERR_OR_NULL(sbuf->thread)) - kthread_stop(sbuf->thread); - - if (sbuf->rings) { - for (i = 0; i < sbuf->ringnr; i++) { - wake_up_interruptible_all(&sbuf->rings[i].txwait); - wake_up_interruptible_all(&sbuf->rings[i].rxwait); -#if defined(SIPC_DEBUG_SBUF_RDWT_OWNER) - sbuf_destroy_rdwt_owner(&sbuf->rings[i]); -#endif - sprd_pms_destroy(sbuf->rings[i].tx_pms); - sprd_pms_destroy(sbuf->rings[i].rx_pms); - } - kfree(sbuf->rings); - } - - if (sbuf->smem_virt) - shmem_ram_unmap(dst, sbuf->smem_virt); - - sipc = smsg_ipcs[dst]; - if (sipc->client) - smem_free(dst, sbuf->smem_addr_debug, sbuf->smem_size); - else - smem_free(dst, sbuf->smem_addr, sbuf->smem_size); - - kfree(sbuf); - - sbufs[dst][ch_index] = NULL; -} -EXPORT_SYMBOL_GPL(sbuf_destroy); - -int sbuf_write(u8 dst, u8 channel, u32 bufid, - void *buf, u32 len, int timeout) -{ - struct sbuf_mgr *sbuf; - struct sbuf_ring *ring = NULL; - struct sbuf_ring_header_op *hd_op; - struct smsg mevt; - void *txpos; - int rval, left, tail, txsize; - u8 ch_index; - union sbuf_buf u_buf; - bool no_data; - unsigned long flags; - u32 v; - - u_buf.buf = buf; - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sbuf = sbufs[dst][ch_index]; - if (!sbuf) - return -ENODEV; - ring = &sbuf->rings[bufid]; - hd_op = &ring->header_op; - if (sbuf->state != SBUF_STATE_READY) { - pr_info("sbuf-%d-%d not ready to write!\n", - dst, channel); - return -ENODEV; - } - - pr_debug("%s: dst=%d, channel=%d, bufid=%d, len=%d, timeout=%d\n", - __func__, - dst, - channel, - bufid, - len, - timeout); - - rval = 0; - left = len; - - if (timeout) { - mutex_lock_interruptible(&ring->txlock); - } else { - if (!mutex_trylock(&ring->txlock)) { - pr_debug("sbuf_read busy, dst=%d, channel=%d, bufid=%d\n", - dst, channel, bufid); - return -EBUSY; - } - } - -#if defined(SIPC_DEBUG_SBUF_RDWT_OWNER) - sbuf_record_rdwt_owner(ring, 0); -#endif - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->tx_pms, sbuf->dst, -1); - if (rval < 0) { - mutex_unlock(&ring->txlock); - return rval; - } - - pr_debug("%s: channel=%d, wrptr=%d, rdptr=%d\n", - __func__, - channel, - BL_READL(hd_op->tx_wt_p), - BL_READL(hd_op->tx_rd_p)); - no_data = ((int)(BL_READL(hd_op->tx_wt_p) - BL_READL(hd_op->tx_rd_p)) >= - hd_op->tx_size); - - /* update write mask */ - spin_lock_irqsave(&ring->poll_lock, flags); - if (no_data) - ring->poll_mask &= ~(POLLOUT | POLLWRNORM); - else - ring->poll_mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - /* release resource */ - sipc_smem_release_resource(ring->tx_pms, sbuf->dst); - - if (no_data) { - if (timeout == 0) { - pr_info("%s: %d-%d ring %d txbuf is full!\n", - __func__, dst, channel, bufid); - rval = -EBUSY; - } else if (timeout < 0) { - /* wait forever */ - rval = wait_event_interruptible( - ring->txwait, - sbuf_has_data(ring, dst, true) || - sbuf->state == SBUF_STATE_IDLE); - if (rval < 0) - pr_debug("%s: wait interrupted!\n", __func__); - - if (sbuf->state == SBUF_STATE_IDLE) { - pr_err("%s: sbuf state is idle!\n", __func__); - rval = -EIO; - } - } else { - /* wait timeout */ - rval = wait_event_interruptible_timeout( - ring->txwait, - sbuf_has_data(ring, dst, true) || - sbuf->state == SBUF_STATE_IDLE, - timeout); - if (rval < 0) { - pr_debug("%s: wait interrupted!\n", __func__); - } else if (rval == 0) { - pr_info("%s: wait timeout!\n", __func__); - rval = -ETIME; - } - - if (sbuf->state == SBUF_STATE_IDLE) { - pr_err("%s: sbuf state is idle!\n", __func__); - rval = -EIO; - } - } - } - - if (rval < 0) { - mutex_unlock(&ring->txlock); - return rval; - } - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->tx_pms, sbuf->dst, -1); - if (rval < 0) { - mutex_unlock(&ring->txlock); - return rval; - } - - while (left && (int)(BL_READL(hd_op->tx_wt_p) - BL_READL(hd_op->tx_rd_p)) < - hd_op->tx_size && sbuf->state == SBUF_STATE_READY) { - /* calc txpos & txsize */ - txpos = ring->txbuf_virt + - BL_READL(hd_op->tx_wt_p) % hd_op->tx_size; - txsize = hd_op->tx_size - - (int)(BL_READL(hd_op->tx_wt_p) - BL_READL(hd_op->tx_rd_p)); - txsize = min(txsize, left); - - tail = txpos + txsize - (ring->txbuf_virt + hd_op->tx_size); - if (tail > 0) { - /* ring buffer is rounded */ - if ((uintptr_t)u_buf.buf > TASK_SIZE) { - unalign_memcpy(txpos, u_buf.buf, txsize - tail); - unalign_memcpy(ring->txbuf_virt, - u_buf.buf + txsize - tail, tail); - } else { - if (unalign_copy_from_user( - txpos, - u_buf.ubuf, - txsize - tail) || - unalign_copy_from_user( - ring->txbuf_virt, - u_buf.ubuf + txsize - tail, - tail)) { - pr_err("%s:failed to copy from user!\n", - __func__); - rval = -EFAULT; - break; - } - } - } else { - if ((uintptr_t)u_buf.buf > TASK_SIZE) { - unalign_memcpy(txpos, u_buf.buf, txsize); - } else { - /* handle the user space address */ - if (unalign_copy_from_user( - txpos, - u_buf.ubuf, - txsize)) { - pr_err("%s:failed to copy from user!\n", - __func__); - rval = -EFAULT; - break; - } - } - } - - pr_debug("%s: channel=%d, txpos=%p, txsize=%d\n", - __func__, channel, txpos, txsize); - - /* update tx wrptr */ - v = BL_READL(hd_op->tx_wt_p) + txsize; - BL_WRITEL(v, hd_op->tx_wt_p); - /* - * force send be true or tx ringbuf is empty, - * need to notify peer side - */ - if (sbuf->force_send || - BL_READL(hd_op->tx_wt_p) - BL_READL(hd_op->tx_rd_p) == txsize) { - smsg_set(&mevt, channel, - SMSG_TYPE_EVENT, - SMSG_EVENT_SBUF_WRPTR, - bufid); - smsg_send(dst, &mevt, -1); - } - - left -= txsize; - u_buf.buf += txsize; - } - - /* update write mask */ - spin_lock_irqsave(&ring->poll_lock, flags); - if ((int)(BL_READL(hd_op->tx_wt_p) - BL_READL(hd_op->tx_rd_p)) >= - hd_op->tx_size) - ring->poll_mask &= ~(POLLOUT | POLLWRNORM); - else - ring->poll_mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - /* release resource */ - sipc_smem_release_resource(ring->tx_pms, sbuf->dst); - if (ring->need_wake_lock) - sprd_pms_release_wakelock_later(ring->tx_pms, 20); - - mutex_unlock(&ring->txlock); - - pr_debug("%s: done, channel=%d, len=%d\n", - __func__, channel, len - left); - - if (len == left) - return rval; - else - return (len - left); -} -EXPORT_SYMBOL_GPL(sbuf_write); - -int sbuf_read(u8 dst, u8 channel, u32 bufid, - void *buf, u32 len, int timeout) -{ - struct sbuf_mgr *sbuf; - struct sbuf_ring *ring = NULL; - struct sbuf_ring_header_op *hd_op; - struct smsg mevt; - void *rxpos; - int rval, left, tail, rxsize; - u8 ch_index; - union sbuf_buf u_buf; - bool no_data; - unsigned long flags; - u32 v; - - u_buf.buf = buf; - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - sbuf = sbufs[dst][ch_index]; - if (!sbuf) - return -ENODEV; - ring = &sbuf->rings[bufid]; - hd_op = &ring->header_op; - - if (sbuf->state != SBUF_STATE_READY) { - pr_debug("sbuf-%d-%d not ready to read!\n", dst, channel); - return -ENODEV; - } - - pr_debug("%s:dst=%d, channel=%d, bufid=%d, len=%d, timeout=%d\n", - __func__, dst, channel, bufid, len, timeout); - - rval = 0; - left = len; - - if (timeout) { - mutex_lock_interruptible(&ring->rxlock); - } else { - if (!mutex_trylock(&ring->rxlock)) { - pr_debug("%s: busy!,dst=%d, channel=%d, bufid=%d\n", - __func__, dst, channel, bufid); - return -EBUSY; - } - } - -#if defined(SIPC_DEBUG_SBUF_RDWT_OWNER) - sbuf_record_rdwt_owner(ring, 1); -#endif - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->rx_pms, sbuf->dst, -1); - if (rval < 0) { - mutex_unlock(&ring->rxlock); - return rval; - } - - pr_debug("%s: channel=%d, wrptr=%d, rdptr=%d\n", - __func__, - channel, - BL_READL(hd_op->rx_wt_p), - BL_READL(hd_op->rx_rd_p)); - no_data = (BL_READL(hd_op->rx_wt_p) == BL_READL(hd_op->rx_rd_p)); - /* update read mask */ - spin_lock_irqsave(&ring->poll_lock, flags); - if (no_data) - ring->poll_mask &= ~(POLLIN | POLLRDNORM); - else - ring->poll_mask |= POLLIN | POLLRDNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - /* release resource */ - sipc_smem_release_resource(ring->rx_pms, sbuf->dst); - - if (no_data) { - if (timeout == 0) { - /* no wait */ - pr_debug("%s: %d-%d ring %d rxbuf is empty!\n", - __func__, dst, channel, bufid); - rval = -ENODATA; - } else if (timeout < 0) { - /* wait forever */ - rval = wait_event_interruptible( - ring->rxwait, - sbuf_has_data(ring, dst, false) || - sbuf->state == SBUF_STATE_IDLE); - if (rval < 0) - pr_debug("%s: wait interrupted!\n", __func__); - - if (sbuf->state == SBUF_STATE_IDLE) { - pr_err("%s: sbuf state is idle!\n", __func__); - rval = -EIO; - } - } else { - /* wait timeout */ - rval = wait_event_interruptible_timeout( - ring->rxwait, - sbuf_has_data(ring, dst, false) || - sbuf->state == SBUF_STATE_IDLE, timeout); - if (rval < 0) { - pr_debug("%s: wait interrupted!\n", __func__); - } else if (rval == 0) { - pr_info("%s: wait timeout!\n", __func__); - rval = -ETIME; - } - - if (sbuf->state == SBUF_STATE_IDLE) { - pr_err("%s: state is idle!\n", __func__); - rval = -EIO; - } - } - } - - if (rval < 0) { - mutex_unlock(&ring->rxlock); - return rval; - } - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->rx_pms, sbuf->dst, -1); - if (rval < 0) { - mutex_unlock(&ring->rxlock); - return rval; - } - - while (left && - (BL_READL(hd_op->rx_wt_p) != BL_READL(hd_op->rx_rd_p)) && - sbuf->state == SBUF_STATE_READY) { - /* calc rxpos & rxsize */ - rxpos = ring->rxbuf_virt + - BL_READL(hd_op->rx_rd_p) % hd_op->rx_size; - rxsize = (int)(BL_READL(hd_op->rx_wt_p) - BL_READL(hd_op->rx_rd_p)); - /* check overrun */ - if (rxsize > hd_op->rx_size) - pr_err("%s: bufid = %d, channel= %d rxsize=0x%x, rdptr=%d, wrptr=%d", - __func__, - bufid, - channel, - rxsize, - BL_READL(hd_op->rx_wt_p), - BL_READL(hd_op->rx_rd_p)); - - rxsize = min(rxsize, left); - - pr_debug("%s: channel=%d, buf=%p, rxpos=%p, rxsize=%d\n", - __func__, channel, u_buf.buf, rxpos, rxsize); - - tail = rxpos + rxsize - (ring->rxbuf_virt + hd_op->rx_size); - - if (tail > 0) { - /* ring buffer is rounded */ - if ((uintptr_t)u_buf.buf > TASK_SIZE) { - unalign_memcpy(u_buf.buf, rxpos, rxsize - tail); - unalign_memcpy(u_buf.buf + rxsize - tail, - ring->rxbuf_virt, tail); - } else { - /* handle the user space address */ - if (unalign_copy_to_user(u_buf.ubuf, - rxpos, - rxsize - tail) || - unalign_copy_to_user(u_buf.ubuf - + rxsize - tail, - ring->rxbuf_virt, - tail)) { - pr_err("%s: failed to copy to user!\n", - __func__); - rval = -EFAULT; - break; - } - } - } else { - if ((uintptr_t)u_buf.buf > TASK_SIZE) { - unalign_memcpy(u_buf.buf, rxpos, rxsize); - } else { - /* handle the user space address */ - if (unalign_copy_to_user(u_buf.ubuf, - rxpos, rxsize)) { - pr_err("%s: failed to copy to user!\n", - __func__); - rval = -EFAULT; - break; - } - } - } - - /* update rx rdptr */ - v = BL_READL(hd_op->rx_rd_p) + rxsize; - BL_WRITEL(v, hd_op->rx_rd_p); - /* rx ringbuf is full ,so need to notify peer side */ - if (BL_READL(hd_op->rx_wt_p) - BL_READL(hd_op->rx_rd_p) == - hd_op->rx_size - rxsize) { - smsg_set(&mevt, channel, - SMSG_TYPE_EVENT, - SMSG_EVENT_SBUF_RDPTR, - bufid); - smsg_send(dst, &mevt, -1); - } - - left -= rxsize; - u_buf.buf += rxsize; - } - - /* update read mask */ - spin_lock_irqsave(&ring->poll_lock, flags); - if (BL_READL(hd_op->rx_wt_p) == BL_READL(hd_op->rx_rd_p)) - ring->poll_mask &= ~(POLLIN | POLLRDNORM); - else - ring->poll_mask |= POLLIN | POLLRDNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - /* release resource */ - sipc_smem_release_resource(ring->rx_pms, sbuf->dst); - if (ring->need_wake_lock) - sprd_pms_release_wakelock_later(ring->rx_pms, 20); - - mutex_unlock(&ring->rxlock); - - pr_debug("%s: done, channel=%d, len=%d", __func__, channel, len - left); - - if (len == left) - return rval; - else - return (len - left); -} -EXPORT_SYMBOL_GPL(sbuf_read); - -int sbuf_poll_wait(u8 dst, u8 channel, u32 bufid, - struct file *filp, poll_table *wait) -{ - struct sbuf_mgr *sbuf; - struct sbuf_ring *ring = NULL; - struct sbuf_ring_header_op *hd_op; - unsigned int mask = 0; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return mask; - } - sbuf = sbufs[dst][ch_index]; - if (!sbuf) - return mask; - ring = &sbuf->rings[bufid]; - hd_op = &ring->header_op; - if (sbuf->state != SBUF_STATE_READY) { - pr_err("sbuf-%d-%d not ready to poll !\n", dst, channel); - return mask; - } - - poll_wait(filp, &ring->txwait, wait); - poll_wait(filp, &ring->rxwait, wait); - - - if (sbuf_has_data(ring, dst, true)) - mask |= POLLOUT | POLLWRNORM; - - if (sbuf_has_data(ring, dst, false)) - mask |= POLLIN | POLLRDNORM; - - return mask; -} -EXPORT_SYMBOL_GPL(sbuf_poll_wait); - -int sbuf_status(u8 dst, u8 channel) -{ - struct sbuf_mgr *sbuf; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - sbuf = sbufs[dst][ch_index]; - - if (!sbuf) - return -ENODEV; - if (sbuf->state != SBUF_STATE_READY) - return -ENODEV; - - return 0; -} -EXPORT_SYMBOL_GPL(sbuf_status); - -int sbuf_register_notifier(u8 dst, u8 channel, u32 bufid, - void (*handler)(int event, void *data), void *data) -{ - struct sbuf_mgr *sbuf; - struct sbuf_ring *ring = NULL; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - sbuf = sbufs[dst][ch_index]; - if (!sbuf) - return -ENODEV; - ring = &sbuf->rings[bufid]; - ring->handler = handler; - ring->data = data; - - if (sbuf->state == SBUF_STATE_READY) - handler(SBUF_NOTIFY_READ, data); - - return 0; -} -EXPORT_SYMBOL_GPL(sbuf_register_notifier); - -void sbuf_get_status(u8 dst, char *status_info, int size) -{ - struct sbuf_mgr *sbuf = NULL; - struct sbuf_ring *ring = NULL; - struct sbuf_ring_header_op *hd_op; - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 4,10,0 )) - wait_queue_t *pos; -#else - wait_queue_entry_t *pos; -#endif - struct task_struct *task; - unsigned long flags; - int i, n, len, cnt; - u32 b_select; - char *phead; -#if defined(SIPC_DEBUG_SBUF_RDWT_OWNER) - struct name_node *node = NULL; -#endif - - len = strlen(status_info); - if (!status_info || size < 0 || dst >= SIPC_ID_NR) - return; - - for (i = 0; i < SMSG_VALID_CH_NR; i++) { - sbuf = sbufs[dst][i]; - if (!sbuf) - continue; - - ring = &sbuf->rings[0]; - /* must request resource before read or write share memory */ - if (sipc_smem_request_resource(ring->rx_pms, dst, 1000) < 0) - continue; - - for (n = 0; n < sbuf->ringnr && len < size; n++) { - ring = &sbuf->rings[n]; - hd_op = &ring->header_op; - - if ((BL_READL(hd_op->rx_wt_p) - BL_READL(hd_op->rx_rd_p)) - < hd_op->rx_size) - continue; - - snprintf(status_info + len, - size - len, - "ch-%d-ring-%d is full.\n", - sbuf->channel, - n); - len = strlen(status_info); - - /* show all rxwait task */ - spin_lock_irqsave(&ring->rxwait.lock, flags); - cnt = 0; - - list_for_each_entry(pos, -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 4,10,0 )) - &ring->rxwait.task_list, - task_list -#else - &ring->rxwait.head, - entry -#endif - ) { - task = sbuf_wait_get_task(pos, &b_select); - if (!task) - continue; - - if (b_select) - phead = "rxwait task"; - else - phead = "select task"; - - snprintf( - status_info + len, - size - len, - "%s %d: %s, state=0x%lx, pid=%d.\n", - phead, - cnt, task->comm, - task->state, task->pid); - cnt++; - len = strlen(status_info); - } - spin_unlock_irqrestore(&ring->rxwait.lock, flags); - - /* only show the latest ever read task */ -#if defined(SIPC_DEBUG_SBUF_RDWT_OWNER) - spin_lock_irqsave(&ring->rxwait.lock, flags); - list_for_each_entry(node, &ring->rx_list, list) { - if (node->latest) { - snprintf( - status_info + len, - size - len, - "read task: %s, pid = %d.\n", - node->comm, - node->pid); - break; - } - } - spin_unlock_irqrestore(&ring->rxwait.lock, flags); -#endif - } - ring = &sbuf->rings[0]; - /* release resource */ - sipc_smem_release_resource(ring->rx_pms, sbuf->dst); - } -} -EXPORT_SYMBOL_GPL(sbuf_get_status); - -#if defined(CONFIG_DEBUG_FS) -static void sbuf_debug_task_show(struct seq_file *m, - struct sbuf_mgr *sbuf, int task_type) -{ - int n, cnt; - u32 b_select; - unsigned long flags; - struct sbuf_ring *ring = NULL; - wait_queue_head_t *phead; - char *buf; -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 4,10,0 )) - wait_queue_t *pos; -#else - wait_queue_entry_t *pos; -#endif - struct task_struct *task; - - for (n = 0; n < sbuf->ringnr; n++) { - ring = &sbuf->rings[n]; - cnt = 0; - - if (task_type == TASK_RXWAIT) { - phead = &ring->rxwait; - buf = "rxwait task"; - } else if (task_type == TASK_TXWAIT) { - phead = &ring->txwait; - buf = "txwait task"; - } else { - phead = &ring->rxwait; - buf = "select task"; - } - - spin_lock_irqsave(&phead->lock, flags); - - list_for_each_entry(pos, -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 4,10,0 )) - &phead->task_list, task_list -#else - &phead->head, entry -#endif - ){ - task = sbuf_wait_get_task(pos, &b_select); - if (!task) - continue; - - if (b_select && (task_type != TASK_SELECT)) - continue; - - seq_printf(m, " ring[%2d]: %s %d ", - n, - buf, - cnt); - seq_printf(m, ": %s, state = 0x%lx, pid = %d\n", - task->comm, - task->state, - task->pid); - cnt++; - } - spin_unlock_irqrestore( - &phead->lock, - flags); - } -} - -#if defined(SIPC_DEBUG_SBUF_RDWT_OWNER) -static void sbuf_debug_list_show(struct seq_file *m, - struct sbuf_mgr *sbuf, int b_rx) -{ - int n, cnt; - struct sbuf_ring *ring = NULL; - struct list_head *plist; - char *buf; - struct name_node *node = NULL; - unsigned long flags; - - /* list all sbuf task list */ - for (n = 0; n < sbuf->ringnr; n++) { - ring = &sbuf->rings[n]; - cnt = 0; - - if (b_rx) { - plist = &ring->rx_list; - buf = "read task"; - } else { - plist = &ring->tx_list; - buf = "write task"; - } - - spin_lock_irqsave(&ring->rxwait.lock, flags); - list_for_each_entry(node, plist, list) { - seq_printf(m, " ring[%2d]: %s %d : %s, pid = %d, latest = %d\n", - n, - buf, - cnt, - node->comm, - node->pid, - node->latest); - cnt++; - } - spin_unlock_irqrestore(&ring->rxwait.lock, flags); - } -} -#endif - -static int sbuf_debug_show(struct seq_file *m, void *private) -{ - struct sbuf_mgr *sbuf = NULL; - struct sbuf_ring *ring = NULL; - struct sbuf_ring_header_op *hd_op; - int i, j, n, cnt; - struct smsg_ipc *sipc = NULL; - - for (i = 0; i < SIPC_ID_NR; i++) { - sipc = smsg_ipcs[i]; - if (!sipc) - continue; - - /* must request resource before read or write share memory */ - if (sipc_smem_request_resource(sipc->sipc_pms, - sipc->dst, 1000) < 0) - continue; - - sipc_debug_putline(m, '*', 120); - seq_printf(m, "dst: 0x%0x, sipc: %s:\n", i, sipc->name); - sipc_debug_putline(m, '*', 120); - - for (j = 0; j < SMSG_VALID_CH_NR; j++) { - sbuf = sbufs[i][j]; - if (!sbuf) - continue; - /* list a sbuf channel */ - sipc_debug_putline(m, '-', 100); - seq_printf(m, "sbuf_%d_%03d, state: %d, force: %d", - sbuf->dst, - sbuf->channel, - sbuf->state, - sbuf->force_send); - seq_printf(m, "virt: 0x%lx, phy: 0x%0x, map: 0x%x", - (unsigned long)sbuf->smem_virt, - sbuf->smem_addr, - sbuf->dst_smem_addr); - seq_printf(m, " size: 0x%0x, ringnr: %d\n", - sbuf->smem_size, - sbuf->ringnr); - sipc_debug_putline(m, '-', 100); - - /* list all sbuf ring info list in a chanel */ - sipc_debug_putline(m, '-', 80); - seq_puts(m, " 1. all sbuf ring info list:\n"); - for (n = 0; n < sbuf->ringnr; n++) { - ring = &sbuf->rings[n]; - hd_op = &ring->header_op; - if (BL_READL(hd_op->tx_wt_p) == 0 && - BL_READL(hd_op->rx_wt_p) == 0) - continue; - - seq_printf(m, " rx ring[%2d]: addr: 0x%0x, mask: 0x%x", - n, ring->header->rxbuf_addr, - ring->poll_mask); - seq_printf(m, "rp: 0x%0x, wp: 0x%0x, size: 0x%0x\n", - BL_READL(hd_op->rx_rd_p), - BL_READL(hd_op->rx_wt_p), - hd_op->rx_size); - - seq_printf(m, " tx ring[%2d]: addr: 0x%0x, ", - n, ring->header->txbuf_addr); - seq_printf(m, "rp: 0x%0x, wp: 0x%0x, size: 0x%0x\n", - BL_READL(hd_op->tx_rd_p), - BL_READL(hd_op->tx_wt_p), - hd_op->tx_size); - } - - /* list all sbuf rxwait/txwait in a chanel */; - sipc_debug_putline(m, '-', 80); - seq_puts(m, " 2. all waittask list:\n"); - sbuf_debug_task_show(m, sbuf, TASK_RXWAIT); - sbuf_debug_task_show(m, sbuf, TASK_TXWAIT); - sbuf_debug_task_show(m, sbuf, TASK_SELECT); - -#ifdef SIPC_DEBUG_SBUF_RDWT_OWNER - /* list all sbuf ever read task list in a chanel */; - sipc_debug_putline(m, '-', 80); - seq_puts(m, " 3. all ever rdwt list:\n"); - sbuf_debug_list_show(m, sbuf, 1); - sbuf_debug_list_show(m, sbuf, 0); -#endif - - /* list all rx full ring list in a chanel */ - cnt = 0; - for (n = 0; n < sbuf->ringnr; n++) { - ring = &sbuf->rings[n]; - hd_op = &ring->header_op; - if ((BL_READL(hd_op->rx_wt_p) - BL_READL(hd_op->rx_rd_p)) - == hd_op->rx_size) { - if (cnt == 0) { - sipc_debug_putline(m, '-', 80); - seq_puts(m, " x. all rx full ring list:\n"); - } - cnt++; - seq_printf(m, " ring[%2d]\n", n); - } - } - } - /* release resource */ - sipc_smem_release_resource(sipc->sipc_pms, sipc->dst); - } - - return 0; -} - -static int sbuf_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, sbuf_debug_show, inode->i_private); -} - -static const struct file_operations sbuf_debug_fops = { - .open = sbuf_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -int sbuf_init_debugfs(void *root) -{ - if (!root) - return -ENXIO; - debugfs_create_file("sbuf", 0444, - (struct dentry *)root, - NULL, &sbuf_debug_fops); - return 0; -} -EXPORT_SYMBOL_GPL(sbuf_init_debugfs); - -#endif /* CONFIG_DEBUG_FS */ - -MODULE_AUTHOR("Chen Gaopeng"); -MODULE_DESCRIPTION("SIPC/SBUF driver"); -MODULE_LICENSE("GPL v2"); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sbuf.h b/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sbuf.h deleted file mode 100644 index 80104f0a6..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sbuf.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#ifndef __SBUF_H -#define __SBUF_H - -/* flag for CMD/DONE msg type */ -#define SMSG_CMD_SBUF_INIT 0x0001 -#define SMSG_DONE_SBUF_INIT 0x0002 - -/* flag for EVENT msg type */ -#define SMSG_EVENT_SBUF_WRPTR 0x0001 -#define SMSG_EVENT_SBUF_RDPTR 0x0002 - -#if defined(CONFIG_DEBUG_FS) -#define SIPC_DEBUG_SBUF_RDWT_OWNER -#define MAX_RECORD_CNT 0x10 -#endif - -/* ring buf header */ -struct sbuf_ring_header { - /* send-buffer info */ - u32 txbuf_addr; - u32 txbuf_size; - u32 txbuf_rdptr; - u32 txbuf_wrptr; - - /* recv-buffer info */ - u32 rxbuf_addr; - u32 rxbuf_size; - u32 rxbuf_rdptr; - u32 rxbuf_wrptr; -}; - -struct sbuf_ring_header_op { - /* - * this points point to share memory - * for update rdptr and wtptr on share memory - */ - volatile u32 *rx_rd_p; - volatile u32 *rx_wt_p; - volatile u32 *tx_rd_p; - volatile u32 *tx_wt_p; - - /* - * this member copy from share memory, - * because this contents will not change on share memory - */ - u32 rx_size;/* rxbuf_size */ - u32 tx_size;/* txbuf_size */ -}; - -/* sbuf_mem is the structure of smem for rings */ -struct sbuf_smem_header { - u32 ringnr; - - struct sbuf_ring_header headers[0]; -}; - -struct sbuf_ring { - /* tx/rx buffer info */ - volatile struct sbuf_ring_header *header; - struct sbuf_ring_header_op header_op; - - void *txbuf_virt; - void *rxbuf_virt; - - /* send/recv wait queue */ - wait_queue_head_t txwait; - wait_queue_head_t rxwait; - -#if defined(SIPC_DEBUG_SBUF_RDWT_OWNER) - /* record all task histoy */ - struct list_head tx_list; - struct list_head rx_list; -#endif - - /* send/recv mutex */ - struct mutex txlock; - struct mutex rxlock; - - struct sprd_pms *tx_pms; - struct sprd_pms *rx_pms; - char tx_pms_name[20]; - char rx_pms_name[20]; - - bool need_wake_lock; - unsigned int poll_mask; - /* protect poll_mask member */ - spinlock_t poll_lock; - - void (*handler)(int event, void *data); - void *data; -}; - -#define SBUF_STATE_IDLE 0 -#define SBUF_STATE_READY 1 - -struct sbuf_mgr { - u8 dst; - u8 channel; - bool force_send; - u32 state; - - void *smem_virt; - u32 smem_addr; - u32 smem_size; - - u32 smem_addr_debug; - u32 dst_smem_addr; - u32 ringnr; - - struct sbuf_ring *rings; - struct task_struct *thread; -}; -#endif diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sipc.c b/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sipc.c deleted file mode 100644 index ee256fab8..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sipc.c +++ /dev/null @@ -1,524 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sipc.h" -#include "sipc_priv.h" - -#define MBOX_BAMK "mbox" -#define PCIE_BAMK "pcie" - -enum { - NORMAL_MODE = 0, - CHARGE_MODE, - CALI_MODE -}; - -#define CALI_LATENCY (10000 * 1000) -#define NORMAL_LATENCY (1 * 1000) - -/* - * In charge mode, will only boot pm system, - * so just create pm systen sipc. - */ -static u8 g_boot_mode = NORMAL_MODE; -/* -static int __init sipc_early_mode(char *str) -{ - if (!memcmp(str, "charger", 7)) - g_boot_mode = CHARGE_MODE; - else if (!memcmp(str, "cali", 4)) - g_boot_mode = CALI_MODE; - else - g_boot_mode = NORMAL_MODE; - - return 0; -} - -early_param("androidboot.mode", sipc_early_mode); -*/ - -#if defined(CONFIG_DEBUG_FS) -void sipc_debug_putline(struct seq_file *m, char c, int n) -{ - char buf[300]; - int i, max, len; - - /* buf will end with '\n' and 0 */ - max = ARRAY_SIZE(buf) - 2; - len = (n > max) ? max : n; - - for (i = 0; i < len; i++) - buf[i] = c; - - buf[i] = '\n'; - buf[i + 1] = 0; - - seq_puts(m, buf); -} -EXPORT_SYMBOL_GPL(sipc_debug_putline); -#endif - -static u32 sipc_rxirq_status(u8 dst) -{ - return 0; -} - -static void sipc_rxirq_clear(u8 dst) -{ - -} - -static void sipc_txirq_trigger(u8 dst, u64 msg) -{ - struct smsg_ipc *ipc; - - ipc = smsg_ipcs[dst]; - - if (ipc) { -#ifdef CONFIG_SPRD_MAILBOX - if (ipc->type == SIPC_BASE_MBOX) { - mbox_raw_sent(ipc->core_id, msg); - return; - } -#endif - - if (ipc->type == SIPC_BASE_PCIE) { -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE - sprd_ep_dev_raise_irq(ipc->ep_dev, PCIE_DBELL_SIPC_IRQ); -#endif - -#ifdef CONFIG_PCIE_EPF_SPRD - sprd_pci_epf_raise_irq(ipc->ep_fun, PCIE_MSI_SIPC_IRQ); -#endif - return; - } - } -} - -#ifdef SPRD_PCIE_USE_DTS -static int sipc_parse_dt(struct smsg_ipc *ipc, - struct device_node *np, struct device *dev) -{ - u32 val[3]; - int ret; - const char *type; - - /* get name */ - ret = of_property_read_string(np, "sprd,name", &ipc->name); - if (ret) - return ret; - - pr_info("sipc: name=%s\n", ipc->name); - - /* get sipc type, optional */ - if (of_property_read_string(np, "sprd,type", &type) == 0) { - pr_info("sipc: type=%s\n", type); - if (strcmp(MBOX_BAMK, type) == 0) - ipc->type = SIPC_BASE_MBOX; - else if (strcmp(PCIE_BAMK, type) == 0) - ipc->type = SIPC_BASE_PCIE; - } - - /* get sipc client, optional */ - if (of_property_read_u32_array(np, "sprd,client", val, 1) == 0) { - ipc->client = (u8)val[0]; - pr_info("sipc: client=%d\n", ipc->client); - } - - /* get sipc dst */ - ret = of_property_read_u32_array(np, "sprd,dst", val, 1); - if (!ret) { - ipc->dst = (u8)val[0]; - pr_info("sipc: dst =%d\n", ipc->dst); - } - - if (ret || ipc->dst >= SIPC_ID_NR) { - pr_err("sipc: dst err, ret =%d.\n", ret); - return ret; - } - -#ifdef CONFIG_SPRD_MAILBOX - if (ipc->type == SIPC_BASE_MBOX) { - /* get core id */ - ipc->core_id = (u8)MBOX_INVALID_CORE; - ret = of_property_read_u32_array(np, "sprd,core", val, 1); - if (!ret) { - ipc->core_id = (u8)val[0]; - pr_info("sipc: core=%d\n", ipc->core_id); - } else { - pr_err("sipc: core err, ret =%d.\n", ret); - return ret; - } - - /* get core sensor id, optional*/ - ipc->core_sensor_id = (u8)MBOX_INVALID_CORE; - if (of_property_read_u32_array(np, "sprd,core_sensor", - val, 1) == 0) { - ipc->core_sensor_id = (u8)val[0]; - pr_info("sipc: core_sensor=%d\n", ipc->core_sensor_id); - } - } -#endif - -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE - if (ipc->type == SIPC_BASE_PCIE) { -#ifdef CONFIG_SPRD_PCIE - struct device_node *pdev_node; -#endif - - ret = of_property_read_u32_array(np, - "sprd,ep-dev", - &ipc->ep_dev, - 1); - pr_info("sipc: ep_dev=%d\n", ipc->ep_dev); - if (ret || ipc->ep_dev >= PCIE_EP_NR) { - pr_err("sipc: ep_dev err, ret =%d.\n", ret); - return ret; - } - -#ifdef CONFIG_SPRD_PCIE - /* get pcie rc ctrl device */ - pdev_node = of_parse_phandle(np, "sprd,rc-ctrl", 0); - if (!pdev_node) { - pr_err("sipc: sprd,rc-ctrl err.\n"); - return -ENODEV; - } - ipc->pcie_dev = of_find_device_by_node(pdev_node); - of_node_put(pdev_node); - - if (!ipc->pcie_dev) { - pr_err("sipc: find pcie_dev err.\n"); - return -ENODEV; - } -#endif - } -#endif - -#ifdef CONFIG_PCIE_EPF_SPRD - if (ipc->type == SIPC_BASE_PCIE) { - ret = of_property_read_u32_array(np, - "sprd,ep-fun", - &ipc->ep_fun, - 1); - pr_info("sipc: ep_fun=%d\n", ipc->ep_fun); - if (ret || ipc->ep_fun >= SPRD_FUNCTION_MAX) { - pr_err("sipc: ep_fun err, ret =%d.\n", ret); - return ret; - } - - /* parse doolbell irq */ - ret = of_irq_get(np, 0); - if (ret < 0) { - pr_err("sipc: doorbell irq err, ret=%d\n", ret); - return -EINVAL; - } - ipc->irq = ret; - pr_info("sipc: irq=%d\n", ipc->irq); - } -#endif - - /* get smem type */ - ret = of_property_read_u32_array(np, - "sprd,smem-type", - &val[0], - 1); - if (!ret) - ipc->smem_type = (enum smem_type)val[0]; - else - ipc->smem_type = SMEM_LOCAL; - - pr_info("sipc: smem_type = %d, ret =%d\n", ipc->smem_type, ret); - - /* get smem info */ - ret = of_property_read_u32_array(np, - "sprd,smem-info", - val, - 3); - if (ret) { - pr_err("sipc: parse smem info failed.\n"); - return ret; - } - ipc->smem_base = val[0]; - ipc->dst_smem_base = val[1]; - ipc->smem_size = val[2]; - pr_info("sipc: smem_base=0x%x, dst_smem_base=0x%x, smem_size=0x%x\n", - ipc->smem_base, ipc->dst_smem_base, ipc->smem_size); - -#ifdef CONFIG_PHYS_ADDR_T_64BIT - /* try to get high_offset */ - ret = of_property_read_u32(np, - "sprd,high-offset", - val); - if (!ret) { - ipc->high_offset = val[0]; - pr_info("sipc: high_offset=0x%xn", ipc->high_offset); - } -#endif - - if (ipc->type == SIPC_BASE_PCIE) { - /* pcie sipc, the host must use loacal SMEM_LOCAL */ - if (!ipc->client && ipc->smem_type != SMEM_LOCAL) { - pr_err("sipc: host must use local smem!"); - return -EINVAL; - } - - if (ipc->client && ipc->smem_type != SMEM_PCIE) { - pr_err("sipc: client must use pcie smem!"); - return -EINVAL; - } - } - - return 0; -} -#else -static u32 sipc_get_smem_base(size_t size) -{ - unsigned long order = get_order(size); - struct page *page, *p, *e; - - page = alloc_pages(GFP_KERNEL, order); - if(page == NULL) { - printk("sipc alloc pages fail\n"); - return 0; - } - split_page(page, order); - for (p = page +(size >> PAGE_SHIFT), e = page + (1 << order); p < e; p++) - __free_page(p); - - if (PageHighMem(page)) { - phys_addr_t base = __pfn_to_phys(page_to_pfn(page)); - //phys_addr_t end = base + size; - while (size > 0) { - void *ptr = kmap_atomic(page); - memset(ptr, 0, PAGE_SIZE); - kunmap_atomic(ptr); - page++; - size -= PAGE_SIZE; - } - - return base; - } else { - void *ptr = page_address(page); - memset(ptr, 0, size); - return __pa(ptr); - } -} - -static int sipc_parse_dt(struct smsg_ipc *ipc, - struct device_node *np, struct device *dev) -{ - u32 val[3]; - int ret = 0; - //dma_addr_t *dma_handle; - - /* get name */ - ipc->name = "sprd,sipc"; - pr_info("sipc: name=%s\n", ipc->name); - - /* get sipc type, optional */ - ipc->type = SIPC_BASE_PCIE; - pr_info("sipc: type=%d\n", ipc->type); - - /* get sipc client, optional */ - - /* get sipc dst */ - ipc->dst = 1; - pr_info("sipc: dst =%d\n", ipc->dst); - - if (ipc->dst >= SIPC_ID_NR) { - pr_err("sipc: dst err\n"); - return ret; - } - -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE - if (ipc->type == SIPC_BASE_PCIE) { - ipc->ep_dev = 0; - pr_info("sipc: ep_dev=%d\n", ipc->ep_dev); - if (ipc->ep_dev >= PCIE_EP_NR) { - pr_err("sipc: ep_dev err\n"); - return -1; - } - - } -#endif - /* get smem type */ - ipc->smem_type = SMEM_LOCAL; - - pr_info("sipc: smem_type = %d\n", ipc->smem_type); - - /* get smem info */ - val[0] = sipc_get_smem_base(0x0300000); - val[1] = val[0]; - val[2] = 0x0300000; - ipc->smem_base = val[0]; - ipc->dst_smem_base = val[1]; - ipc->smem_size = val[2]; - pr_info("sipc: smem_base=0x%x, dst_smem_base=0x%x, smem_size=0x%x\n", - ipc->smem_base, ipc->dst_smem_base, ipc->smem_size); - -#ifdef CONFIG_PHYS_ADDR_T_64BIT - /* try to get high_offset */ - ipc->high_offset = 0; - pr_info("sipc: high_offset=0x%xn", ipc->high_offset); - -#endif - - if (ipc->type == SIPC_BASE_PCIE) { - /* pcie sipc, the host must use loacal SMEM_LOCAL */ - if (!ipc->client && ipc->smem_type != SMEM_LOCAL) { - pr_err("sipc: host must use local smem!"); - return -EINVAL; - } - - if (ipc->client && ipc->smem_type != SMEM_PCIE) { - pr_err("sipc: client must use pcie smem!"); - return -EINVAL; - } - } - - return 0; -} -#endif - -static int sipc_probe(struct platform_device *pdev) -{ - struct smsg_ipc *ipc; - struct device_node *np; - - if (1) { - np = pdev->dev.of_node; - ipc = devm_kzalloc(&pdev->dev, - sizeof(struct smsg_ipc), - GFP_KERNEL); - if (!ipc) - return -ENOMEM; - - if (sipc_parse_dt(ipc, np, &pdev->dev)) { - pr_err("%s: failed to parse dt!\n", __func__); - return -ENODEV; - } - - /* - * In charge mode, will only boot pm system, - * so just create pm systen sipc. - */ - if (g_boot_mode == CHARGE_MODE && ipc->dst != SIPC_ID_PM_SYS) - return -ENODEV; - - ipc->rxirq_status = sipc_rxirq_status; - ipc->rxirq_clear = sipc_rxirq_clear; - ipc->txirq_trigger = sipc_txirq_trigger; - spin_lock_init(&ipc->txpinlock); - - if (ipc->type == SIPC_BASE_PCIE) { - /* init mpm delay enter idle time for pcie. */ - if (g_boot_mode == CALI_MODE) - ipc->latency = CALI_LATENCY; - else - ipc->latency = NORMAL_LATENCY; - } - - smsg_ipc_create(ipc); - platform_set_drvdata(pdev, ipc); - } - return 0; -} - -static int sipc_remove(struct platform_device *pdev) -{ - struct smsg_ipc *ipc = platform_get_drvdata(pdev); - - smsg_ipc_destroy(ipc); - - devm_kfree(&pdev->dev, ipc); - return 0; -} - -#ifdef SPRD_PCIE_USE_DTS -static const struct of_device_id sipc_match_table[] = { - { .compatible = "sprd,sipc", }, - { }, -}; -#endif - -static struct platform_driver sipc_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "sipc", -#ifdef SPRD_PCIE_USE_DTS - .of_match_table = sipc_match_table, -#endif - }, - .probe = sipc_probe, - .remove = sipc_remove, -}; - -#ifndef SPRD_PCIE_USE_DTS -static void sipc_platform_device_release(struct device *dev) {} -static struct platform_device sipc_device = { - .name = "sipc", - .id = -1, - .dev = { - .release = sipc_platform_device_release, - } -}; -#endif - -int sipc_init(void) -{ - int ret; - - smsg_init_channel2index(); -#ifndef SPRD_PCIE_USE_DTS - if((ret = platform_device_register(&sipc_device))) - return ret; -#endif - - if((ret = platform_driver_register(&sipc_driver))) { -#ifndef SPRD_PCIE_USE_DTS - platform_device_unregister(&sipc_device); -#endif - return ret; - } - - return ret; -} -EXPORT_SYMBOL_GPL(sipc_init); - -void sipc_exit(void) -{ - platform_driver_unregister(&sipc_driver); - printk("dayin is here0\n"); -#ifndef SPRD_PCIE_USE_DTS - platform_device_unregister(&sipc_device); -#endif -} -EXPORT_SYMBOL_GPL(sipc_exit); \ No newline at end of file diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sipc_debugfs.c b/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sipc_debugfs.c deleted file mode 100644 index 135f13984..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sipc_debugfs.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include - -#include "../include/sipc.h" -#if defined(CONFIG_DEBUG_FS) -#include "sipc_debugfs.h" - -int sipc_init_debugfs(void) -{ - struct dentry *root = debugfs_create_dir("sipc", NULL); - - if (!root) - return -ENXIO; - - smsg_init_debugfs(root); -#if defined(CONFIG_SPRD_SIPC_SMSGC) - smsgc_init_debugfs(root); -#endif - sbuf_init_debugfs(root); - sblock_init_debugfs(root); -#ifdef CONFIG_SPRD_SIPC_ZERO_COPY_SIPX - sipx_init_debugfs(root); -#endif -#ifdef CONFIG_SPRD_SIPC_SWCNBLK - swcnblk_init_debugfs(root); -#endif - smem_init_debugfs(root); -#ifdef CONFIG_SPRD_MAILBOX - mbox_init_debugfs(root); -#endif - return 0; -} -EXPORT_SYMBOL_GPL(sipc_init_debugfs); -#endif /* CONFIG_DEBUG_FS */ diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sipc_debugfs.h b/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sipc_debugfs.h deleted file mode 100644 index e7849f515..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sipc_debugfs.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ -#ifndef __SIPC_DEBUGFS_H -#define __SIPC_DEBUGFS_H - -int sbuf_init_debugfs(void *root); -int smsg_init_debugfs(void *root); -int sblock_init_debugfs(void *root); -int smem_init_debugfs(void *root); - -#ifdef CONFIG_SPRD_SIPC_ZERO_COPY_SIPX -int sipx_init_debugfs(void *root); -#endif - -#ifdef CONFIG_SPRD_SIPC_SWCNBLK -int swcnblk_init_debugfs(void *root); -#endif - -#if defined(CONFIG_SPRD_SIPC_SMSGC) -int smsgc_init_debugfs(void *root); -#endif - -#ifdef CONFIG_SPRD_MAILBOX -int mbox_init_debugfs(void *root); -#endif -#endif /* !__SIPC_DEBUGFS_H */ - diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sipc_priv.h b/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sipc_priv.h deleted file mode 100644 index 0702faf39..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/sipc_priv.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#ifndef __SIPC_PRIV_H -#define __SIPC_PRIV_H -#include -#include -#include - -#include "../include/sprd_mpm.h" -#ifdef CONFIG_SPRD_MAILBOX -#include -#endif - -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE -#include "../include/sprd_pcie_ep_device.h" -#endif - -#ifdef CONFIG_PCIE_EPF_SPRD -#include -#endif - -#ifdef CONFIG_PCI -#include "../include/sprd_pcie_resource.h" -#endif - -#include "../include/sipc_big_to_little.h" - -#ifndef SZ_1K -#define SZ_1K 0x00000400 -#define SZ_4K 0x00001000 -#endif - -enum { - SIPC_BASE_MBOX = 0, - SIPC_BASE_PCIE, - SIPC_BASE_IPI, - SIPC_BASE_NR -}; - -enum smem_type { - SMEM_LOCAL = 0, - SMEM_PCIE -}; - -extern struct smsg_ipc *smsg_ipcs[]; -#define SMSG_CACHE_NR 256 - -struct smsg_channel { - /* wait queue for recv-buffer */ - wait_queue_head_t rxwait; - struct mutex rxlock; - struct sprd_pms *tx_pms; - struct sprd_pms *rx_pms; - char tx_name[16]; - char rx_name[16]; - - /* cached msgs for recv */ - uintptr_t wrptr[1]; - uintptr_t rdptr[1]; - struct smsg caches[SMSG_CACHE_NR]; -}; - -/* smsg ring-buffer between AP/CP ipc */ -struct smsg_ipc { - const char *name; - struct sprd_pms *sipc_pms; - - u8 dst; - u8 client; /* sipc is client mode */ - /* target core_id over mailbox */ - u8 core_id; - u8 core_sensor_id; - u32 type; /* sipc type, mbox, ipi, pcie */ - - void __iomem *write_addr; - -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE - u32 ep_dev; - struct platform_device *pcie_dev; -#endif -#ifdef CONFIG_PCIE_EPF_SPRD - u32 ep_fun; -#endif - u32 latency; - - /* send-buffer info */ - uintptr_t txbuf_addr; - u32 txbuf_size; /* must be 2^n */ - uintptr_t txbuf_rdptr; - uintptr_t txbuf_wrptr; - - /* recv-buffer info */ - uintptr_t rxbuf_addr; - u32 rxbuf_size; /* must be 2^n */ - uintptr_t rxbuf_rdptr; - uintptr_t rxbuf_wrptr; - - /* sipc irq related */ - int irq; - u32 (*rxirq_status)(u8 id); - void (*rxirq_clear)(u8 id); - void (*txirq_trigger)(u8 id, u64 msg); - - u32 ring_base; - u32 ring_size; - void *smem_vbase; - u32 smem_base; - u32 smem_size; - enum smem_type smem_type; - u32 dst_smem_base; -#ifdef CONFIG_PHYS_ADDR_T_64BIT - u32 high_offset; -#endif - /* lock for send-buffer */ - spinlock_t txpinlock; - /* all fixed channels receivers */ - struct smsg_channel *channels[SMSG_VALID_CH_NR]; - /* record the runtime status of smsg channel */ - atomic_t busy[SMSG_VALID_CH_NR]; - /* all channel states: 0 unused, 1 be opened by other core, 2 opend */ - u8 states[SMSG_VALID_CH_NR]; -}; - -#define CHAN_STATE_UNUSED 0 -#define CHAN_STATE_CLIENT_OPENED 1 -#define CHAN_STATE_HOST_OPENED 2 -#define CHAN_STATE_OPENED 3 -#define CHAN_STATE_FREE 4 - -void smsg_init_channel2index(void); -void smsg_ipc_create(struct smsg_ipc *ipc); -void smsg_ipc_destroy(struct smsg_ipc *ipc); - -/*smem alloc size align*/ -#define SMEM_ALIGN_POOLSZ 0x40000 /*256KB*/ - -#ifdef CONFIG_64BIT -#define SMEM_ALIGN_BYTES 8 -#define SMEM_MIN_ORDER 3 -#else -#define SMEM_ALIGN_BYTES 4 -#define SMEM_MIN_ORDER 2 -#endif - -/* initialize smem pool for AP/CP */ -int smem_init(u32 addr, u32 size, u32 dst, u32 mem_type); -void sbuf_get_status(u8 dst, char *status_info, int size); - -#if defined(CONFIG_DEBUG_FS) -void sipc_debug_putline(struct seq_file *m, char c, int n); -#endif - -#ifdef CONFIG_SPRD_MAILBOX -#define MBOX_INVALID_CORE 0xff -#endif - -/* sipc_smem_request_resource - * local smem no need request resource, just return 0. - */ -static inline int sipc_smem_request_resource(struct sprd_pms *pms, - u8 dst, int timeout) -{ - if (smsg_ipcs[dst]->smem_type == SMEM_LOCAL) - return 0; - - return sprd_pms_request_resource(pms, timeout); -} - -/* sipc_smem_release_resource - * local smem no need release resource, do nothing. - */ -static inline void sipc_smem_release_resource(struct sprd_pms *pms, u8 dst) -{ - if (smsg_ipcs[dst]->smem_type != SMEM_LOCAL) - sprd_pms_release_resource(pms); -} -#endif diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/smem.c b/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/smem.c deleted file mode 100644 index 12640c2e3..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/smem.c +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sipc.h" -#include "sipc_priv.h" -#define CONFIG_SPRD_IPA_PCIE_WORKROUND -/* - * workround: Due to orca ipa hardware limitations - * the sipc share memory must map from - * 0x2x0000000(orca side) to 0xx0000000(roc1 - * side), and the size must be 256M - */ -#ifdef CONFIG_SPRD_IPA_PCIE_WORKROUND -#define IPA_GET_SRC_BASE(addr) (((addr) & 0xf0000000) + 0x200000000) -#define IPA_GET_DST_BASE(addr) ((addr) & 0xf0000000) -#define IPA_SIZE 0x10000000 -#endif - -struct smem_phead { - struct list_head smem_phead; - spinlock_t lock; - u32 poolnum; -}; - -struct smem_pool { - struct list_head smem_head; - struct list_head smem_plist; - spinlock_t lock; - - void *pcie_base; - u32 addr; - u32 size; - u32 dst; - u32 mem_type; - - atomic_t used; - struct gen_pool *gen; -}; - -struct smem_record { - struct list_head smem_list; - struct task_struct *task; - u32 size; - u32 addr; -}; - -struct smem_map_list { - struct list_head map_head; - spinlock_t lock; - u32 inited; -}; - -struct smem_map { - struct list_head map_list; - struct task_struct *task; - const void *mem; - unsigned int count; -}; - -static struct smem_phead sipc_smem_phead; -static struct smem_map_list mem_mp; - -static struct smem_pool *shmem_find_pool(u8 dst) -{ - struct smem_phead *phead = &sipc_smem_phead; - struct smem_pool *spool = NULL; - struct smem_pool *pos; - unsigned long flags; - - /* The num of one pool is 0, means the poll is not ready */ - if (!phead->poolnum) - return NULL; - - spin_lock_irqsave(&phead->lock, flags); - list_for_each_entry(pos, &phead->smem_phead, smem_plist) { - if (pos->dst == dst) { - spool = pos; - break; - } - } - spin_unlock_irqrestore(&phead->lock, flags); - return spool; -} - -static void *soc_modem_ram_vmap(phys_addr_t start, size_t size, int noncached) -{ - struct page **pages; - phys_addr_t page_start; - unsigned int page_count; - pgprot_t prot; - unsigned int i; - void *vaddr; - phys_addr_t addr; - unsigned long flags; - struct smem_map *map; - struct smem_map_list *smem = &mem_mp; - - map = kzalloc(sizeof(struct smem_map), GFP_KERNEL); - if (!map) - return NULL; - - page_start = start - offset_in_page(start); - page_count = DIV_ROUND_UP(size + offset_in_page(start), PAGE_SIZE); - if (noncached) - prot = pgprot_noncached(PAGE_KERNEL); - else - prot = PAGE_KERNEL; - - pages = kmalloc_array(page_count, sizeof(struct page *), GFP_KERNEL); - if (!pages) { - kfree(map); - return NULL; - } - - for (i = 0; i < page_count; i++) { - addr = page_start + i * PAGE_SIZE; - pages[i] = pfn_to_page(addr >> PAGE_SHIFT); - } - -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 5,10,0 )) - vaddr = vm_map_ram(pages, page_count, -1, prot); -#else - vaddr = vmap(pages, page_count, -1, prot); - //vaddr = vm_map_ram(pages, page_count, -1); -#endif - - kfree(pages); - - if (!vaddr) { - pr_err("smem: vm map failed.\n"); - kfree(map); - return NULL; - } - - vaddr += offset_in_page(start); - map->count = page_count; - map->mem = vaddr; - map->task = current; - - if (smem->inited) { - spin_lock_irqsave(&smem->lock, flags); - list_add_tail(&map->map_list, &smem->map_head); - spin_unlock_irqrestore(&smem->lock, flags); - } - return vaddr; -} - -static void *pcie_modem_ram_vmap(phys_addr_t start, size_t size, int noncached) -{ - if (noncached == 0) { - pr_err("%s: cache not support!\n", __func__); - return NULL; - } - -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE - return sprd_ep_map_memory(PCIE_EP_MODEM, start, size); -#endif - -#ifdef CONFIG_PCIE_EPF_SPRD - return sprd_pci_epf_map_memory(SPRD_FUNCTION_0, start, size); -#endif - - return NULL; -} - -static void pcie_modem_ram_unmap(const void *mem) -{ -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE - return sprd_ep_unmap_memory(PCIE_EP_MODEM, mem); -#endif - -#ifdef CONFIG_PCIE_EPF_SPRD - return sprd_pci_epf_unmap_memory(SPRD_FUNCTION_0, mem); -#endif -} - -static void soc_modem_ram_unmap(const void *mem) -{ - struct smem_map *map, *next; - unsigned long flags; - struct smem_map_list *smem = &mem_mp; - bool found = false; - - if (smem->inited) { - spin_lock_irqsave(&smem->lock, flags); - list_for_each_entry_safe(map, next, &smem->map_head, map_list) { - if (map->mem == mem) { - list_del(&map->map_list); - found = true; - break; - } - } - spin_unlock_irqrestore(&smem->lock, flags); - - if (found) { - vm_unmap_ram(mem - offset_in_page(mem), map->count); - kfree(map); - } - } -} - -static void *shmem_ram_vmap(u8 dst, phys_addr_t start, - size_t size, - int noncached) -{ - struct smem_pool *spool; - - spool = shmem_find_pool(dst); - if (spool == NULL) { - pr_err("%s: pool dst %d is not existed!\n", __func__, dst); - return NULL; - } - - if (spool->mem_type == SMEM_PCIE) { - if (start < spool->addr - || start + size > spool->addr + spool->size) { - pr_info("%s: error, start = 0x%lx, size = 0x%lx.\n", - __func__, - (unsigned long)start, - (unsigned long)size); - return NULL; - } - - pr_info("%s: succ, start = 0x%lx, size = 0x%lx.\n", - __func__, (unsigned long)start, (unsigned long)size); - return (spool->pcie_base + start - spool->addr); - } - - return soc_modem_ram_vmap(start, size, noncached); - -} - -int smem_init(u32 addr, u32 size, u32 dst, u32 mem_type) -{ - struct smem_phead *phead = &sipc_smem_phead; - struct smem_map_list *smem = &mem_mp; - struct smem_pool *spool; - unsigned long flags; - - /* fisrt init, create the pool head */ - if (!phead->poolnum) { - spin_lock_init(&phead->lock); - INIT_LIST_HEAD(&phead->smem_phead); - } - - if (shmem_find_pool(dst)) - return 0; - - spool = kzalloc(sizeof(struct smem_pool), GFP_KERNEL); - if (!spool) - return -1; - - spin_lock_irqsave(&phead->lock, flags); - list_add_tail(&spool->smem_plist, &phead->smem_phead); - phead->poolnum++; - spin_unlock_irqrestore(&phead->lock, flags); - - spool->addr = addr; - spool->dst = dst; - spool->mem_type = mem_type; - - if (size >= SMEM_ALIGN_POOLSZ) - size = PAGE_ALIGN(size); - else - size = ALIGN(size, SMEM_ALIGN_BYTES); - - spool->size = size; - atomic_set(&spool->used, 0); - spin_lock_init(&spool->lock); - INIT_LIST_HEAD(&spool->smem_head); - - spin_lock_init(&smem->lock); - INIT_LIST_HEAD(&smem->map_head); - smem->inited = 1; - - /* allocator block size is times of pages */ - if (spool->size >= SMEM_ALIGN_POOLSZ) - spool->gen = gen_pool_create(PAGE_SHIFT, -1); - else - spool->gen = gen_pool_create(SMEM_MIN_ORDER, -1); - - if (!spool->gen) { - pr_err("Failed to create smem gen pool!\n"); - return -1; - } - - if (gen_pool_add(spool->gen, spool->addr, spool->size, -1) != 0) { - pr_err("Failed to add smem gen pool!\n"); - return -1; - } - pr_info("%s: pool addr = 0x%x, size = 0x%x added.\n", - __func__, spool->addr, spool->size); - - if (mem_type == SMEM_PCIE) { -#ifdef CONFIG_SPRD_IPA_PCIE_WORKROUND -#ifdef CONFIG_PCIE_EPF_SPRD - spool->pcie_base = sprd_epf_ipa_map(IPA_GET_SRC_BASE(addr), - IPA_GET_DST_BASE(addr), - IPA_SIZE); - if (!spool->pcie_base) - return -ENOMEM; - - spool->pcie_base += (addr - IPA_GET_DST_BASE(addr)); -#else - pr_err("Failed to pcie map, can't run here!\n"); - return -ENOMEM; -#endif -#else - spool->pcie_base = pcie_modem_ram_vmap(addr, size, 1); -#endif - } - return 0; -} - -/* ****************************************************************** */ - -int smem_get_area(u8 dst, u32 *base, u32 *size) -{ - struct smem_pool *spool; - - if (!base || !size) - return -EINVAL; - - spool = shmem_find_pool(dst); - if (!spool) { - pr_err("%s: err, dst = %d!\n", __func__, dst); - return -EINVAL; - } - - pr_info("%s: addr = 0x%x, size = 0x%x.\n", - __func__, spool->addr, spool->size); - - *base = spool->addr; - *size = spool->size; - - return 0; -} -EXPORT_SYMBOL_GPL(smem_get_area); - -u32 smem_alloc(u8 dst, u32 size) -{ - struct smem_pool *spool; - struct smem_record *recd; - unsigned long flags; - u32 addr = 0; - - spool = shmem_find_pool(dst); - if (spool == NULL) { - pr_err("%s: pool dst %d is not existed!\n", __func__, dst); - return 0; - } - - recd = kzalloc(sizeof(struct smem_record), GFP_KERNEL); - if (!recd) - return 0; - - if (spool->size >= SMEM_ALIGN_POOLSZ) - size = PAGE_ALIGN(size); - else - size = ALIGN(size, SMEM_ALIGN_BYTES); - - addr = gen_pool_alloc(spool->gen, size); - if (!addr) { - pr_err("%s:pool dst=%d, size=0x%x failed to alloc smem!\n", - __func__, dst, size); - kfree(recd); - return 0; - } - - /* record smem alloc info */ - atomic_add(size, &spool->used); - recd->size = size; - recd->task = current; - recd->addr = addr; - spin_lock_irqsave(&spool->lock, flags); - list_add_tail(&recd->smem_list, &spool->smem_head); - spin_unlock_irqrestore(&spool->lock, flags); - - return addr; -} -EXPORT_SYMBOL_GPL(smem_alloc); - -void smem_free(u8 dst, u32 addr, u32 size) -{ - struct smem_pool *spool; - struct smem_record *recd, *next; - unsigned long flags; - - spool = shmem_find_pool(dst); - if (spool == NULL) { - pr_err("%s: pool dst %d is not existed!\n", __func__, dst); - return; - } - - if (size >= SMEM_ALIGN_POOLSZ) - size = PAGE_ALIGN(size); - else - size = ALIGN(size, SMEM_ALIGN_BYTES); - - atomic_sub(size, &spool->used); - gen_pool_free(spool->gen, addr, size); - /* delete record node from list */ - spin_lock_irqsave(&spool->lock, flags); - list_for_each_entry_safe(recd, next, &spool->smem_head, smem_list) { - if (recd->addr == addr) { - list_del(&recd->smem_list); - kfree(recd); - break; - } - } - spin_unlock_irqrestore(&spool->lock, flags); -} -EXPORT_SYMBOL_GPL(smem_free); - -void *shmem_ram_vmap_nocache(u8 dst, phys_addr_t start, size_t size) -{ - return shmem_ram_vmap(dst, start, size, 1); -} -EXPORT_SYMBOL_GPL(shmem_ram_vmap_nocache); - - -void *shmem_ram_vmap_cache(u8 dst, phys_addr_t start, size_t size) -{ - return shmem_ram_vmap(dst, start, size, 0); -} -EXPORT_SYMBOL_GPL(shmem_ram_vmap_cache); - -void shmem_ram_unmap(u8 dst, const void *mem) -{ - struct smem_pool *spool; - - spool = shmem_find_pool(dst); - if (spool == NULL) { - pr_err("%s: pool dst %d is not existed!\n", __func__, dst); - return; - } - - if (spool->mem_type == SMEM_PCIE) - /* do nothing, because it also do nothing in shmem_ram_vmap */ - return; - else - return soc_modem_ram_unmap(mem); -} -EXPORT_SYMBOL_GPL(shmem_ram_unmap); - -void *modem_ram_vmap_nocache(u32 modem_type, phys_addr_t start, size_t size) -{ - if (modem_type == PCIE_MODEM) - return pcie_modem_ram_vmap(start, size, 1); - else - return soc_modem_ram_vmap(start, size, 1); -} -EXPORT_SYMBOL_GPL(modem_ram_vmap_nocache); - - -void *modem_ram_vmap_cache(u32 modem_type, phys_addr_t start, size_t size) -{ - if (modem_type == PCIE_MODEM) - return pcie_modem_ram_vmap(start, size, 0); - else - return soc_modem_ram_vmap(start, size, 0); -} -EXPORT_SYMBOL_GPL(modem_ram_vmap_cache); - -void modem_ram_unmap(u32 modem_type, const void *mem) -{ - if (modem_type == PCIE_MODEM) - return pcie_modem_ram_unmap(mem); - else - return soc_modem_ram_unmap(mem); -} -EXPORT_SYMBOL_GPL(modem_ram_unmap); - -#ifdef CONFIG_DEBUG_FS -static int smem_debug_show(struct seq_file *m, void *private) -{ - struct smem_phead *phead = &sipc_smem_phead; - struct smem_pool *spool, *pos; - struct smem_record *recd; - u32 fsize; - unsigned long flags; - u32 cnt = 1; - - spin_lock_irqsave(&phead->lock, flags); - list_for_each_entry(pos, &phead->smem_phead, smem_plist) { - spool = pos; - fsize = gen_pool_avail(spool->gen); - - sipc_debug_putline(m, '*', 80); - seq_printf(m, "%d, dst:%d, name: %s, smem pool info:\n", - cnt++, spool->dst, - (smsg_ipcs[spool->dst])->name); - seq_printf(m, "phys_addr=0x%x, total=0x%x, used=0x%x, free=0x%x\n", - spool->addr, spool->size, spool->used.counter, fsize); - seq_puts(m, "smem record list:\n"); - - list_for_each_entry(recd, &spool->smem_head, smem_list) { - seq_printf(m, "task %s: pid=%u, addr=0x%x, size=0x%x\n", - recd->task->comm, - recd->task->pid, - recd->addr, - recd->size); - } - } - spin_unlock_irqrestore(&phead->lock, flags); - return 0; -} - -static int smem_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, smem_debug_show, inode->i_private); -} - -static const struct file_operations smem_debug_fops = { - .open = smem_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -int smem_init_debugfs(void *root) -{ - if (!root) - return -ENXIO; - debugfs_create_file("smem", 0444, - (struct dentry *)root, NULL, - &smem_debug_fops); - return 0; -} -EXPORT_SYMBOL_GPL(smem_init_debugfs); - -#endif /* endof CONFIG_DEBUG_FS */ - - -MODULE_AUTHOR("Chen Gaopeng"); -MODULE_DESCRIPTION("SIPC/SMEM driver"); -MODULE_LICENSE("GPL v2"); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/smsg.c b/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/smsg.c deleted file mode 100644 index 051800d8f..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/smsg.c +++ /dev/null @@ -1,1103 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_SPRD_MAILBOX -#include -#endif - -#include "../include/sipc.h" -#include "sipc_priv.h" -#include "../include/sprd_pcie_resource.h" - -#if defined(CONFIG_DEBUG_FS) -#include "sipc_debugfs.h" -#endif - -#define SMSG_TXBUF_ADDR (0) -#define SMSG_TXBUF_SIZE (SZ_1K) -#define SMSG_RXBUF_ADDR (SMSG_TXBUF_SIZE) -#define SMSG_RXBUF_SIZE (SZ_1K) - -#define SMSG_RINGHDR (SMSG_TXBUF_SIZE + SMSG_RXBUF_SIZE) -#define SMSG_TXBUF_RDPTR (SMSG_RINGHDR + 0) -#define SMSG_TXBUF_WRPTR (SMSG_RINGHDR + 4) -#define SMSG_RXBUF_RDPTR (SMSG_RINGHDR + 8) -#define SMSG_RXBUF_WRPTR (SMSG_RINGHDR + 12) - -#define SMSG_RESERVE_BASE (SMSG_RINGHDR + SZ_1K) -#define SMSG_PCIE_WRPTR (SMSG_RESERVE_BASE + 0) -#define SMSG_PCIE_IRQPTR (SMSG_RESERVE_BASE + 4) - -#define SIPC_READL(addr) readl((__force void __iomem *)(addr)) -#define SIPC_WRITEL(b, addr) writel(b, (__force void __iomem *)(addr)) - -static u8 g_wakeup_flag; - -struct smsg_ipc *smsg_ipcs[SIPC_ID_NR]; -EXPORT_SYMBOL_GPL(smsg_ipcs); - -static ushort debug_enable; - -module_param_named(debug_enable, debug_enable, ushort, 0644); -static u8 channel2index[SMSG_CH_NR + 1]; - -static int smsg_ipc_smem_init(struct smsg_ipc *ipc); - -void smsg_init_channel2index(void) -{ - u16 i, j; - - for (i = 0; i < ARRAY_SIZE(channel2index); i++) { - for (j = 0; j < SMSG_VALID_CH_NR; j++) { - /* find the index of channel i */ - if (sipc_cfg[j].channel == i) - break; - } - - /* if not find, init with INVALID_CHANEL_INDEX, - * else init whith j - */ - if (j == SMSG_VALID_CH_NR) - channel2index[i] = INVALID_CHANEL_INDEX; - else - channel2index[i] = j; - } -} - -static void get_channel_status(u8 dst, char *status, int size) -{ - int i, len; - struct smsg_channel *ch; - - len = strlen(status); - for (i = 0; i < SMSG_VALID_CH_NR && len < size; i++) { - ch = smsg_ipcs[dst]->channels[i]; - if (!ch) - continue; - if (SIPC_READL(ch->rdptr) < SIPC_READL(ch->wrptr)) - snprintf( - status + len, - size - len, - "dst-%d-ch-%d: rd = %u, wr = %u.\n", - dst, - i, - SIPC_READL(ch->rdptr), - SIPC_READL(ch->wrptr) - ); - } -} - -static void smsg_wakeup_print(struct smsg_ipc *ipc, struct smsg *msg) -{ - /* if the first msg come after the irq wake up by sipc, - * use prin_fo to output log - */ - if (g_wakeup_flag) { - g_wakeup_flag = 0; - pr_info("irq read smsg: dst=%d, channel=%d,type=%d, flag=0x%04x, value=0x%08x\n", - ipc->dst, - msg->channel, - msg->type, - msg->flag, - msg->value); - } else { - pr_debug("irq read smsg: dst=%d, channel=%d,type=%d, flag=0x%04x, value=0x%08x\n", - ipc->dst, - msg->channel, - msg->type, - msg->flag, - msg->value); - } -} - -static void smsg_die_process(struct smsg_ipc *ipc, struct smsg *msg) -{ - if (msg->type == SMSG_TYPE_DIE) { - if (debug_enable) { - char sipc_status[100] = {0}; - - get_channel_status(ipc->dst, - sipc_status, - sizeof(sipc_status)); - sbuf_get_status(ipc->dst, - sipc_status, - sizeof(sipc_status)); - panic("cpcrash: %s", sipc_status); - while (1) - ; - } - } -} - -static void smsg_msg_process(struct smsg_ipc *ipc, - struct smsg *msg, bool wake_lock) -{ - struct smsg_channel *ch = NULL; - u32 wr; - u8 ch_index; - - smsg_wakeup_print(ipc, msg); - smsg_die_process(ipc, msg); - - ch_index = channel2index[msg->channel]; - atomic_inc(&ipc->busy[ch_index]); - - pr_debug("smsg:get dst=%d msg channel=%d, type=%d, flag=0x%04x, value=0x%08x\n", - ipc->dst, msg->channel, - msg->type, msg->flag, - msg->value); - - if (msg->type >= SMSG_TYPE_NR) { - /* invalid msg */ - pr_err("invalid smsg: channel=%d, type=%d, flag=0x%04x, value=0x%08x\n", - msg->channel, msg->type, msg->flag, msg->value); - goto exit_msg_proc; - } - - ch = ipc->channels[ch_index]; - if (!ch) { - if (ipc->states[ch_index] == CHAN_STATE_UNUSED && - msg->type == SMSG_TYPE_OPEN && - msg->flag == SMSG_OPEN_MAGIC) - ipc->states[ch_index] = CHAN_STATE_CLIENT_OPENED; - else - /* drop this bad msg since channel - * is not opened - */ - pr_info("smsg channel %d not opened! drop smsg: type=%d, flag=0x%04x, value=0x%08x\n", - msg->channel, msg->type, - msg->flag, msg->value); - - goto exit_msg_proc; - } - - if ((int)(SIPC_READL(ch->wrptr) - SIPC_READL(ch->rdptr)) >= - SMSG_CACHE_NR) { - /* msg cache is full, drop this msg */ - pr_info("smsg channel %d recv cache is full! drop smsg: type=%d, flag=0x%04x, value=0x%08x\n", - msg->channel, msg->type, msg->flag, msg->value); - } else { - /* write smsg to cache */ - wr = SIPC_READL(ch->wrptr) & (SMSG_CACHE_NR - 1); - memcpy(&ch->caches[wr], msg, sizeof(struct smsg)); - SIPC_WRITEL(SIPC_READL(ch->wrptr) + 1, ch->wrptr); - } - - wake_up_interruptible_all(&ch->rxwait); - - if (wake_lock) - sprd_pms_request_wakelock_period(ch->rx_pms, 500); - -exit_msg_proc: - atomic_dec(&ipc->busy[ch_index]); -} - -#ifdef CONFIG_SPRD_MAILBOX -static irqreturn_t smsg_mbox_irq_handler(void *ptr, void *private) -{ - struct smsg_ipc *ipc = (struct smsg_ipc *)private; - struct smsg *msg; - - msg = ptr; - smsg_msg_process(ipc, msg, true); - - return IRQ_HANDLED; -} - -static irqreturn_t smsg_mbox_sensor_irq_handler(void *ptr, void *private) -{ - struct smsg_ipc *ipc = (struct smsg_ipc *)private; - struct smsg *msg; - - msg = ptr; - smsg_msg_process(ipc, msg, false); - - return IRQ_HANDLED; -} - -#endif - -static int sipc_process_all_msg(struct smsg_ipc *ipc) -{ - struct smsg *msg; - struct smsg msg_recv; - uintptr_t rxpos; - - /* msg coming, means resource ok, don't wait */ - sipc_smem_request_resource(ipc->sipc_pms, ipc->dst, 0); - - while (BL_READL(ipc->rxbuf_wrptr) != BL_READL(ipc->rxbuf_rdptr)) { - rxpos = (BL_READL(ipc->rxbuf_rdptr) & (ipc->rxbuf_size - 1)) * - sizeof(struct smsg) + ipc->rxbuf_addr; - msg = (struct smsg *)rxpos; - - /* share memory smsg to ipc msg */ - msg_recv.channel = msg->channel; - msg_recv.type = msg->type; - msg_recv.flag = BL_GETW(msg->flag); - msg_recv.value= BL_GETL(msg->value); - smsg_msg_process(ipc, &msg_recv, true); - /* update smsg rdptr */ - BL_WRITEL(BL_READL(ipc->rxbuf_rdptr) + 1, ipc->rxbuf_rdptr); - } - - sipc_smem_release_resource(ipc->sipc_pms, ipc->dst); - - return 0; -} - - -static irqreturn_t smsg_irq_handler(int irq, void *private) -{ - struct smsg_ipc *ipc = (struct smsg_ipc *)private; - - if (ipc->rxirq_status(ipc->dst)) - ipc->rxirq_clear(ipc->dst); - - sipc_process_all_msg(ipc); - - return IRQ_HANDLED; -} - -static void smsg_ipc_init_smsg_irq_callback(struct smsg_ipc *ipc) -{ -#ifdef CONFIG_SPRD_MAILBOX - if (ipc->type == SIPC_BASE_MBOX) { - mbox_register_irq_handle(ipc->core_id, - smsg_mbox_irq_handler, ipc); - - if ((ipc->dst == SIPC_ID_PM_SYS) && - (ipc->core_sensor_id != MBOX_INVALID_CORE)) - mbox_register_irq_handle(ipc->core_sensor_id, - smsg_mbox_sensor_irq_handler, - ipc); - return; - } -#endif - -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE - if (ipc->type == SIPC_BASE_PCIE) { - sprd_ep_dev_register_irq_handler(ipc->ep_dev, - PCIE_MSI_SIPC_IRQ, - smsg_irq_handler, ipc); - sprd_ep_dev_set_irq_addr(ipc->ep_dev, ipc->write_addr + 4); - return; - } -#endif - -#ifdef CONFIG_PCIE_EPF_SPRD - if (ipc->type == SIPC_BASE_PCIE) { - sprd_pci_epf_register_irq_handler(ipc->ep_fun, - PCIE_DBELL_SIPC_IRQ, - smsg_irq_handler, - ipc); - sprd_pci_epf_set_write_addr(ipc->ep_fun, ipc->write_addr); - return; - } -#endif - - if (ipc->type == SIPC_BASE_IPI) { - int ret; - - /* explicitly call irq handler in case of missing irq on boot */ - smsg_irq_handler(ipc->irq, ipc); - - /* register IPI irq */ - ret = request_irq(ipc->irq, - smsg_irq_handler, - IRQF_NO_SUSPEND, - ipc->name, - ipc); - if (ret) - pr_info("%s: request irq err = %d!\n", ipc->name, ret); - } -} - -static int smsg_ipc_smem_init(struct smsg_ipc *ipc) -{ - void __iomem *base, *p; - phys_addr_t offset = 0; - int ret; - - pr_debug("%s: %s, smem_type = %d!\n", - __func__, ipc->name, ipc->smem_type); - - ret = smem_init(ipc->smem_base, ipc->smem_size, - ipc->dst, ipc->smem_type); - if (ret) { - pr_err("%s: %s err = %d!\n", __func__, ipc->name, ret); - return ret; - } - - if (ipc->type != SIPC_BASE_MBOX) { - ipc->ring_base = smem_alloc(ipc->dst, SZ_4K); - ipc->ring_size = SZ_4K; - pr_info("%s: ring_base = 0x%x, ring_size = 0x%x\n", - __func__, - ipc->ring_base, - ipc->ring_size); - } - -#ifdef CONFIG_PHYS_ADDR_T_64BIT - offset = ipc->high_offset; - offset = offset << 32; -#endif - - if (ipc->ring_base) { - base = (void __iomem *)shmem_ram_vmap_nocache(ipc->dst, - ipc->ring_base + offset, - ipc->ring_size); - if (!base) { - pr_err("%s: ioremap failed!\n", __func__); - smem_free(ipc->dst, ipc->ring_base, SZ_4K); - ipc->ring_base = 0; - return -ENOMEM; - } - - /* assume client is boot later than host */ - if (!ipc->client) { - /** - * memset(base, 0, ipc->ring_size); - * the instruction dc avz - * will abort for nocache memory - */ - for (p = base; p < base + ipc->ring_size;) { -#ifdef CONFIG_64BIT - *(uint64_t *)p = 0x0; - p += sizeof(uint64_t); -#else - *(u32 *)p = 0x0; - p += sizeof(u32); -#endif - } - } - - if (ipc->client) { - /* clent mode, tx is host rx , rx is host tx*/ - ipc->smem_vbase = (void *)base; - ipc->txbuf_size = SMSG_RXBUF_SIZE / - sizeof(struct smsg); - ipc->txbuf_addr = (uintptr_t)base + - SMSG_RXBUF_ADDR; - ipc->txbuf_rdptr = (uintptr_t)base + - SMSG_RXBUF_RDPTR; - ipc->txbuf_wrptr = (uintptr_t)base + - SMSG_RXBUF_WRPTR; - ipc->rxbuf_size = SMSG_TXBUF_SIZE / - sizeof(struct smsg); - ipc->rxbuf_addr = (uintptr_t)base + - SMSG_TXBUF_ADDR; - ipc->rxbuf_rdptr = (uintptr_t)base + - SMSG_TXBUF_RDPTR; - ipc->rxbuf_wrptr = (uintptr_t)base + - SMSG_TXBUF_WRPTR; - } else { - ipc->smem_vbase = (void *)base; - ipc->txbuf_size = SMSG_TXBUF_SIZE / - sizeof(struct smsg); - ipc->txbuf_addr = (uintptr_t)base + - SMSG_TXBUF_ADDR; - ipc->txbuf_rdptr = (uintptr_t)base + - SMSG_TXBUF_RDPTR; - ipc->txbuf_wrptr = (uintptr_t)base + - SMSG_TXBUF_WRPTR; - ipc->rxbuf_size = SMSG_RXBUF_SIZE / - sizeof(struct smsg); - ipc->rxbuf_addr = (uintptr_t)base + - SMSG_RXBUF_ADDR; - ipc->rxbuf_rdptr = (uintptr_t)base + - SMSG_RXBUF_RDPTR; - ipc->rxbuf_wrptr = (uintptr_t)base + - SMSG_RXBUF_WRPTR; - } - ipc->write_addr = base + SMSG_PCIE_WRPTR; - } - - /* after smem_init complete, regist msg irq */ - smsg_ipc_init_smsg_irq_callback(ipc); - - return 0; -} - -#ifdef CONFIG_PCIE_EPF_SPRD -static void smsg_pcie_first_ready(void *data) -{ - struct smsg_ipc *ipc = (struct smsg_ipc *)data; - - if (ipc->smem_type == SMEM_PCIE) - smsg_ipc_smem_init(ipc); - else - pr_err("%s: pcie first ready, smem_type =%d!\n", - ipc->name, ipc->smem_type); -} -#endif - -static void smsg_ipc_mpm_init(struct smsg_ipc *ipc) -{ - /* create modem power manger instance for this sipc */ - sprd_mpm_create(ipc->dst, ipc->name, ipc->latency); - - /* init a power manager source */ - ipc->sipc_pms = sprd_pms_create(ipc->dst, ipc->name, true); - if (!ipc->sipc_pms) - pr_warn("create pms %s failed!\n", ipc->name); - - if (ipc->type == SIPC_BASE_PCIE) { - /* int mpm resource ops */ - sprd_mpm_init_resource_ops(ipc->dst, - sprd_pcie_wait_resource, - sprd_pcie_request_resource, - sprd_pcie_release_resource); - -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE - /* in pcie host side, init pcie host resource */ - sprd_pcie_resource_host_init(ipc->dst, - ipc->ep_dev, ipc->pcie_dev); -#endif - -#ifdef CONFIG_PCIE_EPF_SPRD - /* in pcie ep side, init pcie client resource */ - sprd_pcie_resource_client_init(ipc->dst, ipc->ep_fun); -#endif - } -} - -void smsg_ipc_create(struct smsg_ipc *ipc) -{ - pr_info("%s: %s\n", __func__, ipc->name); - - smsg_ipcs[ipc->dst] = ipc; - - smsg_ipc_mpm_init(ipc); - - - if (ipc->type == SIPC_BASE_PCIE) { -#ifdef CONFIG_PCIE_EPF_SPRD - /* set epf door bell irq number */ - sprd_pci_epf_set_irq_number(ipc->ep_fun, ipc->irq); - - /* register first pcie ready notify */ - sprd_register_pcie_resource_first_ready(ipc->dst, - smsg_pcie_first_ready, - ipc); -#endif - } - - /* if SMEM_PCIE, must init after pcie ready */ - if (ipc->smem_type != SMEM_PCIE) - smsg_ipc_smem_init(ipc); -} - -void smsg_ipc_destroy(struct smsg_ipc *ipc) -{ - shmem_ram_unmap(ipc->dst, ipc->smem_vbase); - smem_free(ipc->dst, ipc->ring_base, SZ_4K); - -#ifdef CONFIG_SPRD_MAILBOX - if (ipc->type == SIPC_BASE_MBOX) { - mbox_unregister_irq_handle(ipc->core_id); - - if ((ipc->dst == SIPC_ID_PM_SYS) && - (ipc->core_sensor_id != MBOX_INVALID_CORE)) - mbox_unregister_irq_handle(ipc->core_sensor_id); - } -#endif - - if (ipc->type == SIPC_BASE_PCIE) { -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE - sprd_ep_dev_unregister_irq_handler(ipc->ep_dev, ipc->irq); -#endif - -#ifdef CONFIG_PCIE_EPF_SPRD - sprd_pci_epf_unregister_irq_handler(ipc->ep_fun, ipc->irq); -#endif - sprd_pcie_resource_trash(ipc->dst); - } else { - free_irq(ipc->irq, ipc); - } - - smsg_ipcs[ipc->dst] = NULL; -} - -int sipc_get_wakeup_flag(void) -{ - return (int)g_wakeup_flag; -} -EXPORT_SYMBOL_GPL(sipc_get_wakeup_flag); - -void sipc_set_wakeup_flag(void) -{ - g_wakeup_flag = 1; -} -EXPORT_SYMBOL_GPL(sipc_set_wakeup_flag); - -void sipc_clear_wakeup_flag(void) -{ - g_wakeup_flag = 0; -} -EXPORT_SYMBOL_GPL(sipc_clear_wakeup_flag); - -int smsg_ch_wake_unlock(u8 dst, u8 channel) -{ - struct smsg_ipc *ipc = smsg_ipcs[dst]; - struct smsg_channel *ch; - u8 ch_index; - - ch_index = channel2index[channel]; - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - if (!ipc) - return -ENODEV; - - ch = ipc->channels[ch_index]; - if (!ch) - return -ENODEV; - - sprd_pms_release_wakelock(ch->rx_pms); - return 0; -} -EXPORT_SYMBOL_GPL(smsg_ch_wake_unlock); - -int smsg_ch_open(u8 dst, u8 channel, int timeout) -{ - struct smsg_ipc *ipc = smsg_ipcs[dst]; - struct smsg_channel *ch; - struct smsg mopen; - struct smsg mrecv; - int rval = 0; - u8 ch_index; - - ch_index = channel2index[channel]; - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - if (!ipc) - return -ENODEV; - - ch = kzalloc(sizeof(*ch), GFP_KERNEL); - if (!ch) - return -ENOMEM; - - sprintf(ch->tx_name, "smsg-%d-%d-tx", dst, channel); - ch->tx_pms = sprd_pms_create(dst, ch->tx_name, true); - if (!ch->tx_pms) - pr_warn("create pms %s failed!\n", ch->tx_name); - - sprintf(ch->rx_name, "smsg-%d-%d-rx", dst, channel); - ch->rx_pms = sprd_pms_create(dst, ch->rx_name, true); - if (!ch->rx_pms) - pr_warn("create pms %s failed!\n", ch->rx_name); - - atomic_set(&ipc->busy[ch_index], 1); - init_waitqueue_head(&ch->rxwait); - mutex_init(&ch->rxlock); - ipc->channels[ch_index] = ch; - - pr_info("%s: channel %d-%d send open msg!\n", - __func__, dst, channel); - - smsg_set(&mopen, channel, SMSG_TYPE_OPEN, SMSG_OPEN_MAGIC, 0); - rval = smsg_send(dst, &mopen, timeout); - if (rval != 0) { - pr_err("%s: channel %d-%d send open msg error = %d!\n", - __func__, dst, channel, rval); - ipc->states[ch_index] = CHAN_STATE_UNUSED; - ipc->channels[ch_index] = NULL; - atomic_dec(&ipc->busy[ch_index]); - /* guarantee that channel resource isn't used in irq handler */ - while (atomic_read(&ipc->busy[ch_index])) - ; - - kfree(ch); - - return rval; - } - - /* open msg might be got before */ - if (ipc->states[ch_index] == CHAN_STATE_CLIENT_OPENED) - goto open_done; - - ipc->states[ch_index] = CHAN_STATE_HOST_OPENED; - - do { - smsg_set(&mrecv, channel, 0, 0, 0); - rval = smsg_recv(dst, &mrecv, timeout); - if (rval != 0) { - pr_err("%s: channel %d-%d smsg receive error = %d!\n", - __func__, dst, channel, rval); - ipc->states[ch_index] = CHAN_STATE_UNUSED; - ipc->channels[ch_index] = NULL; - atomic_dec(&ipc->busy[ch_index]); - /* guarantee that channel resource isn't used - * in irq handler - */ - while (atomic_read(&ipc->busy[ch_index])) - ; - - kfree(ch); - return rval; - } - } while (mrecv.type != SMSG_TYPE_OPEN || mrecv.flag != SMSG_OPEN_MAGIC); - - pr_info("%s: channel %d-%d receive open msg!\n", - __func__, dst, channel); - -open_done: - pr_info("%s: channel %d-%d success\n", __func__, dst, channel); - ipc->states[ch_index] = CHAN_STATE_OPENED; - atomic_dec(&ipc->busy[ch_index]); - - return 0; -} -EXPORT_SYMBOL_GPL(smsg_ch_open); - -int smsg_ch_close(u8 dst, u8 channel, int timeout) -{ - struct smsg_ipc *ipc = smsg_ipcs[dst]; - struct smsg_channel *ch; - struct smsg mclose; - u8 ch_index; - - ch_index = channel2index[channel]; - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - ch = ipc->channels[ch_index]; - if (!ch) - return 0; - - smsg_set(&mclose, channel, SMSG_TYPE_CLOSE, SMSG_CLOSE_MAGIC, 0); - smsg_send(dst, &mclose, timeout); - - ipc->states[ch_index] = CHAN_STATE_FREE; - wake_up_interruptible_all(&ch->rxwait); - - /* wait for the channel being unused */ - while (atomic_read(&ipc->busy[ch_index])) - ; - - /* maybe channel has been free for smsg_ch_open failed */ - if (ipc->channels[ch_index]) { - ipc->channels[ch_index] = NULL; - /* guarantee that channel resource isn't used in irq handler */ - while (atomic_read(&ipc->busy[ch_index])) - ; - sprd_pms_destroy(ch->rx_pms); - sprd_pms_destroy(ch->tx_pms); - kfree(ch); - } - - /* finally, update the channel state*/ - ipc->states[ch_index] = CHAN_STATE_UNUSED; - - return 0; -} -EXPORT_SYMBOL_GPL(smsg_ch_close); - -static void smsg_bl_cpoy_msg(struct smsg *dst, struct smsg *src) -{ - dst->channel = src->channel; - dst->type = src->type; - BL_SETW(dst->flag, src->flag); - BL_SETL(dst->value, src->value); -} - -int smsg_senddie(u8 dst) -{ - struct smsg msg; - struct smsg_ipc *ipc = smsg_ipcs[dst]; - uintptr_t txpos; - int rval = 0; - - if (!ipc) - return -ENODEV; - - msg.channel = SMSG_CH_CTRL; - msg.type = SMSG_TYPE_DIE; - msg.flag = 0; - msg.value = 0; - -#ifdef CONFIG_SPRD_MAILBOX - if (ipc->type == SIPC_BASE_MBOX) { - mbox_just_sent(ipc->core_id, *((u64 *)&msg)); - return 0; - } -#endif - - if (ipc->ring_base) { - /* must wait resource before read or write share memory */ - rval = sprd_pms_request_resource(ipc->sipc_pms, 0); - if (rval < 0) - return rval; - - if (((int)(BL_READL(ipc->txbuf_wrptr) - - BL_READL(ipc->txbuf_rdptr)) >= - ipc->txbuf_size)) { - pr_info("%s: smsg txbuf is full!\n", __func__); - rval = -EBUSY; - } else { - /* calc txpos and write smsg */ - txpos = (BL_READL(ipc->txbuf_wrptr) & - (ipc->txbuf_size - 1)) * - sizeof(struct smsg) + ipc->txbuf_addr; - smsg_bl_cpoy_msg((void *)txpos, &msg); - - /* update wrptr */ - BL_WRITEL(BL_READL(ipc->txbuf_wrptr) + 1, - ipc->txbuf_wrptr); - } - ipc->txirq_trigger(ipc->dst, *((u64 *)&msg)); - sprd_pms_release_resource(ipc->sipc_pms); - } - - return rval; -} -EXPORT_SYMBOL_GPL(smsg_senddie); - -int smsg_send(u8 dst, struct smsg *msg, int timeout) -{ - struct smsg_ipc *ipc = smsg_ipcs[dst]; - struct smsg_channel *ch; - uintptr_t txpos; - int rval = 0; - unsigned long flags; - u8 ch_index; - - ch_index = channel2index[msg->channel]; - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, msg->channel); - return -EINVAL; - } - - if (!ipc) - return -ENODEV; - - if (!ipc->channels[ch_index]) { - pr_err("%s: channel %d not inited!\n", __func__, msg->channel); - return -ENODEV; - } - - if (ipc->states[ch_index] != CHAN_STATE_OPENED && - msg->type != SMSG_TYPE_OPEN && - msg->type != SMSG_TYPE_CLOSE) { - pr_err("%s: channel %d not opened!\n", __func__, msg->channel); - return -EINVAL; - } - - ch = ipc->channels[ch_index]; - - pr_debug("send smsg: channel=%d, type=%d, flag=0x%04x, value=0x%08x\n", - msg->channel, msg->type, msg->flag, msg->value); - - /* - * Must wait resource before read or write share memory, - * and must wait resource before trigger irq, - * And it must before if (ipc->ring_base), - * because it be inited as the same time as resource ready. - */ - rval = sprd_pms_request_resource(ch->tx_pms, timeout); - if (rval < 0) - return rval; - - if (ipc->ring_base) { - spin_lock_irqsave(&ipc->txpinlock, flags); - if (((int)(BL_READL(ipc->txbuf_wrptr) - - BL_READL(ipc->txbuf_rdptr)) >= - ipc->txbuf_size)) { - pr_err("write smsg: txbuf full, wrptr=0x%x, rdptr=0x%x\n", - BL_READL(ipc->txbuf_wrptr), - BL_READL(ipc->txbuf_rdptr)); - rval = -EBUSY; - } else { - /* calc txpos and write smsg */ - txpos = (BL_READL(ipc->txbuf_wrptr) & - (ipc->txbuf_size - 1)) * - sizeof(struct smsg) + ipc->txbuf_addr; - smsg_bl_cpoy_msg((void *)txpos, msg); - - /* update wrptr */ - BL_WRITEL(BL_READL(ipc->txbuf_wrptr) + 1, - ipc->txbuf_wrptr); - } - spin_unlock_irqrestore(&ipc->txpinlock, flags); - } else if (ipc->type != SIPC_BASE_MBOX) { - pr_err("send smsg:ring_base is NULL"); - sprd_pms_release_resource(ch->tx_pms); - return -EINVAL; - } - - ipc->txirq_trigger(ipc->dst, *(u64 *)msg); - sprd_pms_release_resource(ch->tx_pms); - - return rval; -} -EXPORT_SYMBOL_GPL(smsg_send); - -int smsg_recv(u8 dst, struct smsg *msg, int timeout) -{ - struct smsg_ipc *ipc = smsg_ipcs[dst]; - struct smsg_channel *ch; - u32 rd; - int rval = 0; - u8 ch_index; - - ch_index = channel2index[msg->channel]; - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, msg->channel); - return -EINVAL; - } - - if (!ipc) - return -ENODEV; - - atomic_inc(&ipc->busy[ch_index]); - - ch = ipc->channels[ch_index]; - - if (!ch) { - pr_err("%s: channel %d not opened!\n", __func__, msg->channel); - atomic_dec(&ipc->busy[ch_index]); - return -ENODEV; - } - - pr_debug("%s: dst=%d, channel=%d, timeout=%d, ch_index = %d\n", - __func__, dst, msg->channel, timeout, ch_index); - - if (timeout == 0) { - if (!mutex_trylock(&ch->rxlock)) { - pr_err("dst=%d, channel=%d recv smsg busy!\n", - dst, msg->channel); - atomic_dec(&ipc->busy[ch_index]); - - return -EBUSY; - } - - /* no wait */ - if (SIPC_READL(ch->wrptr) == SIPC_READL(ch->rdptr)) { - pr_info("dst=%d, channel=%d smsg rx cache is empty!\n", - dst, msg->channel); - - rval = -ENODATA; - - goto recv_failed; - } - } else if (timeout < 0) { - mutex_lock_interruptible(&ch->rxlock); - /* wait forever */ - rval = wait_event_interruptible( - ch->rxwait, - (SIPC_READL(ch->wrptr) != - SIPC_READL(ch->rdptr)) || - (ipc->states[ch_index] == CHAN_STATE_FREE)); - if (rval < 0) { - pr_debug("%s: dst=%d, channel=%d wait interrupted!\n", - __func__, dst, msg->channel); - - goto recv_failed; - } - - if (ipc->states[ch_index] == CHAN_STATE_FREE) { - pr_info("%s: dst=%d, channel=%d channel is free!\n", - __func__, dst, msg->channel); - - rval = -EIO; - - goto recv_failed; - } - } else { - mutex_lock_interruptible(&ch->rxlock); - /* wait timeout */ - rval = wait_event_interruptible_timeout( - ch->rxwait, - (SIPC_READL(ch->wrptr) != SIPC_READL(ch->rdptr)) || - (ipc->states[ch_index] == CHAN_STATE_FREE), - timeout); - if (rval < 0) { - pr_debug("%s: dst=%d, channel=%d wait interrupted!\n", - __func__, dst, msg->channel); - - goto recv_failed; - } else if (rval == 0) { - pr_debug("%s: dst=%d, channel=%d wait timeout!\n", - __func__, dst, msg->channel); - - rval = -ETIME; - - goto recv_failed; - } - - if (ipc->states[ch_index] == CHAN_STATE_FREE) { - pr_info("%s: dst=%d, channel=%d channel is free!\n", - __func__, dst, msg->channel); - - rval = -EIO; - - goto recv_failed; - } - } - - /* read smsg from cache */ - rd = SIPC_READL(ch->rdptr) & (SMSG_CACHE_NR - 1); - memcpy(msg, &ch->caches[rd], sizeof(struct smsg)); - SIPC_WRITEL(SIPC_READL(ch->rdptr) + 1, ch->rdptr); - - if (ipc->ring_base) - pr_debug("read smsg: dst=%d, channel=%d, wrptr=%d, rdptr=%d, rd=%d\n", - dst, - msg->channel, - SIPC_READL(ch->wrptr), - SIPC_READL(ch->rdptr), - rd); - - pr_debug("recv smsg: dst=%d, channel=%d, type=%d, flag=0x%04x, value=0x%08x, rval = %d\n", - dst, msg->channel, msg->type, msg->flag, msg->value, rval); - -recv_failed: - mutex_unlock(&ch->rxlock); - atomic_dec(&ipc->busy[ch_index]); - return rval; -} -EXPORT_SYMBOL_GPL(smsg_recv); - -u8 sipc_channel2index(u8 channel) -{ - return channel2index[channel]; -} -EXPORT_SYMBOL_GPL(sipc_channel2index); - -#if defined(CONFIG_DEBUG_FS) -static int smsg_debug_show(struct seq_file *m, void *private) -{ - struct smsg_ipc *ipc = NULL; - struct smsg_channel *ch; - - int i, j, cnt; - - for (i = 0; i < SIPC_ID_NR; i++) { - ipc = smsg_ipcs[i]; - if (!ipc) - continue; - - sipc_debug_putline(m, '*', 120); - seq_printf(m, "sipc: %s:\n", ipc->name); - seq_printf(m, "dst: 0x%0x, irq: 0x%0x\n", - ipc->dst, ipc->irq); - if (ipc->ring_base) { - /* - * must wait resource before - * read or write share memory. - */ - if (sipc_smem_request_resource(ipc->sipc_pms, - ipc->dst, 1000) < 0) - continue; - - seq_printf(m, "txbufAddr: 0x%p, txbufsize: 0x%x, txbufrdptr: [0x%p]=%d, txbufwrptr: [0x%p]=%d\n", - (void *)ipc->txbuf_addr, - ipc->txbuf_size, - (void *)ipc->txbuf_rdptr, - BL_READL(ipc->txbuf_rdptr), - (void *)ipc->txbuf_wrptr, - BL_READL(ipc->txbuf_wrptr)); - seq_printf(m, "rxbufAddr: 0x%p, rxbufsize: 0x%x, rxbufrdptr: [0x%p]=%d, rxbufwrptr: [0x%p]=%d\n", - (void *)ipc->rxbuf_addr, - ipc->rxbuf_size, - (void *)ipc->rxbuf_rdptr, - BL_READL(ipc->rxbuf_rdptr), - (void *)ipc->rxbuf_wrptr, - BL_READL(ipc->rxbuf_wrptr)); - - /* release resource */ - sipc_smem_release_resource(ipc->sipc_pms, ipc->dst); - } - sipc_debug_putline(m, '-', 80); - seq_puts(m, "1. all channel state list:\n"); - - for (j = 0; j < SMSG_VALID_CH_NR; j++) - seq_printf(m, - "%2d. channel[%3d] states: %d, name: %s\n", - j, - sipc_cfg[j].channel, - ipc->states[j], - sipc_cfg[j].name); - - sipc_debug_putline(m, '-', 80); - seq_puts(m, "2. channel rdpt < wrpt list:\n"); - - cnt = 1; - for (j = 0; j < SMSG_VALID_CH_NR; j++) { - ch = ipc->channels[j]; - if (!ch) - continue; - - if (SIPC_READL(ch->rdptr) < SIPC_READL(ch->wrptr)) - seq_printf(m, "%2d. channel[%3d] rd: %d, wt: %d, name: %s\n", - cnt++, - sipc_cfg[j].channel, - SIPC_READL(ch->rdptr), - SIPC_READL(ch->wrptr), - sipc_cfg[j].name); - } - } - return 0; -} - -static int smsg_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, smsg_debug_show, inode->i_private); -} - -static const struct file_operations smsg_debug_fops = { - .open = smsg_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -int smsg_init_debugfs(void *root) -{ - if (!root) - return -ENXIO; - debugfs_create_file("smsg", 0444, - (struct dentry *)root, - NULL, - &smsg_debug_fops); - return 0; -} -EXPORT_SYMBOL_GPL(smsg_init_debugfs); - -#endif /* CONFIG_DEBUG_FS */ - - -MODULE_AUTHOR("Chen Gaopeng"); -MODULE_DESCRIPTION("SIPC/SMSG driver"); -MODULE_LICENSE("GPL v2"); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/spipe.c b/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/spipe.c deleted file mode 100644 index 7fbd7bc83..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/spipe.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Copyright (C) 2018 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sipc.h" -#include "sipc_priv.h" -#include "spipe.h" - -#define SPIPE_NR_BASE_NUM MKDEV(254, 0) -#define SDIAG_NR_BASE_NUM MKDEV(253, 0) -#define STTY_NR_BASE_NUM MKDEV(252, 0) -#define SNV_NR_BASE_NUM MKDEV(251, 0) - -struct spipe_device { - struct spipe_init_data *init; - int major; - int minor; - struct cdev cdev; -}; - -struct spipe_sbuf { - u8 dst; - u8 channel; - u32 bufid; -}; - -static struct class *spipe_class; - -static int spipe_open(struct inode *inode, struct file *filp) -{ - int minor = iminor(filp->f_path.dentry->d_inode); - struct spipe_device *spipe; - struct spipe_sbuf *sbuf; - - spipe = container_of(inode->i_cdev, struct spipe_device, cdev); - if (sbuf_status(spipe->init->dst, spipe->init->channel) != 0) { - printk("spipe %d-%d not ready to open!\n", - spipe->init->dst, spipe->init->channel); - filp->private_data = NULL; - return -ENODEV; - } - - sbuf = kmalloc(sizeof(struct spipe_sbuf), GFP_KERNEL); - if (!sbuf) - return -ENOMEM; - filp->private_data = sbuf; - - sbuf->dst = spipe->init->dst; - sbuf->channel = spipe->init->channel; - sbuf->bufid = minor - spipe->minor; - - return 0; -} - -static int spipe_release(struct inode *inode, struct file *filp) -{ - struct spipe_sbuf *sbuf = filp->private_data; - - kfree(sbuf); - - return 0; -} - -static ssize_t spipe_read(struct file *filp, - char __user *buf, size_t count, loff_t *ppos) -{ - struct spipe_sbuf *sbuf = filp->private_data; - int timeout = -1; - - if (filp->f_flags & O_NONBLOCK) - timeout = 0; - - return sbuf_read(sbuf->dst, sbuf->channel, sbuf->bufid, - (void *)buf, count, timeout); -} - -static ssize_t spipe_write(struct file *filp, - const char __user *buf, size_t count, loff_t *ppos) -{ - struct spipe_sbuf *sbuf = filp->private_data; - int timeout = -1; - - if (filp->f_flags & O_NONBLOCK) - timeout = 0; - - return sbuf_write(sbuf->dst, sbuf->channel, sbuf->bufid, - (void *)buf, count, timeout); -} - -static unsigned int spipe_poll(struct file *filp, poll_table *wait) -{ - struct spipe_sbuf *sbuf = filp->private_data; - - return sbuf_poll_wait(sbuf->dst, sbuf->channel, sbuf->bufid, - filp, wait); -} - -static long spipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - return 0; -} - -static const struct file_operations spipe_fops = { - .open = spipe_open, - .release = spipe_release, - .read = spipe_read, - .write = spipe_write, - .poll = spipe_poll, - .unlocked_ioctl = spipe_ioctl, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -#ifdef SPRD_PCIE_USE_DTS -static int spipe_parse_dt(struct spipe_init_data **init, - struct device_node *np, struct device *dev, dev_t *devid) -{ - struct spipe_init_data *pdata = NULL; - int ret; - u32 data; - - pdata = devm_kzalloc(dev, sizeof(struct spipe_init_data), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - ret = of_property_read_string(np, - "sprd,name", - (const char **)&pdata->name); - if (ret) - goto error; - - if (!strcmp(pdata->name, "spipe_nr")) - *devid = SPIPE_NR_BASE_NUM; - else if (!strcmp(pdata->name, "sdiag_nr")) - *devid = SDIAG_NR_BASE_NUM; - else if (!strcmp(pdata->name, "stty_nr")) - *devid = STTY_NR_BASE_NUM; - else if (!strcmp(pdata->name, "snv_nr")) - *devid = SNV_NR_BASE_NUM; - - ret = of_property_read_u32(np, "sprd,dst", (u32 *)&data); - if (ret) - goto error; - pdata->dst = (u8)data; - - ret = of_property_read_u32(np, "sprd,channel", (u32 *)&data); - if (ret) - goto error; - pdata->channel = (u8)data; - - ret = of_property_read_u32(np, - "sprd,ringnr", - (u32 *)&pdata->ringnr); - if (ret) - goto error; - - ret = of_property_read_u32(np, - "sprd,size-rxbuf", - (u32 *)&pdata->rxbuf_size); - if (ret) - goto error; - - ret = of_property_read_u32(np, - "sprd,size-txbuf", - (u32 *)&pdata->txbuf_size); - if (ret) - goto error; - - *init = pdata; - return ret; -error: - devm_kfree(dev, pdata); - *init = NULL; - return ret; -} -#else -static int spipe_parse_dt(struct spipe_init_data **init, - struct device_node *np, struct device *dev, dev_t *devid) -{ - struct spipe_init_data *pdata = *init; - - if (!strcmp(pdata->name, "spipe_nr")) - *devid = SPIPE_NR_BASE_NUM; - else if (!strcmp(pdata->name, "sdiag_nr")) - *devid = SDIAG_NR_BASE_NUM; - else if (!strcmp(pdata->name, "stty_nr")) - *devid = STTY_NR_BASE_NUM; - else if (!strcmp(pdata->name, "snv_nr")) - *devid = SNV_NR_BASE_NUM; - - return 0; -} -#endif - -static inline void spipe_destroy_pdata(struct spipe_init_data **init, - struct device *dev) -{ - *init = NULL; -} - -static int spipe_probe(struct platform_device *pdev) -{ - struct spipe_init_data *init = pdev->dev.platform_data; - struct spipe_device *spipe; - dev_t devid; - int i, rval; - struct device_node *np; - - printk("%s!\n", __func__); - - if (1) { - np = pdev->dev.of_node; - rval = spipe_parse_dt(&init, np, &pdev->dev, &devid); - if (rval) { - pr_err("Failed to parse spipe device tree, ret=%d\n", rval); - return rval; - } - - printk("spipe: after parse device tree, name=%s, dst=%u, channel=%u, ringnr=%u, rxbuf_size=0x%x, txbuf_size=0x%x\n", - init->name, - init->dst, - init->channel, - init->ringnr, - init->rxbuf_size, - init->txbuf_size); - - rval = sbuf_create(init->dst, init->channel, init->ringnr, - init->txbuf_size, init->rxbuf_size); - if (rval != 0) { - printk("Failed to create sbuf: %d\n", rval); - spipe_destroy_pdata(&init, &pdev->dev); - return rval; - } - - spipe = devm_kzalloc(&pdev->dev, - sizeof(struct spipe_device), - GFP_KERNEL); - if (spipe == NULL) { - sbuf_destroy(init->dst, init->channel); - spipe_destroy_pdata(&init, &pdev->dev); - printk("Failed to allocate spipe_device\n"); - return -ENOMEM; - } - - rval = alloc_chrdev_region(&devid, 0, init->ringnr, init->name); - //rval = register_chrdev_region(devid, init->ringnr, init->name); - if (rval != 0) { - sbuf_destroy(init->dst, init->channel); - devm_kfree(&pdev->dev, spipe); - spipe_destroy_pdata(&init, &pdev->dev); - printk("Failed to alloc spipe chrdev\n"); - return rval; - } - - cdev_init(&(spipe->cdev), &spipe_fops); - rval = cdev_add(&(spipe->cdev), devid, init->ringnr); - if (rval != 0) { - sbuf_destroy(init->dst, init->channel); - devm_kfree(&pdev->dev, spipe); - unregister_chrdev_region(devid, init->ringnr); - spipe_destroy_pdata(&init, &pdev->dev); - printk("Failed to add spipe cdev\n"); - return rval; - } - - spipe->major = MAJOR(devid); - spipe->minor = MINOR(devid); - if (init->ringnr > 1) { - for (i = 0; i < init->ringnr; i++) { - device_create(spipe_class, NULL, - MKDEV(spipe->major, spipe->minor + i), - NULL, "%s%d", init->name, i); - } - } else { - device_create(spipe_class, NULL, - MKDEV(spipe->major, spipe->minor), - NULL, "%s", init->name); - } - - spipe->init = init; - - platform_set_drvdata(pdev, spipe); - } - - return 0; -} - -static int spipe_remove(struct platform_device *pdev) -{ - struct spipe_device *spipe = platform_get_drvdata(pdev); - int i; - - if (spipe) { - for (i = 0; i < spipe->init->ringnr; i++) { - device_destroy(spipe_class, MKDEV(spipe->major, spipe->minor + i)); - } - cdev_del(&(spipe->cdev)); - unregister_chrdev_region(MKDEV(spipe->major, spipe->minor), spipe->init->ringnr); - - sbuf_destroy(spipe->init->dst, spipe->init->channel); - - spipe_destroy_pdata(&spipe->init, &pdev->dev); - - devm_kfree(&pdev->dev, spipe); - - platform_set_drvdata(pdev, NULL); - } - - return 0; -} - -#ifdef SPRD_PCIE_USE_DTS -static const struct of_device_id spipe_match_table[] = { - {.compatible = "sprd,spipe", }, - { }, -}; -#endif - -static struct platform_driver spipe_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "spipe", -#ifdef SPRD_PCIE_USE_DTS - .of_match_table = spipe_match_table, -#endif - }, - .probe = spipe_probe, - .remove = spipe_remove, -}; - -static struct platform_device *spipe_pdev[MAX_SPIPE_CHN_NUM]; -static struct spipe_init_data spipe_data[MAX_SPIPE_CHN_NUM] = { - { - .sipc_name = SPIPE_DRVIER_NMAE, - .name = "spipe_nr", - .dst = 1, - .channel = 4, - .ringnr = 15, - .txbuf_size = 0x1000, - .rxbuf_size = 0x1000 - }, - { - .sipc_name = SPIPE_DRVIER_NMAE, - .name = "sdiag_nr", - .dst = 1, - .channel = 21, - .ringnr = 1, - .txbuf_size = 0x40000, - .rxbuf_size = 0x8000 - }, - { - .sipc_name = SPIPE_DRVIER_NMAE, - .name = "stty_nr", - .dst = 1, - .channel = 6, - .ringnr = 32, - .txbuf_size = 0x0800, - .rxbuf_size = 0x0800 - }, - { - .sipc_name = SPIPE_DRVIER_NMAE, - .name = "snv_nr", - .dst = 1, - .channel = 40, - .ringnr = 1, - .txbuf_size = 0x40400, - .rxbuf_size = 0x1000 - } - -}; - -static int spipe_platform_device_reigster(void) -{ - int retval = -ENOMEM; - int i; - - for(i = 0; i < MAX_SPIPE_CHN_NUM; i++) { - spipe_pdev[i] = platform_device_alloc(SPIPE_DRVIER_NMAE, i); - if (!spipe_pdev[i]) { - i--; - while (i >= 0) - platform_device_put(spipe_pdev[i--]); - return retval; - } - } - - for (i = 0; i < MAX_SPIPE_CHN_NUM; i++) { - retval = platform_device_add_data(spipe_pdev[i], &spipe_data[i], - sizeof(struct spipe_init_data)); - if (retval) - goto err_add_pdata; - } - - for (i = 0; i < MAX_SPIPE_CHN_NUM; i++) { - retval = platform_device_add(spipe_pdev[i]); - if (retval < 0) { - i--; - while (i >= 0) - platform_device_del(spipe_pdev[i]); - goto err_add_pdata; - } - } - - return retval; - -err_add_pdata: - for (i = 0; i < MAX_SPIPE_CHN_NUM; i++) - platform_device_put(spipe_pdev[i]); - return retval; -} - -static void spipe_platform_device_unreigster(void) -{ - int i; - for (i = 0; i < MAX_SPIPE_CHN_NUM; i++) { - platform_device_unregister(spipe_pdev[i]); - } -} - - -int spipe_init(void) -{ - int ret; - - spipe_class = class_create(THIS_MODULE, "spipe"); - if (IS_ERR(spipe_class)) - return PTR_ERR(spipe_class); -#ifndef SPRD_PCIE_USE_DTS - if((ret = spipe_platform_device_reigster())) - return ret; -#endif - - if((ret = platform_driver_register(&spipe_driver))) { -#ifndef SPRD_PCIE_USE_DTS - spipe_platform_device_unreigster(); -#endif - return ret; - } - return ret; -} -EXPORT_SYMBOL_GPL(spipe_init); - -void spipe_exit(void) -{ - platform_driver_unregister(&spipe_driver); -#ifndef SPRD_PCIE_USE_DTS - spipe_platform_device_unreigster(); -#endif - class_destroy(spipe_class); -} - -void spipe_device_down(void) -{ - int retval = -ENOMEM; - int i; - - for(i = 0; i < MAX_SPIPE_CHN_NUM; i++) { - sbuf_down(spipe_data[i].dst, spipe_data[i].channel); - } -} - -EXPORT_SYMBOL_GPL(spipe_exit); -EXPORT_SYMBOL_GPL(spipe_device_down); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/spipe.h b/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/spipe.h deleted file mode 100644 index eacca6c67..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/spipe.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#ifndef __SPIPE_H -#define __SPIPE_H - -#define MAX_SPIPE_CHN_NUM 4 -#define SPIPE_DRVIER_NMAE "spipe" - -struct spipe_init_data { - char *name; - char *sipc_name; - u8 dst; - u8 channel; - u32 ringnr; - u32 txbuf_size; - u32 rxbuf_size; -}; -#endif diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/spool.c b/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/spool.c deleted file mode 100644 index 724dc9648..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/spool.c +++ /dev/null @@ -1,538 +0,0 @@ -/* - * Copyright (C) 2018 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sipc.h" -#include "spool.h" - -#define SLOG_NR_BASE_NUM MKDEV(156, 0) - -struct spool_device; - -struct spool_device { - struct spool_init_data *init; - int major; - int minor; - struct cdev cdev; - struct platform_device *plt_dev; - - struct device *sys_dev; /* Device object in sysfs */ -}; - -struct spool_sblock { - u8 dst; - u8 channel; - bool is_hold; - struct sblock hold; -}; - -static struct class *spool_class; - -static int spool_open(struct inode *inode, struct file *filp) -{ - struct spool_device *spool; - struct spool_sblock *sblock; - int ret; - - spool = container_of(inode->i_cdev, struct spool_device, cdev); - ret = sblock_query(spool->init->dst, spool->init->channel); - if (ret) - return ret; - sblock = kmalloc(sizeof(struct spool_sblock), GFP_KERNEL); - if (!sblock) - return -ENOMEM; - filp->private_data = sblock; - - sblock->dst = spool->init->dst; - sblock->channel = spool->init->channel; - sblock->is_hold = 0; - - return 0; -} - -static int spool_release(struct inode *inode, struct file *filp) -{ - struct spool_sblock *sblock = filp->private_data; - - if (sblock->is_hold) { - if (sblock_release(sblock->dst, sblock->channel, &sblock->hold)) - pr_debug("failed to release block!\n"); - } - kfree(sblock); - - return 0; -} - -static ssize_t spool_read(struct file *filp, - char __user *buf, size_t count, loff_t *ppos) -{ - struct spool_sblock *sblock = filp->private_data; - int timeout = -1; - int ret = 0; - int rdsize = 0; - struct sblock blk = {0}; - - if (filp->f_flags & O_NONBLOCK) - timeout = 0; - - if (sblock->is_hold) { - if (count < sblock->hold.length - *ppos) { - rdsize = count; - } else { - rdsize = sblock->hold.length - *ppos; - sblock->is_hold = 0; - } - blk = sblock->hold; - } else{ - *ppos = 0; - ret = sblock_receive(sblock->dst, - sblock->channel, &blk, timeout); - if (ret < 0) { - pr_debug("%s: failed to receive block!\n", __func__); - return ret; - } - if (blk.length <= count) - rdsize = blk.length; - else { - rdsize = count; - sblock->is_hold = 1; - sblock->hold = blk; - } - } - - if (unalign_copy_to_user(buf, blk.addr + *ppos, rdsize)) { - pr_err("%s: failed to copy to user!\n", __func__); - sblock->is_hold = 0; - *ppos = 0; - ret = -EFAULT; - } else { - ret = rdsize; - *ppos += rdsize; - } - - if (sblock->is_hold == 0) { - if (sblock_release(sblock->dst, sblock->channel, &blk)) - pr_err("%s: failed to release block!\n", __func__); - } - - return ret; -} - -static ssize_t spool_write(struct file *filp, - const char __user *buf, size_t count, loff_t *ppos) -{ - struct spool_sblock *sblock = filp->private_data; - int timeout = -1; - int ret = 0; - int wrsize = 0; - int pos = 0; - struct sblock blk = {0}; - size_t len = count; - - if (filp->f_flags & O_NONBLOCK) - timeout = 0; - - do { - ret = sblock_get(sblock->dst, sblock->channel, &blk, timeout); - if (ret < 0) { - pr_info("%s: failed to get block!\n", __func__); - return ret; - } - - wrsize = (blk.length > len ? len : blk.length); - if (unalign_copy_from_user(blk.addr, buf + pos, wrsize)) { - pr_info("%s: failed to copy from user!\n", __func__); - ret = -EFAULT; - } else { - blk.length = wrsize; - len -= wrsize; - pos += wrsize; - } - - if (sblock_send(sblock->dst, sblock->channel, &blk)) - pr_debug("%s: failed to send block!", __func__); - } while (len > 0 && ret == 0); - - return count - len; -} - -static unsigned int spool_poll(struct file *filp, poll_table *wait) -{ - struct spool_sblock *sblock = filp->private_data; - - return sblock_poll_wait(sblock->dst, sblock->channel, filp, wait); -} - -static long spool_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - return 0; -} - -static const struct file_operations spool_fops = { - .open = spool_open, - .release = spool_release, - .read = spool_read, - .write = spool_write, - .poll = spool_poll, - .unlocked_ioctl = spool_ioctl, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -#ifdef SPRD_PCIE_USE_DTS -static int spool_parse_dt(struct spool_init_data **init, struct device *dev, - struct device_node *np, dev_t *dev_no) -{ - struct spool_init_data *pdata = NULL; - int ret; - u32 data; - - pdata = devm_kzalloc(dev, sizeof(struct spool_init_data), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - ret = of_property_read_string(np, "sprd,name", - (const char **)&pdata->name); - if (ret) - goto error; - - if (!strcmp(pdata->name, "slog_nr")) - *dev_no = SLOG_NR_BASE_NUM; - - ret = of_property_read_u32(np, "sprd,dst", (u32 *)&data); - if (ret) - goto error; - pdata->dst = (u8)data; - - ret = of_property_read_u32(np, "sprd,channel", (u32 *)&data); - if (ret) - goto error; - pdata->channel = (u8)data; - - ret = of_property_read_u32(np, "sprd,preconfigured", (u32 *)&data); - if (!ret) - pdata->pre_cfg = (int)data; - - ret = of_property_read_u32(np, "sprd,tx-blksize", - (u32 *)&pdata->txblocksize); - if (ret) - goto error; - ret = of_property_read_u32(np, "sprd,tx-blknum", - (u32 *)&pdata->txblocknum); - if (ret) - goto error; - ret = of_property_read_u32(np, "sprd,rx-blksize", - (u32 *)&pdata->rxblocksize); - if (ret) - goto error; - ret = of_property_read_u32(np, "sprd,rx-blknum", - (u32 *)&pdata->rxblocknum); - if (ret) - goto error; - - if (!of_property_read_u32(np, "sprd,nodev", (u32 *)&data)) - pdata->nodev = (u8)data; - - *init = pdata; - return ret; -error: - devm_kfree(dev, pdata); - *init = NULL; - return ret; -} -#else -static int spool_parse_dt(struct spool_init_data **init, struct device *dev, - struct device_node *np, dev_t *dev_no) -{ - struct spool_init_data *pdata = NULL; - - pdata = devm_kzalloc(dev, sizeof(struct spool_init_data), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - pdata->name = "slog_nr"; - if (!strcmp(pdata->name, "slog_nr")) - *dev_no = SLOG_NR_BASE_NUM; - pdata->dst = 1; - pdata->channel = 5; - pdata->txblocksize = 0; - pdata->txblocknum = 0; - pdata->rxblocksize = 0x10000; - pdata->rxblocknum = 32; - *init = pdata; - - return 0; -} -#endif - - -static ssize_t base_addr_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct spool_device *spool = (struct spool_device *) - dev_get_drvdata(dev); - struct spool_init_data *init = spool->init; - uint32_t addr; - int ret; - - ret = sblock_get_smem_cp_addr(init->dst, init->channel, - &addr); - if (ret < 0) - return ret; - - return snprintf(buf, PAGE_SIZE, "%u %u 0x%08X %d %u %u %u %u\n", - (unsigned int)init->dst, - (unsigned int)init->channel, - addr, - init->pre_cfg, - (unsigned int)init->txblocknum, - (unsigned int)init->txblocksize, - (unsigned int)init->rxblocknum, - (unsigned int)init->rxblocksize); -} - -static DEVICE_ATTR(base_addr, 0440, - base_addr_show, NULL); - -static int create_spool(struct platform_device *pdev, - struct spool_init_data *init, - struct spool_device **out, dev_t dev_no) -{ - int rval; - struct spool_device *spool; - //dev_t dev_no; - char sp_name[16]; - - snprintf(sp_name, sizeof(sp_name), "spool-%u-%u", - (unsigned int)init->dst, - (unsigned int)init->channel); - //rval = alloc_chrdev_region(&dev_no, 0, 1, sp_name); - rval = register_chrdev_region(dev_no, 1, sp_name); - if (rval) - return rval; - - if (init->pre_cfg) - rval = sblock_pcfg_create(init->dst, - init->channel, - init->txblocknum, - init->txblocksize, - init->rxblocknum, - init->rxblocksize); - else - rval = sblock_create(init->dst, - init->channel, - init->txblocknum, - init->txblocksize, - init->rxblocknum, - init->rxblocksize); - if (rval) { - pr_info("Failed to create sblock: %d\n", rval); - goto free_devno; - } - - spool = devm_kzalloc(&pdev->dev, - sizeof(struct spool_device), - GFP_KERNEL); - if (!spool) { - pr_info("Failed to allocate spool_device\n"); - rval = -ENOMEM; - goto free_sblock; - } - - spool->init = init; - spool->major = MAJOR(dev_no); - spool->minor = MINOR(dev_no); - spool->plt_dev = pdev; - - if (!init->nodev) { - cdev_init(&spool->cdev, &spool_fops); - - rval = cdev_add(&spool->cdev, dev_no, 1); - if (rval) { - pr_info("Failed to add spool cdev\n"); - goto free_spool; - } - } - - spool->sys_dev = device_create(spool_class, NULL, - dev_no, - spool, "%s", init->name); - device_create_file(&pdev->dev, &dev_attr_base_addr); - - platform_set_drvdata(pdev, spool); - - *out = spool; - - return 0; - -free_spool: - devm_kfree(&pdev->dev, spool); - -free_sblock: - sblock_destroy(init->dst, init->channel); - -free_devno: - unregister_chrdev_region(dev_no, 1); - return rval; -} - -static int destroy_spool(struct spool_device *spool) -{ - dev_t dev_no = MKDEV(spool->major, spool->minor); - struct spool_init_data *init = spool->init; - - if (spool->sys_dev) { - device_destroy(spool_class, dev_no); - spool->sys_dev = NULL; - } - if (!init->nodev) - cdev_del(&spool->cdev); - sblock_destroy(init->dst, init->channel); - unregister_chrdev_region(dev_no, 1); - devm_kfree(&spool->plt_dev->dev, init); - devm_kfree(&spool->plt_dev->dev, spool); - - return 0; -} - -static int spool_probe(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - int rval; - struct spool_init_data *init; - struct spool_device *spool; - dev_t dev_no; - -#ifdef SPRD_PCIE_USE_DTS - if (!np) - return -ENODEV; -#endif - - rval = spool_parse_dt(&init, &pdev->dev, np, &dev_no); - if (rval) { - pr_err("Failed to parse spool device tree, ret=%d\n", - rval); - return rval; - } - - pr_info("spool: name=%s, dst=%u, channel=%u, pre_cfg=%u\n", - init->name, - init->dst, - init->channel, - init->pre_cfg); - - pr_info("spool: tx_num=%u, tx_size=%u, rx_num=%u, rx_size=%u\n", - init->txblocknum, - init->txblocksize, - init->rxblocknum, - init->rxblocksize); - - rval = create_spool(pdev, init, &spool, dev_no); - if (rval) { - pr_err("Failed to create spool device %u:%u, ret=%d\n", - (unsigned int)init->dst, - (unsigned int)init->channel, rval); - devm_kfree(&pdev->dev, init); - } - - return 0; -} - -static int spool_remove(struct platform_device *pdev) -{ - struct spool_device *priv = (struct spool_device *) - platform_get_drvdata(pdev); - - destroy_spool(priv); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -#ifdef SPRD_PCIE_USE_DTS -static const struct of_device_id spool_match_table[] = { - { .compatible = "sprd,spool", }, - { }, -}; -#endif - -static struct platform_driver spool_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "spool", -#ifdef SPRD_PCIE_USE_DTS - .of_match_table = spool_match_table, -#endif - }, - .probe = spool_probe, - .remove = spool_remove, -}; - -#ifndef SPRD_PCIE_USE_DTS -static void spool_platform_device_release(struct device *dev) {} -static struct platform_device spool_device = { - .name = "spool", - .id = -1, - .dev = { - .release = spool_platform_device_release, - } -}; -#endif - -int spool_init(void) -{ - int ret; - - spool_class = class_create(THIS_MODULE, "spool"); - if (IS_ERR(spool_class)) - return PTR_ERR(spool_class); -#ifndef SPRD_PCIE_USE_DTS - if((ret = platform_device_register(&spool_device))) - return ret; -#endif - if((ret = platform_driver_register(&spool_driver))) { -#ifndef SPRD_PCIE_USE_DTS - platform_device_unregister(&spool_device); -#endif - return ret; - } - - return ret; -} -EXPORT_SYMBOL_GPL(spool_init); - -void spool_exit(void) -{ - platform_driver_unregister(&spool_driver); -#ifndef SPRD_PCIE_USE_DTS - platform_device_unregister(&spool_device); -#endif - class_destroy(spool_class); -} - - -void spool_device_down(void) -{ - sblock_down(1, 5); -} - -EXPORT_SYMBOL_GPL(spool_exit); -EXPORT_SYMBOL_GPL(spool_device_down); diff --git a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/spool.h b/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/spool.h deleted file mode 100644 index c0c5d2eeb..000000000 --- a/package/wwan/driver/quectel_SRPD_PCIE/src/sipc/spool.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 the - * GNU General Public License for more details. - */ - -#ifndef __SPOOL_H -#define __SPOOL_H - -struct spool_init_data { - char *name; - u8 dst; - u8 channel; - u8 nodev; - /* Preconfigured channel */ - int pre_cfg; - u32 txblocknum; - u32 txblocksize; - u32 rxblocknum; - u32 rxblocksize; -}; -#endif