sm8750: init kernel modules repo
This commit is contained in:
4
qcom/opensource/data-kernel/data_dlkm_vendor_board.mk
Normal file
4
qcom/opensource/data-kernel/data_dlkm_vendor_board.mk
Normal file
@@ -0,0 +1,4 @@
|
||||
SMEM_MAILBOX_DLKM_BOARD_PLATFORMS_LIST := sun
|
||||
ifneq (,$(call is-board-platform-in-list2,$(SMEM_MAILBOX_DLKM_BOARD_PLATFORMS_LIST)))
|
||||
BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/smem-mailbox.ko
|
||||
endif
|
3
qcom/opensource/data-kernel/data_dlkm_vendor_product.mk
Normal file
3
qcom/opensource/data-kernel/data_dlkm_vendor_product.mk
Normal file
@@ -0,0 +1,3 @@
|
||||
ifeq ($(TARGET_BOARD_PLATFORM), sun)
|
||||
PRODUCT_PACKAGES += smem-mailbox.ko
|
||||
endif
|
1
qcom/opensource/data-kernel/drivers/Android.mk
Normal file
1
qcom/opensource/data-kernel/drivers/Android.mk
Normal file
@@ -0,0 +1 @@
|
||||
include $(call all-subdir-makefiles)
|
37
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/Android.mk
Normal file
37
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/Android.mk
Normal file
@@ -0,0 +1,37 @@
|
||||
#This makefile is only to compile EMAC for AUTO platform
|
||||
|
||||
ifeq ($(TARGET_BOARD_AUTO),true)
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
# This makefile is only for DLKM
|
||||
ifneq ($(findstring vendor,$(LOCAL_PATH)),)
|
||||
|
||||
ifneq ($(findstring opensource,$(LOCAL_PATH)),)
|
||||
EMAC_BLD_DIR := ../../vendor/qcom/opensource/data-kernel/drivers/emac-dwc-eqos
|
||||
endif # opensource
|
||||
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
|
||||
DLKM_DIR := ./device/qcom/common/dlkm
|
||||
KBUILD_OPTIONS := $(EMAC_BLD_DIR)
|
||||
KBUILD_OPTIONS += DCONFIG_PTPSUPPORT_OBJ=1
|
||||
KBUILD_OPTIONS += DCONFIG_DEBUGFS_OBJ=1
|
||||
#KBUILD_OPTIONS += DDWC_ETH_QOS_TEST=1
|
||||
|
||||
LOCAL_MODULE := emac_dwc_eqos.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := emac_perf_settings.sh
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_CLASS := ETC
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/emac
|
||||
LOCAL_SRC_FILES := emac_perf_settings.sh
|
||||
include $(BUILD_PREBUILT)
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@@ -0,0 +1,50 @@
|
||||
/* Copyright (c) 2017, 2019, 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 <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/if.h>
|
||||
|
||||
#include <linux/inetdevice.h>
|
||||
#include <net/addrconf.h>
|
||||
#include <linux/inet.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#define EMAC_DRV_NAME "qcom-emac-dwc-eqos"
|
||||
|
||||
static int __init DWC_ETH_QOS_app_init (void)
|
||||
{
|
||||
struct net_device *dev;
|
||||
rtnl_lock();
|
||||
for_each_netdev(&init_net, dev) {
|
||||
if(strncmp (EMAC_DRV_NAME, netdev_drivername(dev), strlen(EMAC_DRV_NAME)) == 0)
|
||||
if (dev_change_flags(dev, dev->flags | IFF_UP) < 0)
|
||||
pr_err("EMAC_DRV_NAME:DWC_ETH_QOS_app_init: Failed to open %s\n", dev->name);
|
||||
}
|
||||
rtnl_unlock();
|
||||
|
||||
pr_info("Call DWC_ETH_QOS_open function for test purpose\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void __exit DWC_ETH_QOS_app_cleanup (void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
module_init(DWC_ETH_QOS_app_init);
|
||||
module_exit(DWC_ETH_QOS_app_cleanup);
|
1922
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/DWC_ETH_QOS_desc.c
Normal file
1922
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/DWC_ETH_QOS_desc.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,102 @@
|
||||
/* Copyright (c) 2017, 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.
|
||||
*
|
||||
* This file contain content copied from Synopsis driver,
|
||||
* provided under the license below
|
||||
*/
|
||||
/* =========================================================================
|
||||
* The Synopsys DWC ETHER QOS Software Driver and documentation (hereinafter
|
||||
* "Software") is an unsupported proprietary work of Synopsys, Inc. unless
|
||||
* otherwise expressly agreed to in writing between Synopsys and you.
|
||||
*
|
||||
* The Software IS NOT an item of Licensed Software or Licensed Product under
|
||||
* any End User Software License Agreement or Agreement for Licensed Product
|
||||
* with Synopsys or any supplement thereto. Permission is hereby granted,
|
||||
* free of charge, to any person obtaining a copy of this software annotated
|
||||
* with this license and the Software, to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject
|
||||
* to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* =========================================================================
|
||||
*/
|
||||
|
||||
#ifndef __DWC_ETH_QOS_DESC_H__
|
||||
|
||||
#define __DWC_ETH_QOS_DESC_H__
|
||||
|
||||
static INT allocate_buffer_and_desc(struct DWC_ETH_QOS_prv_data *);
|
||||
|
||||
static void DWC_ETH_QOS_wrapper_tx_descriptor_init(struct DWC_ETH_QOS_prv_data
|
||||
*pdata);
|
||||
|
||||
static void DWC_ETH_QOS_wrapper_tx_descriptor_init_single_q(
|
||||
struct DWC_ETH_QOS_prv_data *pdata, UINT);
|
||||
|
||||
static void DWC_ETH_QOS_wrapper_rx_descriptor_init(struct DWC_ETH_QOS_prv_data
|
||||
*pdata);
|
||||
|
||||
static void DWC_ETH_QOS_wrapper_rx_descriptor_init_single_q(
|
||||
struct DWC_ETH_QOS_prv_data *pdata, UINT);
|
||||
|
||||
#ifdef DWC_INET_LRO
|
||||
static int DWC_ETH_QOS_get_skb_hdr(struct sk_buff *skb, void **iphdr,
|
||||
void **tcph, u64 *hdr_flags, void *priv);
|
||||
#endif
|
||||
|
||||
static void DWC_ETH_QOS_tx_free_mem(struct DWC_ETH_QOS_prv_data *);
|
||||
|
||||
static void DWC_ETH_QOS_rx_free_mem(struct DWC_ETH_QOS_prv_data *);
|
||||
|
||||
static unsigned int DWC_ETH_QOS_map_skb(struct net_device *, struct sk_buff *);
|
||||
|
||||
static void DWC_ETH_QOS_unmap_tx_skb(struct DWC_ETH_QOS_prv_data *,
|
||||
struct DWC_ETH_QOS_tx_buffer *);
|
||||
|
||||
static void DWC_ETH_QOS_unmap_rx_skb(struct DWC_ETH_QOS_prv_data *,
|
||||
struct DWC_ETH_QOS_rx_buffer *);
|
||||
|
||||
static void DWC_ETH_QOS_re_alloc_skb(
|
||||
struct DWC_ETH_QOS_prv_data *pdata, UINT);
|
||||
|
||||
static void DWC_ETH_QOS_tx_desc_free_mem(struct DWC_ETH_QOS_prv_data *pdata,
|
||||
UINT tx_q_cnt);
|
||||
|
||||
static void DWC_ETH_QOS_tx_buf_free_mem(struct DWC_ETH_QOS_prv_data *pdata,
|
||||
UINT tx_q_cnt);
|
||||
|
||||
static void DWC_ETH_QOS_rx_desc_free_mem(struct DWC_ETH_QOS_prv_data *pdata,
|
||||
UINT rx_q_cnt);
|
||||
|
||||
static void DWC_ETH_QOS_rx_buf_free_mem(struct DWC_ETH_QOS_prv_data *pdata,
|
||||
UINT rx_q_cnt);
|
||||
|
||||
static void DWC_ETH_QOS_rx_skb_free_mem(
|
||||
struct DWC_ETH_QOS_prv_data *pdata, UINT);
|
||||
|
||||
static void DWC_ETH_QOS_tx_skb_free_mem(struct DWC_ETH_QOS_prv_data *pdata,
|
||||
UINT);
|
||||
#endif
|
5240
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c
Normal file
5240
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c
Normal file
File diff suppressed because it is too large
Load Diff
8165
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c
Normal file
8165
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,155 @@
|
||||
/* Copyright (c) 2017, 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.
|
||||
*
|
||||
* This file contain content copied from Synopsis driver,
|
||||
* provided under the license below
|
||||
*/
|
||||
/* =========================================================================
|
||||
* The Synopsys DWC ETHER QOS Software Driver and documentation (hereinafter
|
||||
* "Software") is an unsupported proprietary work of Synopsys, Inc. unless
|
||||
* otherwise expressly agreed to in writing between Synopsys and you.
|
||||
*
|
||||
* The Software IS NOT an item of Licensed Software or Licensed Product under
|
||||
* any End User Software License Agreement or Agreement for Licensed Product
|
||||
* with Synopsys or any supplement thereto. Permission is hereby granted,
|
||||
* free of charge, to any person obtaining a copy of this software annotated
|
||||
* with this license and the Software, to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject
|
||||
* to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* =========================================================================
|
||||
*/
|
||||
|
||||
#ifndef __DWC_ETH_QOS_DRV_H__
|
||||
|
||||
#define __DWC_ETH_QOS_DRV_H__
|
||||
|
||||
static int DWC_ETH_QOS_open(struct net_device *);
|
||||
|
||||
static int DWC_ETH_QOS_close(struct net_device *);
|
||||
|
||||
static void DWC_ETH_QOS_set_rx_mode(struct net_device *);
|
||||
|
||||
static int DWC_ETH_QOS_start_xmit(struct sk_buff *, struct net_device *);
|
||||
|
||||
static void DWC_ETH_QOS_tx_interrupt(struct net_device *,
|
||||
struct DWC_ETH_QOS_prv_data *, UINT);
|
||||
|
||||
static struct net_device_stats *DWC_ETH_QOS_get_stats(struct net_device *);
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
static void DWC_ETH_QOS_poll_controller(struct net_device *);
|
||||
#endif /*end of CONFIG_NET_POLL_CONTROLLER */
|
||||
|
||||
static int DWC_ETH_QOS_set_features(
|
||||
struct net_device *dev, netdev_features_t features);
|
||||
|
||||
static netdev_features_t DWC_ETH_QOS_fix_features(
|
||||
struct net_device *dev, netdev_features_t features);
|
||||
|
||||
INT DWC_ETH_QOS_configure_remotewakeup(struct net_device *dev,
|
||||
struct ifr_data_struct *req);
|
||||
|
||||
static void DWC_ETH_QOS_program_dcb_algorithm(
|
||||
struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data_struct *req);
|
||||
|
||||
static void DWC_ETH_QOS_program_avb_algorithm(
|
||||
struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data_struct *req);
|
||||
|
||||
static void DWC_ETH_QOS_config_tx_pbl(struct DWC_ETH_QOS_prv_data *pdata,
|
||||
UINT tx_pbl, UINT ch_no);
|
||||
static void DWC_ETH_QOS_config_rx_pbl(struct DWC_ETH_QOS_prv_data *pdata,
|
||||
UINT rx_pbl, UINT ch_no);
|
||||
|
||||
static int DWC_ETH_QOS_handle_prv_ioctl(struct DWC_ETH_QOS_prv_data *pdata,
|
||||
struct ifr_data_struct *req);
|
||||
|
||||
static int DWC_ETH_QOS_handle_prv_ioctl_ipa(struct DWC_ETH_QOS_prv_data *pdata,
|
||||
struct ifreq *ifr);
|
||||
|
||||
static int DWC_ETH_QOS_ioctl(struct net_device *, struct ifreq *, int);
|
||||
|
||||
static INT DWC_ETH_QOS_change_mtu(struct net_device *dev, INT new_mtu);
|
||||
|
||||
static int DWC_ETH_QOS_clean_split_hdr_rx_irq(
|
||||
struct DWC_ETH_QOS_prv_data *pdata, int quota, UINT);
|
||||
|
||||
static int DWC_ETH_QOS_clean_jumbo_rx_irq(struct DWC_ETH_QOS_prv_data *pdata,
|
||||
int quota, UINT);
|
||||
|
||||
static int DWC_ETH_QOS_clean_rx_irq(struct DWC_ETH_QOS_prv_data *pdata,
|
||||
int quota, UINT);
|
||||
|
||||
static void DWC_ETH_QOS_consume_page(struct DWC_ETH_QOS_rx_buffer *buffer,
|
||||
struct sk_buff *skb,
|
||||
u16 length, u16 buf2_len);
|
||||
|
||||
static void DWC_ETH_QOS_receive_skb(struct DWC_ETH_QOS_prv_data *pdata,
|
||||
struct net_device *dev,
|
||||
struct sk_buff *skb,
|
||||
UINT);
|
||||
|
||||
static void DWC_ETH_QOS_configure_rx_fun_ptr(struct DWC_ETH_QOS_prv_data
|
||||
*pdata);
|
||||
|
||||
static int DWC_ETH_QOS_alloc_split_hdr_rx_buf(
|
||||
struct DWC_ETH_QOS_prv_data *pdata,
|
||||
struct DWC_ETH_QOS_rx_buffer *buffer,
|
||||
UINT qinx, gfp_t gfp);
|
||||
|
||||
static int DWC_ETH_QOS_alloc_jumbo_rx_buf(struct DWC_ETH_QOS_prv_data *pdata,
|
||||
struct DWC_ETH_QOS_rx_buffer *buffer, UINT qinx,
|
||||
gfp_t gfp);
|
||||
|
||||
static int DWC_ETH_QOS_alloc_rx_buf(struct DWC_ETH_QOS_prv_data *pdata,
|
||||
struct DWC_ETH_QOS_rx_buffer *buffer, UINT qinx,
|
||||
gfp_t gfp);
|
||||
|
||||
static void DWC_ETH_QOS_default_common_confs(struct DWC_ETH_QOS_prv_data
|
||||
*pdata);
|
||||
static void DWC_ETH_QOS_default_tx_confs(struct DWC_ETH_QOS_prv_data *pdata);
|
||||
static void DWC_ETH_QOS_default_tx_confs_single_q(struct DWC_ETH_QOS_prv_data
|
||||
*pdata, UINT);
|
||||
static void DWC_ETH_QOS_default_rx_confs(struct DWC_ETH_QOS_prv_data *pdata);
|
||||
static void DWC_ETH_QOS_default_rx_confs_single_q(struct DWC_ETH_QOS_prv_data
|
||||
*pdata, UINT);
|
||||
|
||||
int DWC_ETH_QOS_poll(struct DWC_ETH_QOS_prv_data *pdata, int budget, int qinx);
|
||||
|
||||
static void DWC_ETH_QOS_mmc_setup(struct DWC_ETH_QOS_prv_data *pdata);
|
||||
inline unsigned int DWC_ETH_QOS_reg_read(volatile ULONG * ptr);
|
||||
|
||||
#ifdef DWC_ETH_QOS_QUEUE_SELECT_ALGO
|
||||
u16 DWC_ETH_QOS_select_queue(struct net_device *dev, struct sk_buff *skb,
|
||||
void *accel_priv, select_queue_fallback_t fallback);
|
||||
#endif
|
||||
|
||||
static int DWC_ETH_QOS_vlan_rx_add_vid(
|
||||
struct net_device *dev, __be16 proto, u16 vid);
|
||||
static int DWC_ETH_QOS_vlan_rx_kill_vid(struct net_device *dev,
|
||||
__be16 proto, u16 vid);
|
||||
#endif
|
@@ -0,0 +1,555 @@
|
||||
/* 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.
|
||||
*
|
||||
* This file contain content copied from Synopsis driver,
|
||||
* provided under the license below
|
||||
*/
|
||||
/* =========================================================================
|
||||
* The Synopsys DWC ETHER QOS Software Driver and documentation (hereinafter
|
||||
* "Software") is an unsupported proprietary work of Synopsys, Inc. unless
|
||||
* otherwise expressly agreed to in writing between Synopsys and you.
|
||||
*
|
||||
* The Software IS NOT an item of Licensed Software or Licensed Product under
|
||||
* any End User Software License Agreement or Agreement for Licensed Product
|
||||
* with Synopsys or any supplement thereto. Permission is hereby granted,
|
||||
* free of charge, to any person obtaining a copy of this software annotated
|
||||
* with this license and the Software, to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject
|
||||
* to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* =========================================================================
|
||||
*/
|
||||
|
||||
/*!@file: DWC_ETH_QOS_eee.c
|
||||
* @brief: Driver functions.
|
||||
*/
|
||||
#include "DWC_ETH_QOS_yheader.h"
|
||||
|
||||
/* Clause 22 registers to access clause 45 register set */
|
||||
#define MMD_CTRL_REG 0x0D /* MMD Access Control Register */
|
||||
#define MMD_ADDR_DATA_REG 0x0E /* MMD Access Address Data Register */
|
||||
|
||||
/* MMD Access Control register fields */
|
||||
#define MMD_CTRL_FUNC_ADDR 0x0000 /* address */
|
||||
#define MMD_CTRL_FUNC_DATA_NOINCR 0x4000 /* data, no post increment */
|
||||
/* data, post increment on reads & writes */
|
||||
#define MMD_CTRL_FUNC_DATA_INCR_ON_RDWT 0x8000
|
||||
|
||||
/* data, post increment on writes only */
|
||||
#define MMD_CTRL_FUNC_DATA_INCR_ON_WT 0xC000
|
||||
|
||||
/* Clause 45 expansion register */
|
||||
#define CL45_PCS_EEE_ABLE 0x14 /* EEE Capability register */
|
||||
#define CL45_ADV_EEE_REG 0x3C /* EEE advertisement */
|
||||
#define CL45_AN_EEE_LPABLE_REG 0x3D /* EEE Link Partner ability reg */
|
||||
#define CL45_CLK_STOP_EN_REG 0x0 /* Clock Stop enable reg */
|
||||
|
||||
/* Clause 45 expansion registers fields */
|
||||
/* LP EEE capabilities status */
|
||||
#define CL45_LP_ADV_EEE_STATS_1000BASE_T 0x0004
|
||||
|
||||
#define CL45_CLK_STOP_EN 0x400 /* Enable xMII Clock Stop */
|
||||
|
||||
#define AR8035_SMART_EEE_CTRL_3 0x805D
|
||||
#define AR8035_SMART_EEE_EN (1<<8)
|
||||
|
||||
#define PHY_RX_CLOCK_STOPPABLE_EN 1
|
||||
#define PHY_RX_CLOCK_STOPPABLE_DIS 0
|
||||
|
||||
void DWC_ETH_QOS_enable_eee_mode(struct DWC_ETH_QOS_prv_data *pdata)
|
||||
{
|
||||
struct DWC_ETH_QOS_tx_wrapper_descriptor *tx_desc_data = NULL;
|
||||
struct hw_if_struct *hw_if = &pdata->hw_if;
|
||||
int tx_idle = 0, QINX;
|
||||
|
||||
DBGPR_EEE("-->DWC_ETH_QOS_enable_eee_mode\n");
|
||||
|
||||
for (QINX = 0; pdata->tx_queue_cnt > QINX ; QINX++) {
|
||||
tx_desc_data = GET_TX_WRAPPER_DESC(QINX);
|
||||
|
||||
if ((tx_desc_data->dirty_tx == tx_desc_data->cur_tx) &&
|
||||
(!pdata->tx_path_in_lpi_mode)) {
|
||||
tx_idle = 1;
|
||||
} else {
|
||||
tx_idle = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tx_idle)
|
||||
hw_if->set_eee_mode();
|
||||
|
||||
DBGPR_EEE("<--DWC_ETH_QOS_enable_eee_mode\n");
|
||||
}
|
||||
|
||||
void DWC_ETH_QOS_disable_eee_mode(struct DWC_ETH_QOS_prv_data *pdata)
|
||||
{
|
||||
struct hw_if_struct *hw_if = &pdata->hw_if;
|
||||
|
||||
DBGPR_EEE("-->DWC_ETH_QOS_disable_eee_mode\n");
|
||||
|
||||
hw_if->reset_eee_mode();
|
||||
del_timer_sync(&pdata->eee_ctrl_timer);
|
||||
pdata->tx_path_in_lpi_mode = false;
|
||||
pdata->eee_active = 0;
|
||||
|
||||
DBGPR_EEE("-->DWC_ETH_QOS_disable_eee_mode\n");
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief API to control EEE mode.
|
||||
*
|
||||
* \details This function will move the MAC transmitter in LPI mode
|
||||
* if there is no data transfer and MAC is not already in LPI state.
|
||||
*
|
||||
* \param[in] data - data hook
|
||||
*
|
||||
* \return void
|
||||
*/
|
||||
|
||||
static void DWC_ETH_QOS_eee_ctrl_timer(unsigned long data)
|
||||
{
|
||||
struct DWC_ETH_QOS_prv_data *pdata =
|
||||
(struct DWC_ETH_QOS_prv_data *)data;
|
||||
|
||||
DBGPR_EEE("-->DWC_ETH_QOS_eee_ctrl_timer\n");
|
||||
|
||||
DWC_ETH_QOS_enable_eee_mode(pdata);
|
||||
|
||||
DBGPR_EEE("<--DWC_ETH_QOS_eee_ctrl_timer\n");
|
||||
}
|
||||
|
||||
static void DWC_ETH_QOS_mmd_phy_indirect(struct mii_bus *bus,
|
||||
int REGADDR,
|
||||
int DEVADDR,
|
||||
int PHYADDR)
|
||||
{
|
||||
/* Write the desired MMD devAddr */
|
||||
bus->write(bus, PHYADDR, MMD_CTRL_REG, DEVADDR);
|
||||
|
||||
/* Write the desired MMD regAddr */
|
||||
bus->write(bus, PHYADDR, MMD_ADDR_DATA_REG, REGADDR);
|
||||
|
||||
/* Select the Function : DATA with no post increment */
|
||||
bus->write(bus, PHYADDR, MMD_CTRL_REG,
|
||||
(DEVADDR | MMD_CTRL_FUNC_DATA_NOINCR));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief API to read data from the MMD registers.
|
||||
*
|
||||
* \details This function will read data from the MMD(clause 45) registers
|
||||
* using clause 22 registers. The procedure to read MMD registers is,
|
||||
* 1. Write the desired MMD device addr into reg 13
|
||||
* 2. Write the desired MMD reg addr into reg 14
|
||||
* 3. Select the desired Function - MMD data command by writing in reg 13
|
||||
* 4. Read the content of the MMD's selected reg through reg 14
|
||||
*
|
||||
* \param[in] bus - the target MII bus
|
||||
* \param[in] regAddr - desired MMD reg addr to be read
|
||||
* \param[in] devAddr - desired MMD address
|
||||
* \param[in] phyAddr - PHY addr/id on the MII bus
|
||||
*
|
||||
* \return integer
|
||||
*/
|
||||
static int DWC_ETH_QOS_phy_read_mmd_indirect(struct mii_bus *bus,
|
||||
int REGADDR,
|
||||
int DEVADDR,
|
||||
int PHYADDR)
|
||||
{
|
||||
u32 ret;
|
||||
|
||||
DBGPR_EEE("-->DWC_ETH_QOS_phy_read_mmd_indirect\n");
|
||||
|
||||
DWC_ETH_QOS_mmd_phy_indirect(bus, REGADDR, DEVADDR, PHYADDR);
|
||||
/* read the content of the MMD's selected register */
|
||||
ret = bus->read(bus, PHYADDR, MMD_ADDR_DATA_REG);
|
||||
|
||||
DBGPR_EEE("<--DWC_ETH_QOS_phy_read_mmd_indirect\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief API to write data into the MMD registers.
|
||||
*
|
||||
* \details This function will write data into MMD(clause 45) registers
|
||||
* using clause 22 registers. The procedure to write MMD registers is,
|
||||
* 1. Write the desired MMD device addr into reg 13
|
||||
* 2. Write the desired MMD reg addr into reg 14
|
||||
* 3. Select the desired Function - MMD data command by writing in reg 13
|
||||
* 4. Write the data into MMD's selected reg through reg 14
|
||||
*
|
||||
* \param[in] bus - the target MII bus
|
||||
* \param[in] regAddr - desired MMD reg addr to be written
|
||||
* \param[in] devAddr - desired MMD address
|
||||
* \param[in] phyAddr - PHY addr/id on the MII bus
|
||||
* \param[in] data - data to write into the MMD register
|
||||
*
|
||||
* \return void
|
||||
*/
|
||||
static void DWC_ETH_QOS_phy_write_mmd_indirect(struct mii_bus *bus,
|
||||
int REGADDR,
|
||||
int DEVADDR,
|
||||
int PHYADDR,
|
||||
u32 data)
|
||||
{
|
||||
DBGPR_EEE("-->DWC_ETH_QOS_phy_write_mmd_indirect\n");
|
||||
|
||||
DWC_ETH_QOS_mmd_phy_indirect(bus, REGADDR, DEVADDR, PHYADDR);
|
||||
/* Write the data into MMD's selected register */
|
||||
bus->write(bus, PHYADDR, MMD_ADDR_DATA_REG, data);
|
||||
|
||||
DBGPR_EEE("<--DWC_ETH_QOS_phy_write_mmd_indirect\n");
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
#define MDIO_EEE_100TX 0x0002 /* EEE is supported for 100BASE-TX */
|
||||
#define MDIO_EEE_1000T 0x0004 /* EEE is supported for 1000BASE-T */
|
||||
#define MDIO_EEE_10GT 0x0008 /* EEE is supported for 10GBASE-T */
|
||||
#define MDIO_EEE_1000KX 0x0010 /* EEE is supported for 1000BASE-KX */
|
||||
#define MDIO_EEE_10GKX4 0x0020 /* EEE is supported for 10GBASE-KX4 */
|
||||
#define MDIO_EEE_10GKR 0x0040 /* EEE is supported for 10GBASE KR */
|
||||
|
||||
/* A small helper function that translates MMD EEE Capability (3.20) bits
|
||||
* to ethtool supported settings.
|
||||
*/
|
||||
static u32 DWC_ETH_QOS_mmd_eee_cap_to_ethtool_sup_t(u16 eee_cap)
|
||||
{
|
||||
u32 supported = 0;
|
||||
|
||||
if (eee_cap & MDIO_EEE_100TX)
|
||||
supported |= SUPPORTED_100baseT_Full;
|
||||
if (eee_cap & MDIO_EEE_1000T)
|
||||
supported |= SUPPORTED_1000baseT_Full;
|
||||
if (eee_cap & MDIO_EEE_10GT)
|
||||
supported |= SUPPORTED_10000baseT_Full;
|
||||
if (eee_cap & MDIO_EEE_1000KX)
|
||||
supported |= SUPPORTED_1000baseKX_Full;
|
||||
if (eee_cap & MDIO_EEE_10GKX4)
|
||||
supported |= SUPPORTED_10000baseKX4_Full;
|
||||
if (eee_cap & MDIO_EEE_10GKR)
|
||||
supported |= SUPPORTED_10000baseKR_Full;
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
||||
/* A small helper function that translates the MMD EEE Advertisment (7.60)
|
||||
* and MMD EEE Link Partner Ability (7.61) bits to ethtool advertisement
|
||||
* settings.
|
||||
*/
|
||||
static inline u32 DWC_ETH_QOS_mmd_eee_adv_to_ethtool_adv_t(u16 eee_adv)
|
||||
{
|
||||
u32 adv = 0;
|
||||
|
||||
if (eee_adv & MDIO_EEE_100TX)
|
||||
adv |= ADVERTISED_100baseT_Full;
|
||||
if (eee_adv & MDIO_EEE_1000T)
|
||||
adv |= ADVERTISED_1000baseT_Full;
|
||||
if (eee_adv & MDIO_EEE_10GT)
|
||||
adv |= ADVERTISED_10000baseT_Full;
|
||||
if (eee_adv & MDIO_EEE_1000KX)
|
||||
adv |= ADVERTISED_1000baseKX_Full;
|
||||
if (eee_adv & MDIO_EEE_10GKX4)
|
||||
adv |= ADVERTISED_10000baseKX4_Full;
|
||||
if (eee_adv & MDIO_EEE_10GKR)
|
||||
adv |= ADVERTISED_10000baseKR_Full;
|
||||
|
||||
return adv;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief API to disable EEE mode.
|
||||
*
|
||||
* \details This function disable smart EEE
|
||||
* \param[in] phydev - pointer to target phy_device structure
|
||||
*/
|
||||
|
||||
static void DWC_ETH_QOS_disable_smart_eee(struct phy_device *phydev)
|
||||
{
|
||||
u32 smart_eee;
|
||||
|
||||
smart_eee = DWC_ETH_QOS_phy_read_mmd_indirect(
|
||||
phydev->mdio.bus, AR8035_SMART_EEE_CTRL_3,
|
||||
MDIO_MMD_PCS, phydev->mdio.addr);
|
||||
|
||||
smart_eee &= ~AR8035_SMART_EEE_EN;
|
||||
DWC_ETH_QOS_phy_write_mmd_indirect(
|
||||
phydev->mdio.bus, AR8035_SMART_EEE_CTRL_3,
|
||||
MDIO_MMD_PCS,phydev->mdio.addr, smart_eee);
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief API to initialize and check EEE mode.
|
||||
*
|
||||
* \details This function checks if the EEE is supported by
|
||||
* looking at the MMD registers and it also programs the MMD
|
||||
* register 3.0 setting the "Clock stop enable" bit if required.
|
||||
*
|
||||
* \param[in] phydev - pointer to target phy_device structure
|
||||
* \param[in] clk_stop_enable - PHY may stop the clock during LPI
|
||||
*
|
||||
* \return integer
|
||||
*
|
||||
* \retval zero if EEE is supported else return -ve number.
|
||||
*/
|
||||
static int DWC_ETH_QOS_phy_init_eee(struct phy_device *phydev,
|
||||
bool clk_stop_enable)
|
||||
{
|
||||
int ret = -EPROTONOSUPPORT;
|
||||
|
||||
DBGPR_EEE("-->DWC_ETH_QOS_phy_init_eee\n");
|
||||
|
||||
/* According to 802.3az,the EEE is supported only in full duplex-mode.
|
||||
* Also EEE feature is active when core is operating with MII, GMII,
|
||||
* SGMII or RGMII.
|
||||
*/
|
||||
if ((phydev->duplex == DUPLEX_FULL) &&
|
||||
((phydev->interface == PHY_INTERFACE_MODE_MII) ||
|
||||
(phydev->interface == PHY_INTERFACE_MODE_GMII) ||
|
||||
(phydev->interface == PHY_INTERFACE_MODE_SGMII) ||
|
||||
(phydev->interface == PHY_INTERFACE_MODE_RGMII))) {
|
||||
int eee_lp, eee_cap, eee_adv;
|
||||
/*u32 cap,lp , adv;*/
|
||||
int status;/*, idx;*/
|
||||
|
||||
/* Read phy status to properly get the right settings */
|
||||
status = phy_read_status(phydev);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* First check if the EEE ability is supported */
|
||||
eee_cap = DWC_ETH_QOS_phy_read_mmd_indirect(
|
||||
phydev->mdio.bus,
|
||||
CL45_PCS_EEE_ABLE, MDIO_MMD_PCS,phydev->mdio.addr);
|
||||
if (eee_cap < 0)
|
||||
return eee_cap;
|
||||
if (eee_cap == 0)
|
||||
return -1;
|
||||
|
||||
/* cap = DWC_ETH_QOS_mmd_eee_cap_to_ethtool_sup_t(eee_cap);
|
||||
* if (!cap)
|
||||
* goto eee_exit;
|
||||
*/
|
||||
/* check whether link Partner support EEE or not */
|
||||
eee_lp = DWC_ETH_QOS_phy_read_mmd_indirect(
|
||||
phydev->mdio.bus,
|
||||
CL45_AN_EEE_LPABLE_REG, MDIO_MMD_AN,phydev->mdio.addr);
|
||||
if (eee_lp < 0)
|
||||
return eee_lp;
|
||||
if (eee_lp == 0)
|
||||
return -1;
|
||||
|
||||
eee_adv = DWC_ETH_QOS_phy_read_mmd_indirect(
|
||||
phydev->mdio.bus,
|
||||
CL45_ADV_EEE_REG, MDIO_MMD_AN,phydev->mdio.addr);
|
||||
if (eee_adv < 0)
|
||||
return eee_adv;
|
||||
if (eee_adv == 0)
|
||||
return -1;
|
||||
|
||||
/* TODO:check this
|
||||
* adv = DWC_ETH_QOS_mmd_eee_adv_to_ethtool_adv_t(eee_adv);
|
||||
* lp = DWC_ETH_QOS_mmd_eee_adv_to_ethtool_adv_t(eee_lp);
|
||||
* idx = phy_find_setting(phydev->speed, phydev->duplex);
|
||||
* if ((lp & adv & settings[idx].setting))
|
||||
goto eee_exit;
|
||||
*/
|
||||
if (clk_stop_enable) {
|
||||
/* Configure the PHY to stop receiving xMII
|
||||
* clock while it is signaling LPI.
|
||||
*/
|
||||
int val = DWC_ETH_QOS_phy_read_mmd_indirect(phydev->mdio.bus,
|
||||
CL45_CLK_STOP_EN_REG, MDIO_MMD_PCS,
|
||||
phydev->mdio.addr);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
val |= CL45_CLK_STOP_EN;
|
||||
DWC_ETH_QOS_phy_write_mmd_indirect(
|
||||
phydev->mdio.bus, CL45_CLK_STOP_EN_REG, MDIO_MMD_PCS,
|
||||
phydev->mdio.addr, val);
|
||||
}
|
||||
|
||||
/* Disable smart EEE feature in AR8035*/
|
||||
if (phydev->phy_id == ATH8035_PHY_ID || phydev->phy_id == ATH8030_PHY_ID) {
|
||||
DWC_ETH_QOS_disable_smart_eee(phydev);
|
||||
}
|
||||
|
||||
ret = 0; /* EEE supported */
|
||||
}
|
||||
|
||||
DBGPR_EEE("<--DWC_ETH_QOS_phy_init_eee\n");
|
||||
|
||||
/*eee_exit:*/
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief API to initialize EEE mode.
|
||||
*
|
||||
* \details This function enables the LPI state and start the timer
|
||||
* to verify whether the tx path can enter in LPI state if
|
||||
* a. GMAC supports EEE mode &
|
||||
* b. phy can also manage EEE.
|
||||
*
|
||||
* \param[in] pdata - pointer to private data structure
|
||||
*
|
||||
* \return bool
|
||||
*
|
||||
* \retval true on success & false on failure.
|
||||
*/
|
||||
bool DWC_ETH_QOS_eee_init(struct DWC_ETH_QOS_prv_data *pdata)
|
||||
{
|
||||
struct hw_if_struct *hw_if;
|
||||
bool ret = false;
|
||||
|
||||
EMACDBG("Enter\n");
|
||||
|
||||
hw_if = &pdata->hw_if;
|
||||
|
||||
/* Disable smart EEE & EEE for ATH8030*/
|
||||
if ((pdata->emac_hw_version_type == EMAC_HW_v2_3_1)
|
||||
&& (pdata->io_macro_phy_intf == RMII_MODE) &&
|
||||
pdata->phydev->phy_id == ATH8030_PHY_ID) {
|
||||
//disable smart EEE
|
||||
DWC_ETH_QOS_disable_smart_eee(pdata->phydev);
|
||||
EMACDBG("disable smart EEE for 8030\n");
|
||||
}
|
||||
|
||||
/* For RMII mode EEE is not supported */
|
||||
if (pdata->io_macro_phy_intf == RMII_MODE)
|
||||
goto phy_eee_failed;
|
||||
|
||||
/* HW supports the EEE feature */
|
||||
if (pdata->hw_feat.eee_sel) {
|
||||
#ifndef DWC_ETH_QOS_CUSTOMIZED_EEE_TEST
|
||||
/* check if the PHY supports EEE */
|
||||
if (!pdata->phydev || !pdata->phydev->link
|
||||
|| DWC_ETH_QOS_phy_init_eee(pdata->phydev, PHY_RX_CLOCK_STOPPABLE_DIS))
|
||||
goto phy_eee_failed;
|
||||
#endif /* DWC_ETH_QOS_CUSTOMIZED_EEE_TEST */
|
||||
|
||||
if (!pdata->eee_active) {
|
||||
pdata->eee_active = 1;
|
||||
if (pdata->use_lpi_auto_entry_timer) {
|
||||
pdata->hw_if.set_lpi_us_tic_counter(CLOCK_AHB_MHZ);
|
||||
hw_if->set_lpi_tx_auto_entry_timer(DWC_ETH_QOS_DEFAULT_LPI_LPIET_TIMER);
|
||||
hw_if->set_eee_timer(DWC_ETH_QOS_DEFAULT_LPI_LS_TIMER,
|
||||
DWC_ETH_QOS_DEFAULT_LPI_TWT_TIMER);
|
||||
hw_if->set_lpi_tx_automate();
|
||||
hw_if->set_lpi_tx_auto_entry_timer_en();
|
||||
hw_if->set_eee_mode();
|
||||
hw_if->set_eee_pls(pdata->phydev->link);
|
||||
} else {
|
||||
init_timer(&pdata->eee_ctrl_timer);
|
||||
pdata->eee_ctrl_timer.function =
|
||||
DWC_ETH_QOS_eee_ctrl_timer;
|
||||
pdata->eee_ctrl_timer.data = (unsigned long)pdata;
|
||||
pdata->eee_ctrl_timer.expires =
|
||||
DWC_ETH_QOS_LPI_TIMER(
|
||||
DWC_ETH_QOS_DEFAULT_LPI_TIMER);
|
||||
add_timer(&pdata->eee_ctrl_timer);
|
||||
|
||||
hw_if->set_eee_timer(DWC_ETH_QOS_DEFAULT_LPI_LS_TIMER,
|
||||
DWC_ETH_QOS_DEFAULT_LPI_TWT_TIMER);
|
||||
|
||||
if (pdata->use_lpi_tx_automate)
|
||||
hw_if->set_lpi_tx_automate();
|
||||
}
|
||||
} else {
|
||||
/* When EEE has been already initialized we have to
|
||||
* modify the PLS bit in MAC_LPI_Control_Status reg
|
||||
* according to PHY link status.
|
||||
*/
|
||||
hw_if->set_eee_pls(pdata->phydev->link);
|
||||
}
|
||||
|
||||
DBGPR_EEE("EEE initialized\n");
|
||||
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
#ifndef DWC_ETH_QOS_CUSTOMIZED_EEE_TEST
|
||||
phy_eee_failed:
|
||||
/* In case of failure, reset the PHY link status in MAC_LPI_Control_Status reg */
|
||||
hw_if->set_eee_pls(0);
|
||||
|
||||
/* Disable EEE mode */
|
||||
if (pdata->eee_active) {
|
||||
hw_if->reset_eee_mode();
|
||||
pdata->eee_active = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
EMACDBG("Exit\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define MAC_LPS_TLPIEN 0x00000001
|
||||
#define MAC_LPS_TLPIEX 0x00000002
|
||||
#define MAC_LPS_RLPIEN 0x00000004
|
||||
#define MAC_LPS_RLPIEX 0x00000008
|
||||
void DWC_ETH_QOS_handle_eee_interrupt(struct DWC_ETH_QOS_prv_data *pdata)
|
||||
{
|
||||
struct hw_if_struct *hw_if = &pdata->hw_if;
|
||||
u32 lpi_status;
|
||||
|
||||
DBGPR_EEE("-->DWC_ETH_QOS_handle_eee_interrupt\n");
|
||||
|
||||
lpi_status = hw_if->get_lpi_status();
|
||||
DBGPR_EEE("MAC_LPI_Control_Status = %#x\n", lpi_status);
|
||||
|
||||
if (lpi_status & MAC_LPS_TLPIEN) {
|
||||
pdata->tx_path_in_lpi_mode = 1;
|
||||
pdata->xstats.tx_path_in_lpi_mode_irq_n++;
|
||||
DBGPR_EEE("MAC Transmitter has entered the LPI state\n");
|
||||
}
|
||||
|
||||
if (lpi_status & MAC_LPS_TLPIEX) {
|
||||
pdata->tx_path_in_lpi_mode = 0;
|
||||
pdata->xstats.tx_path_exit_lpi_mode_irq_n++;
|
||||
DBGPR_EEE("MAC Transmitter has exited the LPI state\n");
|
||||
}
|
||||
|
||||
if (lpi_status & MAC_LPS_RLPIEN) {
|
||||
pdata->xstats.rx_path_in_lpi_mode_irq_n++;
|
||||
DBGPR_EEE("MAC Receiver has entered the LPI state\n");
|
||||
}
|
||||
|
||||
if (lpi_status & MAC_LPS_RLPIEX) {
|
||||
pdata->xstats.rx_path_exit_lpi_mode_irq_n++;
|
||||
DBGPR_EEE("MAC Receiver has exited the LPI state\n");
|
||||
}
|
||||
|
||||
DBGPR_EEE("<--DWC_ETH_QOS_handle_eee_interrupt\n");
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,86 @@
|
||||
/* Copyright (c) 2017, 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.
|
||||
*
|
||||
* This file contain content copied from Synopsis driver,
|
||||
* provided under the license below
|
||||
*/
|
||||
/* =========================================================================
|
||||
* The Synopsys DWC ETHER QOS Software Driver and documentation (hereinafter
|
||||
* "Software") is an unsupported proprietary work of Synopsys, Inc. unless
|
||||
* otherwise expressly agreed to in writing between Synopsys and you.
|
||||
*
|
||||
* The Software IS NOT an item of Licensed Software or Licensed Product under
|
||||
* any End User Software License Agreement or Agreement for Licensed Product
|
||||
* with Synopsys or any supplement thereto. Permission is hereby granted,
|
||||
* free of charge, to any person obtaining a copy of this software annotated
|
||||
* with this license and the Software, to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject
|
||||
* to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* =========================================================================
|
||||
*/
|
||||
|
||||
#ifndef __DWC_ETH_QOS_ETHTOOL_H__
|
||||
|
||||
#define __DWC_ETH_QOS_ETHTOOL_H__
|
||||
|
||||
static void DWC_ETH_QOS_get_pauseparam(struct net_device *dev,
|
||||
struct ethtool_pauseparam *pause);
|
||||
static int DWC_ETH_QOS_set_pauseparam(struct net_device *dev,
|
||||
struct ethtool_pauseparam *pause);
|
||||
|
||||
static int DWC_ETH_QOS_getsettings(struct net_device *dev,
|
||||
struct ethtool_cmd *cmd);
|
||||
static int DWC_ETH_QOS_setsettings(struct net_device *dev,
|
||||
struct ethtool_cmd *cmd);
|
||||
static void DWC_ETH_QOS_get_wol(struct net_device *dev,
|
||||
struct ethtool_wolinfo *wol);
|
||||
static int DWC_ETH_QOS_set_wol(struct net_device *dev,
|
||||
struct ethtool_wolinfo *wol);
|
||||
|
||||
static int DWC_ETH_QOS_set_coalesce(struct net_device *dev,
|
||||
struct ethtool_coalesce *ec);
|
||||
static int DWC_ETH_QOS_get_coalesce(struct net_device *dev,
|
||||
struct ethtool_coalesce *ec);
|
||||
|
||||
static int DWC_ETH_QOS_get_sset_count(struct net_device *dev, int sset);
|
||||
|
||||
static void DWC_ETH_QOS_get_strings(struct net_device *dev, u32 stringset,
|
||||
u8 *data);
|
||||
|
||||
static void DWC_ETH_QOS_get_ethtool_stats(
|
||||
struct net_device *dev,
|
||||
struct ethtool_stats *dummy, u64 *data);
|
||||
|
||||
#ifdef DWC_ETH_QOS_CONFIG_PTP
|
||||
|
||||
static int DWC_ETH_QOS_get_ts_info(struct net_device *dev,
|
||||
struct ethtool_ts_info *info);
|
||||
|
||||
#endif /* end of DWC_ETH_QOS_CONFIG_PTP */
|
||||
|
||||
#endif
|
1613
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/DWC_ETH_QOS_ipa.c
Normal file
1613
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/DWC_ETH_QOS_ipa.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,91 @@
|
||||
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of The Linux Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
|
||||
*/
|
||||
|
||||
#ifndef __DWC_ETH_QOS_IPA_H__
|
||||
#define __DWC_ETH_QOS_IPA_H__
|
||||
|
||||
#include <linux/ipa.h>
|
||||
#include <linux/ipa_uc_offload.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
|
||||
#include "DWC_ETH_QOS_yheader.h"
|
||||
#include "DWC_ETH_QOS_yregacc.h"
|
||||
#include "DWC_ETH_QOS_yrgmii_io_macro_regacc.h"
|
||||
|
||||
typedef enum {
|
||||
EV_INVALID = 0,
|
||||
EV_DEV_OPEN,
|
||||
EV_DEV_CLOSE,
|
||||
EV_IPA_READY,
|
||||
EV_IPA_UC_READY,
|
||||
EV_PHY_LINK_UP,
|
||||
EV_PHY_LINK_DOWN,
|
||||
EV_DPM_SUSPEND,
|
||||
EV_DPM_RESUME,
|
||||
EV_USR_SUSPEND,
|
||||
EV_USR_RESUME,
|
||||
EV_IPA_OFFLOAD_MAX,
|
||||
} IPA_OFFLOAD_EVENT;
|
||||
|
||||
#ifdef DWC_ETH_QOS_ENABLE_IPA
|
||||
|
||||
#define EMAC_IPA_CAPABLE 1
|
||||
|
||||
void DWC_ETH_QOS_ipa_offload_event_handler(
|
||||
struct DWC_ETH_QOS_prv_data *pdata, IPA_OFFLOAD_EVENT ev);
|
||||
int DWC_ETH_QOS_disable_enable_ipa_offload(struct DWC_ETH_QOS_prv_data *pdata,int chInx_tx_ipa,
|
||||
int chInx_rx_ipa);
|
||||
void DWC_ETH_QOS_ipa_stats_read(struct DWC_ETH_QOS_prv_data *pdata);
|
||||
|
||||
#else /* DWC_ETH_QOS_ENABLE_IPA */
|
||||
|
||||
#define EMAC_IPA_CAPABLE 0
|
||||
|
||||
static inline void DWC_ETH_QOS_ipa_offload_event_handler(
|
||||
struct DWC_ETH_QOS_prv_data *pdata, IPA_OFFLOAD_EVENT ev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int DWC_ETH_QOS_disable_enable_ipa_offload(struct DWC_ETH_QOS_prv_data *pdata,
|
||||
int chInx_tx_ipa, int chInx_rx_ipa)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static inline void DWC_ETH_QOS_ipa_stats_read(struct DWC_ETH_QOS_prv_data *pdata)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* DWC_ETH_QOS_ENABLE_IPA */
|
||||
|
||||
#endif
|
1417
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/DWC_ETH_QOS_mdio.c
Normal file
1417
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/DWC_ETH_QOS_mdio.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,230 @@
|
||||
/*Copyright (c) 2019, 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.
|
||||
*/
|
||||
|
||||
/*!@file: DWC_ETH_QOS_poll_support.c
|
||||
*/
|
||||
|
||||
#include "DWC_ETH_QOS_yheader.h"
|
||||
|
||||
#define AVB_CLASS_A_CHANNEL_NUM 2
|
||||
#define AVB_CLASS_B_CHANNEL_NUM 3
|
||||
|
||||
extern struct DWC_ETH_QOS_prv_data *gDWC_ETH_QOS_prv_data;
|
||||
|
||||
struct pps_info {
|
||||
int channel_no;
|
||||
};
|
||||
|
||||
bool avb_class_a_msg_wq_flag;
|
||||
bool avb_class_b_msg_wq_flag;
|
||||
|
||||
DECLARE_WAIT_QUEUE_HEAD(avb_class_a_msg_wq);
|
||||
DECLARE_WAIT_QUEUE_HEAD(avb_class_b_msg_wq);
|
||||
|
||||
static ssize_t pps_fops_read(struct file *filp, char __user *buf,
|
||||
size_t count, loff_t *f_pos)
|
||||
{
|
||||
|
||||
unsigned int len = 0, buf_len = 5000;
|
||||
char* temp_buf;
|
||||
ssize_t ret_cnt = 0;
|
||||
struct pps_info *info;
|
||||
|
||||
info = filp->private_data;
|
||||
|
||||
if (info->channel_no == AVB_CLASS_A_CHANNEL_NUM ) {
|
||||
temp_buf = kzalloc(buf_len, GFP_KERNEL);
|
||||
if (!temp_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (gDWC_ETH_QOS_prv_data)
|
||||
len = scnprintf(temp_buf, buf_len ,
|
||||
"%ld\n", gDWC_ETH_QOS_prv_data->avb_class_a_intr_cnt);
|
||||
else
|
||||
len = scnprintf(temp_buf, buf_len , "0\n");
|
||||
|
||||
ret_cnt = simple_read_from_buffer(buf, count, f_pos, temp_buf, len);
|
||||
kfree(temp_buf);
|
||||
if (gDWC_ETH_QOS_prv_data)
|
||||
EMACERR("poll pps2intr info=%d sent by kernel\n", gDWC_ETH_QOS_prv_data->avb_class_a_intr_cnt);
|
||||
} else if (info->channel_no == AVB_CLASS_B_CHANNEL_NUM ) {
|
||||
temp_buf = kzalloc(buf_len, GFP_KERNEL);
|
||||
if (!temp_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (gDWC_ETH_QOS_prv_data)
|
||||
len = scnprintf(temp_buf, buf_len ,
|
||||
"%ld\n", gDWC_ETH_QOS_prv_data->avb_class_b_intr_cnt);
|
||||
else
|
||||
len = scnprintf(temp_buf, buf_len , "0\n");
|
||||
|
||||
ret_cnt = simple_read_from_buffer(buf, count, f_pos, temp_buf, len);
|
||||
kfree(temp_buf);
|
||||
|
||||
} else {
|
||||
EMACERR("invalid channel %d\n",info->channel_no);
|
||||
}
|
||||
return ret_cnt;
|
||||
|
||||
}
|
||||
|
||||
static unsigned int pps_fops_poll(struct file *file, poll_table *wait)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
struct pps_info *info;
|
||||
|
||||
info = file->private_data;
|
||||
if (info->channel_no == AVB_CLASS_A_CHANNEL_NUM ){
|
||||
EMACDBG("avb_class_a_fops_poll wait\n");
|
||||
|
||||
poll_wait(file, &avb_class_a_msg_wq, wait);
|
||||
|
||||
EMACDBG("avb_class_a_fops_poll exit\n");
|
||||
|
||||
if (avb_class_a_msg_wq_flag == 1) {
|
||||
//Sending read mask
|
||||
mask |= POLLIN | POLLRDNORM;
|
||||
avb_class_a_msg_wq_flag = 0;
|
||||
}
|
||||
} else if (info->channel_no == AVB_CLASS_B_CHANNEL_NUM) {
|
||||
EMACDBG("avb_class_b_fops_poll wait\n");
|
||||
|
||||
poll_wait(file, &avb_class_b_msg_wq, wait);
|
||||
|
||||
EMACDBG("avb_class_b_fops_poll exit\n");
|
||||
|
||||
if (avb_class_b_msg_wq_flag == 1) {
|
||||
//Sending read mask
|
||||
mask |= POLLIN | POLLRDNORM;
|
||||
avb_class_b_msg_wq_flag = 0;
|
||||
}
|
||||
} else {
|
||||
EMACERR("invalid channel %d\n",info->channel_no);
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
int pps_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct pps_info *info;
|
||||
|
||||
EMACDBG("pps_open enter\n");
|
||||
|
||||
info = kmalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!strncmp(file->f_path.dentry->d_iname, AVB_CLASS_A_POLL_DEV_NODE_NAME , strlen (AVB_CLASS_A_POLL_DEV_NODE_NAME))) {
|
||||
EMACDBG("pps_open file name =%s \n",file->f_path.dentry->d_iname);
|
||||
info->channel_no = AVB_CLASS_A_CHANNEL_NUM;
|
||||
} else if (!strncmp(file->f_path.dentry->d_iname, AVB_CLASS_B_POLL_DEV_NODE_NAME , strlen (AVB_CLASS_B_POLL_DEV_NODE_NAME))) {
|
||||
EMACDBG("pps_open file name =%s \n",file->f_path.dentry->d_iname);
|
||||
info->channel_no = AVB_CLASS_B_CHANNEL_NUM;
|
||||
} else {
|
||||
|
||||
EMACDBG("stsrncmp failed for %s\n",file->f_path.dentry->d_iname);
|
||||
}
|
||||
file->private_data = info;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pps_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
kfree(file->private_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const struct file_operations pps_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = pps_open,
|
||||
.release = pps_release,
|
||||
.read = pps_fops_read,
|
||||
.poll = pps_fops_poll,
|
||||
};
|
||||
|
||||
int create_pps_interrupt_info_device_node(dev_t *pps_dev_t, struct cdev** pps_cdev,
|
||||
struct class** pps_class, char *pps_dev_node_name)
|
||||
{
|
||||
int ret;
|
||||
EMACDBG("create_pps_interrupt_info_device_node enter \n");
|
||||
|
||||
ret = alloc_chrdev_region(pps_dev_t, 0, 1,
|
||||
pps_dev_node_name);
|
||||
if (ret) {
|
||||
EMACERR("alloc_chrdev_region error for node %s \n", pps_dev_node_name);
|
||||
goto alloc_chrdev1_region_fail;
|
||||
}
|
||||
|
||||
*pps_cdev = cdev_alloc();
|
||||
if(!*pps_cdev) {
|
||||
ret = -ENOMEM;
|
||||
EMACERR("failed to alloc cdev\n");
|
||||
goto fail_alloc_cdev;
|
||||
}
|
||||
cdev_init(*pps_cdev, &pps_fops);
|
||||
|
||||
ret = cdev_add(*pps_cdev, *pps_dev_t, 1);
|
||||
if (ret < 0) {
|
||||
EMACERR(":cdev_add err=%d\n", -ret);
|
||||
goto cdev1_add_fail;
|
||||
}
|
||||
|
||||
*pps_class = class_create(THIS_MODULE, pps_dev_node_name);
|
||||
if(!*pps_class) {
|
||||
ret = -ENODEV;
|
||||
EMACERR("failed to create class\n");
|
||||
goto fail_create_class;
|
||||
}
|
||||
|
||||
if (!device_create(*pps_class, NULL,
|
||||
*pps_dev_t, NULL, pps_dev_node_name)) {
|
||||
ret = -EINVAL;
|
||||
EMACERR("failed to create device_create\n");
|
||||
goto fail_create_device;
|
||||
}
|
||||
|
||||
EMACDBG("create_pps_interrupt_info_device_node exit successfuly \n");
|
||||
|
||||
return 0;
|
||||
|
||||
fail_create_device:
|
||||
class_destroy(*pps_class);
|
||||
fail_create_class:
|
||||
cdev_del(*pps_cdev);
|
||||
cdev1_add_fail:
|
||||
fail_alloc_cdev:
|
||||
unregister_chrdev_region(*pps_dev_t, 1);
|
||||
alloc_chrdev1_region_fail:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
int remove_pps_interrupt_info_device_node(struct DWC_ETH_QOS_prv_data *pdata)
|
||||
{
|
||||
cdev_del(pdata->avb_class_a_cdev);
|
||||
device_destroy(pdata->avb_class_a_class, pdata->avb_class_a_dev_t);
|
||||
class_destroy(pdata->avb_class_a_class);
|
||||
unregister_chrdev_region(pdata->avb_class_a_dev_t, 1);
|
||||
pdata->avb_class_a_cdev = NULL;
|
||||
pdata->avb_class_a_class = NULL;
|
||||
|
||||
cdev_del(pdata->avb_class_b_cdev);
|
||||
device_destroy(pdata->avb_class_b_class, pdata->avb_class_b_dev_t);
|
||||
class_destroy(pdata->avb_class_b_class);
|
||||
unregister_chrdev_region(pdata->avb_class_b_dev_t, 1);
|
||||
pdata->avb_class_b_cdev = NULL;
|
||||
pdata->avb_class_b_class = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,381 @@
|
||||
/* Copyright (c) 2017, 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.
|
||||
*
|
||||
* This file contain content copied from Synopsis driver,
|
||||
* provided under the license below
|
||||
*/
|
||||
/* =========================================================================
|
||||
* The Synopsys DWC ETHER QOS Software Driver and documentation (hereinafter
|
||||
* "Software") is an unsupported proprietary work of Synopsys, Inc. unless
|
||||
* otherwise expressly agreed to in writing between Synopsys and you.
|
||||
*
|
||||
* The Software IS NOT an item of Licensed Software or Licensed Product under
|
||||
* any End User Software License Agreement or Agreement for Licensed Product
|
||||
* with Synopsys or any supplement thereto. Permission is hereby granted,
|
||||
* free of charge, to any person obtaining a copy of this software annotated
|
||||
* with this license and the Software, to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject
|
||||
* to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* =========================================================================
|
||||
*/
|
||||
|
||||
/*!@file: DWC_ETH_QOS_ptp.c
|
||||
* @brief: Driver functions.
|
||||
*/
|
||||
#include "DWC_ETH_QOS_yheader.h"
|
||||
#include "DWC_ETH_QOS_yapphdr.h"
|
||||
#ifdef CONFIG_PPS_OUTPUT
|
||||
extern int ETH_PPSOUT_Config(struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data_struct* req);
|
||||
extern void DWC_ETH_QOS_pps_timer_init(struct ifr_data_struct* req);
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
* \brief API to adjust the frequency of hardware clock.
|
||||
*
|
||||
* \details This function is used to adjust the frequency of the
|
||||
* hardware clock.
|
||||
*
|
||||
* \param[in] ptp – pointer to ptp_clock_info structure.
|
||||
* \param[in] delta – desired period change in parts per billion.
|
||||
*
|
||||
* \return int
|
||||
*
|
||||
* \retval 0 on success and -ve number on failure.
|
||||
*/
|
||||
|
||||
static int DWC_ETH_QOS_adjust_freq(struct ptp_clock_info *ptp, s32 ppb)
|
||||
{
|
||||
struct DWC_ETH_QOS_prv_data *pdata =
|
||||
container_of(ptp, struct DWC_ETH_QOS_prv_data, ptp_clock_ops);
|
||||
struct hw_if_struct *hw_if = &pdata->hw_if;
|
||||
unsigned long flags;
|
||||
u64 adj;
|
||||
u32 diff, addend;
|
||||
int neg_adj = 0;
|
||||
|
||||
DBGPR_PTP("-->DWC_ETH_QOS_adjust_freq: %d\n", ppb);
|
||||
|
||||
if (ppb < 0) {
|
||||
neg_adj = 1;
|
||||
ppb = -ppb;
|
||||
}
|
||||
|
||||
addend = pdata->default_addend;
|
||||
adj = addend;
|
||||
adj *= ppb;
|
||||
/* div_u64 will divided the "adj" by "1000000000ULL"
|
||||
* and return the quotient.
|
||||
*/
|
||||
diff = div_u64(adj, 1000000000ULL);
|
||||
addend = neg_adj ? (addend - diff) : (addend + diff);
|
||||
|
||||
spin_lock_irqsave(&pdata->ptp_lock, flags);
|
||||
|
||||
hw_if->config_addend(addend);
|
||||
|
||||
spin_unlock_irqrestore(&pdata->ptp_lock, flags);
|
||||
|
||||
DBGPR_PTP("<--DWC_ETH_QOS_adjust_freq\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief API to adjust the hardware time.
|
||||
*
|
||||
* \details This function is used to shift/adjust the time of the
|
||||
* hardware clock.
|
||||
*
|
||||
* \param[in] ptp – pointer to ptp_clock_info structure.
|
||||
* \param[in] delta – desired change in nanoseconds.
|
||||
*
|
||||
* \return int
|
||||
*
|
||||
* \retval 0 on success and -ve number on failure.
|
||||
*/
|
||||
|
||||
static int DWC_ETH_QOS_adjust_time(struct ptp_clock_info *ptp, s64 delta)
|
||||
{
|
||||
struct DWC_ETH_QOS_prv_data *pdata =
|
||||
container_of(ptp, struct DWC_ETH_QOS_prv_data, ptp_clock_ops);
|
||||
struct hw_if_struct *hw_if = &pdata->hw_if;
|
||||
unsigned long flags;
|
||||
u32 sec, nsec;
|
||||
u32 quotient, reminder;
|
||||
int neg_adj = 0;
|
||||
|
||||
DBGPR_PTP("-->DWC_ETH_QOS_adjust_time: delta = %lld\n", delta);
|
||||
|
||||
if (delta < 0) {
|
||||
neg_adj = 1;
|
||||
delta = -delta;
|
||||
}
|
||||
|
||||
quotient = div_u64_rem(delta, 1000000000ULL, &reminder);
|
||||
sec = quotient;
|
||||
nsec = reminder;
|
||||
|
||||
spin_lock_irqsave(&pdata->ptp_lock, flags);
|
||||
|
||||
hw_if->adjust_systime(sec, nsec, neg_adj, pdata->one_nsec_accuracy);
|
||||
|
||||
spin_unlock_irqrestore(&pdata->ptp_lock, flags);
|
||||
|
||||
DBGPR_PTP("<--DWC_ETH_QOS_adjust_time\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief API to get the current time.
|
||||
*
|
||||
* \details This function is used to read the current time from the
|
||||
* hardware clock.
|
||||
*
|
||||
* \param[in] ptp – pointer to ptp_clock_info structure.
|
||||
* \param[in] ts – pointer to hold the time/result.
|
||||
*
|
||||
* \return int
|
||||
*
|
||||
* \retval 0 on success and -ve number on failure.
|
||||
*/
|
||||
|
||||
static int DWC_ETH_QOS_get_time(struct ptp_clock_info *ptp, struct timespec64 *ts)
|
||||
{
|
||||
struct DWC_ETH_QOS_prv_data *pdata =
|
||||
container_of(ptp, struct DWC_ETH_QOS_prv_data, ptp_clock_ops);
|
||||
struct hw_if_struct *hw_if = &pdata->hw_if;
|
||||
u64 ns;
|
||||
u32 reminder;
|
||||
unsigned long flags;
|
||||
|
||||
DBGPR_PTP("-->DWC_ETH_QOS_get_time\n");
|
||||
|
||||
spin_lock_irqsave(&pdata->ptp_lock, flags);
|
||||
|
||||
ns = hw_if->get_systime();
|
||||
|
||||
spin_unlock_irqrestore(&pdata->ptp_lock, flags);
|
||||
|
||||
ts->tv_sec = div_u64_rem(ns, 1000000000ULL, &reminder);
|
||||
ts->tv_nsec = reminder;
|
||||
|
||||
DBGPR_PTP("<--DWC_ETH_QOS_get_time: ts->tv_sec = %ld,", ts->tv_sec);
|
||||
DBGPR_PTP("ts->tv_nsec = %ld\n", ts->tv_nsec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief API to set the current time.
|
||||
*
|
||||
* \details This function is used to set the current time on the
|
||||
* hardware clock.
|
||||
*
|
||||
* \param[in] ptp – pointer to ptp_clock_info structure.
|
||||
* \param[in] ts – time value to set.
|
||||
*
|
||||
* \return int
|
||||
*
|
||||
* \retval 0 on success and -ve number on failure.
|
||||
*/
|
||||
|
||||
static int DWC_ETH_QOS_set_time(struct ptp_clock_info *ptp,
|
||||
const struct timespec64 *ts)
|
||||
{
|
||||
struct DWC_ETH_QOS_prv_data *pdata =
|
||||
container_of(ptp, struct DWC_ETH_QOS_prv_data, ptp_clock_ops);
|
||||
struct hw_if_struct *hw_if = &pdata->hw_if;
|
||||
unsigned long flags;
|
||||
|
||||
DBGPR_PTP("-->DWC_ETH_QOS_set_time: ts->tv_sec = %ld,", ts->tv_sec);
|
||||
DBGPR_PTP("ts->tv_nsec = %ld\n", ts->tv_nsec);
|
||||
|
||||
spin_lock_irqsave(&pdata->ptp_lock, flags);
|
||||
|
||||
hw_if->init_systime(ts->tv_sec, ts->tv_nsec);
|
||||
|
||||
spin_unlock_irqrestore(&pdata->ptp_lock, flags);
|
||||
|
||||
DBGPR_PTP("<--DWC_ETH_QOS_set_time\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief API to enable/disable an ancillary feature.
|
||||
*
|
||||
* \details This function is used to enable or disable an ancillary
|
||||
* device feature like PPS, PEROUT and EXTTS.
|
||||
*
|
||||
* \param[in] ptp – pointer to ptp_clock_info structure.
|
||||
* \param[in] rq – desired resource to enable or disable.
|
||||
* \param[in] on – caller passes one to enable or zero to disable.
|
||||
*
|
||||
* \return int
|
||||
*
|
||||
* \retval 0 on success and -ve(EINVAL or EOPNOTSUPP) number on failure.
|
||||
*/
|
||||
|
||||
static int DWC_ETH_QOS_enable(struct ptp_clock_info *ptp,
|
||||
struct ptp_clock_request *rq, int on)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* structure describing a PTP hardware clock.
|
||||
*/
|
||||
static struct ptp_clock_info DWC_ETH_QOS_ptp_clock_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "DWC_ETH_QOS_clk",
|
||||
.max_adj = DWC_ETH_QOS_SYSCLOCK,
|
||||
/* the max possible frequency adjustment, in parts per billion */
|
||||
.n_alarm = 0, /* the number of programmable alarms */
|
||||
.n_ext_ts = 0, /* the number of externel time stamp channels */
|
||||
.n_per_out = 0, /* the number of programmable periodic signals */
|
||||
.pps = 0, /* indicates whether the clk supports a PPS callback */
|
||||
.adjfreq = DWC_ETH_QOS_adjust_freq,
|
||||
.adjtime = DWC_ETH_QOS_adjust_time,
|
||||
.gettime64 = DWC_ETH_QOS_get_time,
|
||||
.settime64 = DWC_ETH_QOS_set_time,
|
||||
.enable = DWC_ETH_QOS_enable,
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief API to register ptp clock driver.
|
||||
*
|
||||
* \details This function is used to register the ptp clock
|
||||
* driver to kernel. It also does some housekeeping work.
|
||||
*
|
||||
* \param[in] pdata – pointer to private data structure.
|
||||
*
|
||||
* \return int
|
||||
*
|
||||
* \retval 0 on success and -ve number on failure.
|
||||
*/
|
||||
|
||||
int DWC_ETH_QOS_ptp_init(struct DWC_ETH_QOS_prv_data *pdata)
|
||||
{
|
||||
int ret = 0;
|
||||
#ifdef CONFIG_PPS_OUTPUT
|
||||
struct ifr_data_struct req = {0};
|
||||
struct ETH_PPS_Config eth_pps_cfg = {0};
|
||||
#endif
|
||||
|
||||
DBGPR_PTP("-->DWC_ETH_QOS_ptp_init\n");
|
||||
|
||||
if (!pdata->hw_feat.tsstssel) {
|
||||
ret = -1;
|
||||
pdata->ptp_clock = NULL;
|
||||
pr_alert("No PTP supports in HW\n"
|
||||
"Aborting PTP clock driver registration\n");
|
||||
goto no_hw_ptp;
|
||||
}
|
||||
|
||||
DWC_ETH_QOS_enable_ptp_clk(&pdata->pdev->dev);
|
||||
|
||||
spin_lock_init(&pdata->ptp_lock);
|
||||
|
||||
pdata->ptp_clock_ops = DWC_ETH_QOS_ptp_clock_ops;
|
||||
|
||||
pdata->ptp_clock = ptp_clock_register(&pdata->ptp_clock_ops,
|
||||
&pdata->pdev->dev);
|
||||
|
||||
if (IS_ERR(pdata->ptp_clock)) {
|
||||
pdata->ptp_clock = NULL;
|
||||
pr_alert("ptp_clock_register() failed\n");
|
||||
} else {
|
||||
pr_alert("Added PTP HW clock successfully\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPS_OUTPUT
|
||||
if (pdata->res_data->pps_lpass_conn_en) {
|
||||
/*Configuring PPS0 PPS output frequency to defualt 19.2 Mhz*/
|
||||
eth_pps_cfg.ppsout_ch = 0;
|
||||
eth_pps_cfg.ptpclk_freq = DWC_ETH_QOS_DEFAULT_PTP_CLOCK;
|
||||
eth_pps_cfg.ppsout_freq = DWC_ETH_QOS_DEFAULT_LPASS_PPS_FREQUENCY;
|
||||
eth_pps_cfg.ppsout_start = 1;
|
||||
eth_pps_cfg.ppsout_duty = 50;
|
||||
req.ptr = (void*)ð_pps_cfg;
|
||||
|
||||
DWC_ETH_QOS_pps_timer_init(&req);
|
||||
ret = ETH_PPSOUT_Config(pdata, &req);
|
||||
}
|
||||
#endif
|
||||
|
||||
DBGPR_PTP("<--DWC_ETH_QOS_ptp_init\n");
|
||||
|
||||
return ret;
|
||||
|
||||
no_hw_ptp:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief API to unregister ptp clock driver.
|
||||
*
|
||||
* \details This function is used to remove/unregister the ptp
|
||||
* clock driver from the kernel.
|
||||
*
|
||||
* \param[in] pdata – pointer to private data structure.
|
||||
*
|
||||
* \return void
|
||||
*/
|
||||
|
||||
void DWC_ETH_QOS_ptp_remove(struct DWC_ETH_QOS_prv_data *pdata)
|
||||
{
|
||||
DBGPR_PTP("-->DWC_ETH_QOS_ptp_remove\n");
|
||||
|
||||
if (pdata->ptp_clock) {
|
||||
ptp_clock_unregister(pdata->ptp_clock);
|
||||
pr_alert("Removed PTP HW clock successfully\n");
|
||||
}
|
||||
|
||||
DWC_ETH_QOS_disable_ptp_clk(&pdata->pdev->dev);
|
||||
|
||||
DBGPR_PTP("<--DWC_ETH_QOS_ptp_remove\n");
|
||||
}
|
||||
/*!
|
||||
* \brief API to find the PHC index.
|
||||
*
|
||||
* \details This function is used to find the PHC index from Linux subsystem
|
||||
*
|
||||
* \param[in] pdata ??? pointer to private data structure.
|
||||
*
|
||||
* \return void
|
||||
*/
|
||||
|
||||
int DWC_ETH_QOS_phc_index(struct DWC_ETH_QOS_prv_data *pdata)
|
||||
{
|
||||
DBGPR_PTP("Fetching PHC index \n");
|
||||
if (pdata->ptp_clock)
|
||||
return ptp_clock_index(pdata->ptp_clock);
|
||||
else
|
||||
return -1;
|
||||
}
|
@@ -0,0 +1,680 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/*!@file: DWC_ETH_QOS_rgmii_io_macro.c
|
||||
* @brief: RGMII IO MACRO functions.
|
||||
*/
|
||||
#include "DWC_ETH_QOS_yheader.h"
|
||||
#include "DWC_ETH_QOS_yrgmii_io_macro_regacc.h"
|
||||
|
||||
/* RGMII IO MACRO power on reset values */
|
||||
#define RGMII_IO_MACRO_CONFIG_POR_ARR_INDEX 0
|
||||
#define SDCC_HC_REG_DLL_CONFIG_POR_ARR_INDEX 1
|
||||
#define SDCC_HC_REG_DDR_CONFIG_POR_ARR_INDEX 2
|
||||
#define SDCC_HC_REG_DLL_CONFIG_2_POR_ARR_INDEX 3
|
||||
#define SDCC_USR_CTL_POR_ARR_INDEX 4
|
||||
#define RGMII_IO_MACRO_CONFIG_2_POR_ARR_INDEX 5
|
||||
|
||||
#define RGMII_IO_MACRO_DLL_POR_NUM_OF_REGS 6
|
||||
|
||||
#define RGMII_IO_MACRO_DLL_POR_REG_OFFSET_INDEX 0
|
||||
#define RGMII_IO_MACRO_DLL_POR_REG_DATA_INDEX 1
|
||||
|
||||
ULONG rgmii_io_macro_dll_por_values
|
||||
[EMAC_HW_vMAX][RGMII_IO_MACRO_DLL_POR_NUM_OF_REGS][2] = {
|
||||
[EMAC_HW_None] = {
|
||||
[RGMII_IO_MACRO_CONFIG_POR_ARR_INDEX] = { RGMII_IO_MACRO_CONFIG_RGOFFADDR_OFFSET, 0x0 },
|
||||
[SDCC_HC_REG_DLL_CONFIG_POR_ARR_INDEX] = { SDCC_HC_REG_DLL_CONFIG_RGOFFADDR_OFFSET, 0x0 },
|
||||
[SDCC_HC_REG_DDR_CONFIG_POR_ARR_INDEX] = { SDCC_HC_REG_DDR_CONFIG_RGOFFADDR_OFFSET, 0x0 },
|
||||
[SDCC_HC_REG_DLL_CONFIG_2_POR_ARR_INDEX] = { SDCC_HC_REG_DLL_CONFIG_2_RGOFFADDR_OFFSET, 0x0 },
|
||||
[SDCC_USR_CTL_POR_ARR_INDEX] = { SDCC_USR_CTL_RGOFFADDR_OFFSET, 0x0 },
|
||||
[RGMII_IO_MACRO_CONFIG_2_POR_ARR_INDEX] = { RGMII_IO_MACRO_CONFIG_2_RGOFFADDR_OFFSET, 0x0 },
|
||||
},
|
||||
[EMAC_HW_v2_0_0] = {
|
||||
[RGMII_IO_MACRO_CONFIG_POR_ARR_INDEX] = { RGMII_IO_MACRO_CONFIG_RGOFFADDR_OFFSET, 0x40C01343 },
|
||||
[SDCC_HC_REG_DLL_CONFIG_POR_ARR_INDEX] = { SDCC_HC_REG_DLL_CONFIG_RGOFFADDR_OFFSET, 0x2004642C },
|
||||
[SDCC_HC_REG_DDR_CONFIG_POR_ARR_INDEX] = { SDCC_HC_REG_DDR_CONFIG_RGOFFADDR_OFFSET, 0x00000000 },
|
||||
[SDCC_HC_REG_DLL_CONFIG_2_POR_ARR_INDEX] = { SDCC_HC_REG_DLL_CONFIG_2_RGOFFADDR_OFFSET, 0x00200000 },
|
||||
[SDCC_USR_CTL_POR_ARR_INDEX] = { SDCC_USR_CTL_RGOFFADDR_OFFSET, 0x00000000 },
|
||||
[RGMII_IO_MACRO_CONFIG_2_POR_ARR_INDEX] = { RGMII_IO_MACRO_CONFIG_2_RGOFFADDR_OFFSET, 0x00002060 },
|
||||
},
|
||||
[EMAC_HW_v2_1_0] = {
|
||||
[RGMII_IO_MACRO_CONFIG_POR_ARR_INDEX] = { RGMII_IO_MACRO_CONFIG_RGOFFADDR_OFFSET, 0x40C01343 },
|
||||
[SDCC_HC_REG_DLL_CONFIG_POR_ARR_INDEX] = { SDCC_HC_REG_DLL_CONFIG_RGOFFADDR_OFFSET, 0x2004642C },
|
||||
[SDCC_HC_REG_DDR_CONFIG_POR_ARR_INDEX] = { SDCC_HC_REG_DDR_CONFIG_RGOFFADDR_OFFSET, 0x00000000 },
|
||||
[SDCC_HC_REG_DLL_CONFIG_2_POR_ARR_INDEX] = { SDCC_HC_REG_DLL_CONFIG_2_RGOFFADDR_OFFSET, 0x00200000 },
|
||||
[SDCC_USR_CTL_POR_ARR_INDEX] = { SDCC_USR_CTL_RGOFFADDR_OFFSET, 0x00010800 },
|
||||
[RGMII_IO_MACRO_CONFIG_2_POR_ARR_INDEX] = { RGMII_IO_MACRO_CONFIG_2_RGOFFADDR_OFFSET, 0x00002060 },
|
||||
},
|
||||
[EMAC_HW_v2_1_1] = {
|
||||
[RGMII_IO_MACRO_CONFIG_POR_ARR_INDEX] = { RGMII_IO_MACRO_CONFIG_RGOFFADDR_OFFSET, 0x40C01343 },
|
||||
[SDCC_HC_REG_DLL_CONFIG_POR_ARR_INDEX] = { SDCC_HC_REG_DLL_CONFIG_RGOFFADDR_OFFSET, 0x2004642C },
|
||||
[SDCC_HC_REG_DDR_CONFIG_POR_ARR_INDEX] = { SDCC_HC_REG_DDR_CONFIG_RGOFFADDR_OFFSET, 0x00000000 },
|
||||
[SDCC_HC_REG_DLL_CONFIG_2_POR_ARR_INDEX] = { SDCC_HC_REG_DLL_CONFIG_2_RGOFFADDR_OFFSET, 0x00200000 },
|
||||
[SDCC_USR_CTL_POR_ARR_INDEX] = { SDCC_USR_CTL_RGOFFADDR_OFFSET, 0x00000000 },
|
||||
[RGMII_IO_MACRO_CONFIG_2_POR_ARR_INDEX] = { RGMII_IO_MACRO_CONFIG_2_RGOFFADDR_OFFSET, 0x00002060 },
|
||||
},
|
||||
[EMAC_HW_v2_1_2] = {
|
||||
[RGMII_IO_MACRO_CONFIG_POR_ARR_INDEX] = { RGMII_IO_MACRO_CONFIG_RGOFFADDR_OFFSET, 0x40C01343 },
|
||||
[SDCC_HC_REG_DLL_CONFIG_POR_ARR_INDEX] = { SDCC_HC_REG_DLL_CONFIG_RGOFFADDR_OFFSET, 0x2004642C },
|
||||
[SDCC_HC_REG_DDR_CONFIG_POR_ARR_INDEX] = { SDCC_HC_REG_DDR_CONFIG_RGOFFADDR_OFFSET, 0x00000000 },
|
||||
[SDCC_HC_REG_DLL_CONFIG_2_POR_ARR_INDEX] = { SDCC_HC_REG_DLL_CONFIG_2_RGOFFADDR_OFFSET, 0x00200000 },
|
||||
[SDCC_USR_CTL_POR_ARR_INDEX] = { SDCC_USR_CTL_RGOFFADDR_OFFSET, 0x00000000 },
|
||||
[RGMII_IO_MACRO_CONFIG_2_POR_ARR_INDEX] = { RGMII_IO_MACRO_CONFIG_2_RGOFFADDR_OFFSET, 0x00002060 },
|
||||
},
|
||||
[EMAC_HW_v2_2_0] = {
|
||||
[RGMII_IO_MACRO_CONFIG_POR_ARR_INDEX] = { RGMII_IO_MACRO_CONFIG_RGOFFADDR_OFFSET, 0x00C01343 },
|
||||
[SDCC_HC_REG_DLL_CONFIG_POR_ARR_INDEX] = { SDCC_HC_REG_DLL_CONFIG_RGOFFADDR_OFFSET, 0x6004642C },
|
||||
[SDCC_HC_REG_DDR_CONFIG_POR_ARR_INDEX] = { SDCC_HC_REG_DDR_CONFIG_RGOFFADDR_OFFSET, 0x00000000 },
|
||||
[SDCC_HC_REG_DLL_CONFIG_2_POR_ARR_INDEX] = { SDCC_HC_REG_DLL_CONFIG_2_RGOFFADDR_OFFSET, 0x00200000 },
|
||||
[SDCC_USR_CTL_POR_ARR_INDEX] = { SDCC_USR_CTL_RGOFFADDR_OFFSET, 0x00010800 },
|
||||
[RGMII_IO_MACRO_CONFIG_2_POR_ARR_INDEX] = { RGMII_IO_MACRO_CONFIG_2_RGOFFADDR_OFFSET, 0x00002060 },
|
||||
},
|
||||
[EMAC_HW_v2_3_0] = {
|
||||
[RGMII_IO_MACRO_CONFIG_POR_ARR_INDEX] = { RGMII_IO_MACRO_CONFIG_RGOFFADDR_OFFSET, 0x00C01343 },
|
||||
[SDCC_HC_REG_DLL_CONFIG_POR_ARR_INDEX] = { SDCC_HC_REG_DLL_CONFIG_RGOFFADDR_OFFSET, 0x2004642C },
|
||||
[SDCC_HC_REG_DDR_CONFIG_POR_ARR_INDEX] = { SDCC_HC_REG_DDR_CONFIG_RGOFFADDR_OFFSET, 0x00000000 },
|
||||
[SDCC_HC_REG_DLL_CONFIG_2_POR_ARR_INDEX] = { SDCC_HC_REG_DLL_CONFIG_2_RGOFFADDR_OFFSET, 0x00200000 },
|
||||
[SDCC_USR_CTL_POR_ARR_INDEX] = { SDCC_USR_CTL_RGOFFADDR_OFFSET, 0x00010800 },
|
||||
[RGMII_IO_MACRO_CONFIG_2_POR_ARR_INDEX] = { RGMII_IO_MACRO_CONFIG_2_RGOFFADDR_OFFSET, 0x00002060 },
|
||||
},
|
||||
[EMAC_HW_v2_3_1] = {
|
||||
[RGMII_IO_MACRO_CONFIG_POR_ARR_INDEX] = { RGMII_IO_MACRO_CONFIG_RGOFFADDR_OFFSET, 0x40C01343 },
|
||||
[SDCC_HC_REG_DLL_CONFIG_POR_ARR_INDEX] = { SDCC_HC_REG_DLL_CONFIG_RGOFFADDR_OFFSET, 0x2004642C },
|
||||
[SDCC_HC_REG_DDR_CONFIG_POR_ARR_INDEX] = { SDCC_HC_REG_DDR_CONFIG_RGOFFADDR_OFFSET, 0x00000000 },
|
||||
[SDCC_HC_REG_DLL_CONFIG_2_POR_ARR_INDEX] = { SDCC_HC_REG_DLL_CONFIG_2_RGOFFADDR_OFFSET, 0x00200000 },
|
||||
[SDCC_USR_CTL_POR_ARR_INDEX] = { SDCC_USR_CTL_RGOFFADDR_OFFSET, 0x00000000 },
|
||||
[RGMII_IO_MACRO_CONFIG_2_POR_ARR_INDEX] = { RGMII_IO_MACRO_CONFIG_2_RGOFFADDR_OFFSET, 0x00002060 },
|
||||
},
|
||||
[EMAC_HW_v2_3_2] = {
|
||||
[RGMII_IO_MACRO_CONFIG_POR_ARR_INDEX] = { RGMII_IO_MACRO_CONFIG_RGOFFADDR_OFFSET, 0x40C01343 },
|
||||
[SDCC_HC_REG_DLL_CONFIG_POR_ARR_INDEX] = { SDCC_HC_REG_DLL_CONFIG_RGOFFADDR_OFFSET, 0x2004642C },
|
||||
[SDCC_HC_REG_DDR_CONFIG_POR_ARR_INDEX] = { SDCC_HC_REG_DDR_CONFIG_RGOFFADDR_OFFSET, 0x00000000 },
|
||||
[SDCC_HC_REG_DLL_CONFIG_2_POR_ARR_INDEX] = { SDCC_HC_REG_DLL_CONFIG_2_RGOFFADDR_OFFSET, 0x00200000 },
|
||||
[SDCC_USR_CTL_POR_ARR_INDEX] = { SDCC_USR_CTL_RGOFFADDR_OFFSET, 0x00000000 },
|
||||
[RGMII_IO_MACRO_CONFIG_2_POR_ARR_INDEX] = { RGMII_IO_MACRO_CONFIG_2_RGOFFADDR_OFFSET, 0x00002060 },
|
||||
},
|
||||
};
|
||||
|
||||
/* SDCDC DLL initialization */
|
||||
/*!
|
||||
* \brief Initialize the SDCDC
|
||||
*
|
||||
* \details This function will write to the various fields in
|
||||
* SDCC_HC_REG_DLL_CONFIG register for the DLL
|
||||
* initialization
|
||||
*\return Y_SUCCESS
|
||||
*/
|
||||
int DWC_ETH_QOS_rgmii_io_macro_sdcdc_init(struct DWC_ETH_QOS_prv_data *pdata)
|
||||
{
|
||||
int reg_val = 0;
|
||||
ULONG RETRYCOUNT = 1000;
|
||||
ULONG current_cnt = 0;
|
||||
volatile ULONG VARDLL_LOCK;
|
||||
EMACDBG("Enter\n");
|
||||
|
||||
/* Write 1 to DLL_RST bit of SDCC_HC_REG_DLL_CONFIG register */
|
||||
SDCC_HC_DLL_RST_UDFWR(0x1);
|
||||
|
||||
/* Write 1 to PDN bit of SDCC_HC_REG_DLL_CONFIG register */
|
||||
SDCC_HC_PDN_UDFWR(0x1);
|
||||
|
||||
/* Write 0 to DLL_RST bit of SDCC_HC_REG_DLL_CONFIG register */
|
||||
SDCC_HC_DLL_RST_UDFWR(0x0);
|
||||
|
||||
/* Write 0 to PDN bit of SDCC_HC_REG_DLL_CONFIG register */
|
||||
SDCC_HC_PDN_UDFWR(0x0);
|
||||
|
||||
/* DLL RST=0 and PDN=0 are sufficient for RGMII_ID 10/100 Mbps mode */
|
||||
if (pdata->speed == SPEED_100 || pdata->speed == SPEED_10) {
|
||||
EMACDBG("Bail out\n");
|
||||
return Y_SUCCESS;
|
||||
}
|
||||
/* Write 1 to DLL_EN */
|
||||
SDCC_HC_DLL_EN_UDFWR(0x1);
|
||||
|
||||
/* Write 1 to CK_OUT_EN */
|
||||
SDCC_HC_CK_OUT_EN_UDFWR(0x1);
|
||||
|
||||
SDCC_USR_CTL_RGRD(reg_val);
|
||||
reg_val &= ~(0x7UL<<24);
|
||||
reg_val |= (0x4UL<<24);
|
||||
SDCC_USR_CTL_RGWR(reg_val);
|
||||
|
||||
/* Wait until DLL_LOCK bit of SDC4_STATUS register is 1 */
|
||||
while (1) {
|
||||
if (current_cnt > RETRYCOUNT)
|
||||
return -Y_FAILURE;
|
||||
|
||||
SDC4_STATUS_DLL_LOCK_STS_UDFRD(VARDLL_LOCK);
|
||||
if (VARDLL_LOCK == 1) {
|
||||
EMACDBG("DLL lock status bit set. DLL init successful\n");
|
||||
break;
|
||||
}
|
||||
|
||||
current_cnt++;
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
EMACDBG("Exit\n");
|
||||
return Y_SUCCESS;
|
||||
}
|
||||
|
||||
/* SDCDC low power mode */
|
||||
/*!
|
||||
* \brief Put SDCDC in the lowest power consumption mode
|
||||
*
|
||||
* \details This function will write to the PDN field in
|
||||
* SDCC_HC_REG_DLL_CONFIG register to enable low power mode
|
||||
*
|
||||
*\return 0 on success and -ve on failure.
|
||||
*/
|
||||
int DWC_ETH_QOS_rgmii_io_macro_sdcdc_enable_lp_mode(void)
|
||||
{
|
||||
EMACDBG("Enter\n");
|
||||
/* Write 1 to PDN bit of SDCC_HC_REG_DLL_CONFIG register */
|
||||
SDCC_HC_PDN_UDFWR(0x1);
|
||||
EMACDBG("Exit\n");
|
||||
return Y_SUCCESS;
|
||||
}
|
||||
|
||||
/* SDCDC DLL configuration */
|
||||
/*!
|
||||
* \brief Configure SDCDC DLL config
|
||||
*
|
||||
* \details This function will write to the various fields in
|
||||
* SDCC_HC_REG_DLL_CONFIG and SDCC_HC_REG_DLL_CONFIG_2
|
||||
* registers for DLL configuration
|
||||
*
|
||||
*\return 0 on success and -1 on failure.
|
||||
*/
|
||||
int DWC_ETH_QOS_rgmii_io_macro_sdcdc_config(struct DWC_ETH_QOS_prv_data *pdata)
|
||||
{
|
||||
|
||||
ULONG RETRYCOUNT = 1000;
|
||||
ULONG current_cnt = 0;
|
||||
volatile ULONG VARCK_OUT_EN;
|
||||
EMACDBG("Enter\n");
|
||||
|
||||
if (pdata->emac_hw_version_type == EMAC_HW_v2_3_0) {
|
||||
/* Set CDR_EN bit to 1 */
|
||||
SDCC_HC_CDR_EN_UDFWR(0x1);
|
||||
} else {
|
||||
/* Set CDR_EN bit to 0 */
|
||||
SDCC_HC_CDR_EN_UDFWR(0x0);
|
||||
}
|
||||
|
||||
/* Set CDR_EXT_EN bit to 1 */
|
||||
SDCC_HC_CDR_EXT_EN_UDFWR(0x1);
|
||||
|
||||
/* Set CK_OUT_EN bit to 0 */
|
||||
SDCC_HC_CK_OUT_EN_UDFWR(0x0);
|
||||
|
||||
/* Set DLL_EN bit to 1 */
|
||||
SDCC_HC_DLL_EN_UDFWR(0x1);
|
||||
|
||||
if (pdata->emac_hw_version_type == EMAC_HW_v2_3_0) {
|
||||
/* Set MCLK_GATING_ENABLE bit to 0 */
|
||||
SDCC_HC_MCLK_GATING_ENABLE_UDFWR(0x0);
|
||||
|
||||
/* Set CDR_FINE_PHASE bit to 0 */
|
||||
SDCC_HC_CDR_FINE_PHASE_UDFWR(0x0);
|
||||
}
|
||||
|
||||
/* Wait until CK_OUT_EN bit of SDCC_HC_REG_DLL_CONFIG register
|
||||
* is 0
|
||||
*/
|
||||
while (1) {
|
||||
if (current_cnt > RETRYCOUNT)
|
||||
return -Y_FAILURE;
|
||||
|
||||
SDCC_HC_CK_OUT_EN_UDFRD(VARCK_OUT_EN);
|
||||
if (VARCK_OUT_EN == 0)
|
||||
break;
|
||||
|
||||
current_cnt++;
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
/* Set CK_OUT_EN bit to 1 */
|
||||
SDCC_HC_CK_OUT_EN_UDFWR(0x1);
|
||||
|
||||
/* Wait until CK_OUT_EN bit of SDCC_HC_REG_DLL_CONFIG register
|
||||
* is 1
|
||||
*/
|
||||
current_cnt = 0;
|
||||
while (1) {
|
||||
if (current_cnt > RETRYCOUNT)
|
||||
return -Y_FAILURE;
|
||||
|
||||
SDCC_HC_CK_OUT_EN_UDFRD(VARCK_OUT_EN);
|
||||
if (VARCK_OUT_EN == 1)
|
||||
break;
|
||||
|
||||
current_cnt++;
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
/* Write 1 to DDR_CAL_EN bit of SDCC_HC_REG_DLL_CONFIG_2
|
||||
* register
|
||||
*/
|
||||
SDCC_HC_CFG_2_DDR_CAL_EN_UDFWR(0x1);
|
||||
|
||||
if (pdata->emac_hw_version_type == EMAC_HW_v2_3_0) {
|
||||
/* Set DLL_CLOCK_DISABLE bit to 0 */
|
||||
SDCC_HC_CFG_2_DLL_CLOCK_DISABLE_UDFWR(0x0);
|
||||
|
||||
/* Set MCLK_FREQ_CALC bit to 26 */
|
||||
SDCC_HC_CFG_2_MCLK_FREQ_CALC_UDFWR(0x1A);
|
||||
|
||||
/* Set DDR_TRAFFIC_INIT_SEL bit to 0 */
|
||||
SDCC_HC_CFG_2_DDR_TRAFFIC_INIT_SEL_UDFWR(0x1);
|
||||
|
||||
/* Set DDR_TRAFFIC_INIT_SW bit to 0 */
|
||||
SDCC_HC_CFG_2_DDR_TRAFFIC_INIT_SW_UDFWR(0x1);
|
||||
}
|
||||
|
||||
|
||||
EMACDBG("Exit\n");
|
||||
return Y_SUCCESS;
|
||||
}
|
||||
|
||||
/* SDCC DLL Bypass mode programming */
|
||||
/*!
|
||||
* \brief Enable SDCC DLL Bypass mode programming
|
||||
*
|
||||
* \details This function will write to the PDN field in
|
||||
* SDCC_HC_REG_DLL_CONFIG register and bypass bit in
|
||||
* SDCC_DLL_TEST_CTL register
|
||||
*
|
||||
*\return 0 on success
|
||||
*/
|
||||
int DWC_ETH_QOS_sdcc_set_bypass_mode(void)
|
||||
{
|
||||
EMACDBG("Enter\n");
|
||||
/* Write 1 to PDN bit of SDCC_HC_REG_DLL_CONFIG register */
|
||||
SDCC_HC_PDN_UDFWR(0x1);
|
||||
|
||||
/* Write 1 to bypass bit of SDCC_USR_CTL register */
|
||||
SDCC_USR_CTL_BYPASS_MODE_UDFWR(0x1);
|
||||
|
||||
EMACDBG("Exit\n");
|
||||
return Y_SUCCESS;
|
||||
}
|
||||
|
||||
/* Programming rgmii_io_macro register for loopback mode */
|
||||
/*!
|
||||
* \brief Initialize the rgmii io macro block
|
||||
*
|
||||
* \details This function will write to the loopback
|
||||
* fields in RGMII_IO_MACRO_CONFIG RGMII_IO_MACRO_CONFIG_2
|
||||
* registers to set the RGMII loopback mode
|
||||
*
|
||||
*\return 0 on success
|
||||
*/
|
||||
static int DWC_ETH_QOS_set_rgmii_loopback_mode(UINT lb_mode)
|
||||
{
|
||||
EMACDBG("Enter\n");
|
||||
RGMII_CONFIG_2_TX_TO_RX_LOOPBACK_EN_UDFWR(lb_mode);
|
||||
EMACDBG("RGMII loopback mode set to = %d\n", lb_mode);
|
||||
|
||||
EMACDBG("Exit\n");
|
||||
return Y_SUCCESS;
|
||||
}
|
||||
|
||||
/* Programming rgmii_io_macro register for func_clk_en */
|
||||
/*!
|
||||
* \brief Initialize the rgmii io macro block
|
||||
*
|
||||
* \details This function will write to the func_clk_en
|
||||
* fields in RGMII_IO_MACRO_CONFIG
|
||||
*
|
||||
*\return 0 on success
|
||||
*/
|
||||
int DWC_ETH_QOS_set_rgmii_func_clk_en(void)
|
||||
{
|
||||
EMACDBG("Enter\n");
|
||||
RGMII_FUNC_CLK_EN_UDFWR(1);
|
||||
EMACDBG("Exit\n");
|
||||
return Y_SUCCESS;
|
||||
}
|
||||
|
||||
/* Programming rgmii_io_macro register initialization */
|
||||
/*!
|
||||
* \brief Initialize the rgmii io macro block
|
||||
*
|
||||
* \details This function will write to the various
|
||||
* fields in RGMII_IO_MACRO_CONFIG register to set the RGMII mode
|
||||
*
|
||||
*\return 0 on success
|
||||
*/
|
||||
int DWC_ETH_QOS_rgmii_io_macro_init(struct DWC_ETH_QOS_prv_data *pdata)
|
||||
{
|
||||
uint loopback_mode = 0;
|
||||
uint loopback_mode_en = 0;
|
||||
uint rgmii_data_divide_clk;
|
||||
ULONG data;
|
||||
|
||||
if (pdata->emac_hw_version_type == EMAC_HW_v2_3_0 || (pdata->emac_hw_version_type == EMAC_HW_v2_3_1)
|
||||
|| (pdata->emac_hw_version_type == EMAC_HW_v2_1_1)) {
|
||||
if(pdata->io_macro_phy_intf == RGMII_MODE)
|
||||
loopback_mode_en = 0x1;
|
||||
rgmii_data_divide_clk = 0x0;
|
||||
} else {
|
||||
loopback_mode_en = 0x0;
|
||||
rgmii_data_divide_clk = 0x1;
|
||||
}
|
||||
|
||||
EMACDBG("Enter\n");
|
||||
|
||||
/* Loopback is disabled */
|
||||
DWC_ETH_QOS_set_rgmii_loopback_mode(loopback_mode);
|
||||
|
||||
switch (pdata->io_macro_phy_intf) {
|
||||
case RGMII_MODE:
|
||||
/* Select RGMII interface */
|
||||
RGMII_INTF_SEL_UDFWR(0x0);
|
||||
|
||||
switch (pdata->speed) {
|
||||
case SPEED_1000:
|
||||
EMACDBG("Set RGMII registers for speed = %d\n", pdata->speed);
|
||||
if (pdata->io_macro_tx_mode_non_id){
|
||||
EMACDBG(
|
||||
"Set registers for Bypass mode = %d\n",
|
||||
pdata->io_macro_tx_mode_non_id);
|
||||
/* Enable DDR mode*/
|
||||
RGMII_DDR_MODE_UDFWR(0x1);
|
||||
RGMII_BYPASS_TX_ID_EN_UDFWR(0x1);
|
||||
RGMII_POS_NEG_DATA_SEL_UDFWR(0x0);
|
||||
RGMII_PROG_SWAP_UDFWR(0x0);
|
||||
RGMII_CONFIG_2_DATA_DIVIDE_CLK_SEL_UDFWR(rgmii_data_divide_clk);
|
||||
RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFWR(0x0);
|
||||
RGMII_CONFIG_2_RERVED_CONFIG_16_EN_UDFWR(0x0);
|
||||
/* Rx Path */
|
||||
RGMII_CONFIG_2_RX_PROG_SWAP_UDFWR(0x1);
|
||||
RGMII_LOOPBACK_EN_UDFWR(loopback_mode_en);
|
||||
if (pdata->emac_hw_version_type == EMAC_HW_v2_1_0 ||
|
||||
pdata->emac_hw_version_type == EMAC_HW_v2_1_2 ||
|
||||
(pdata->emac_hw_version_type == EMAC_HW_v2_3_1) ||
|
||||
pdata->emac_hw_version_type == EMAC_HW_v2_1_1)
|
||||
RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFWR(0x1);
|
||||
} else {
|
||||
/* Enable DDR mode*/
|
||||
RGMII_DDR_MODE_UDFWR(0x1);
|
||||
RGMII_BYPASS_TX_ID_EN_UDFWR(0x0);
|
||||
RGMII_POS_NEG_DATA_SEL_UDFWR(0x1);
|
||||
/* RGMII_TX_POS and RGMII_TX_NEG input pins are swapped
|
||||
* based on the programmable swap control bit
|
||||
*/
|
||||
RGMII_PROG_SWAP_UDFWR(0x1);
|
||||
RGMII_CONFIG_2_DATA_DIVIDE_CLK_SEL_UDFWR(rgmii_data_divide_clk);
|
||||
RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFWR(0x1);
|
||||
RGMII_CONFIG_2_RERVED_CONFIG_16_EN_UDFWR(0x0);
|
||||
/* If data arrives at positive edge or if data is
|
||||
* delayed by 1.5ns/ 2ns then write 1 to RX_PROG_SWAP
|
||||
* bit of register EMAC_RGMII_IO_MACRO_CONFIG_2
|
||||
*/
|
||||
RGMII_CONFIG_2_RX_PROG_SWAP_UDFWR(0x1);
|
||||
|
||||
/* Program PRG_RCLK_DLY to 52 ns for a required delay of 2 ns on HANA AU */
|
||||
if (pdata->emac_hw_version_type == EMAC_HW_v2_1_0 ||
|
||||
pdata->emac_hw_version_type == EMAC_HW_v2_1_2)
|
||||
SDCC_HC_PRG_RCLK_DLY_UDFWR(52);
|
||||
else if (pdata->emac_hw_version_type == EMAC_HW_v2_3_1)
|
||||
SDCC_HC_PRG_RCLK_DLY_UDFWR(104);
|
||||
else if (pdata->emac_hw_version_type == EMAC_HW_v2_1_1)
|
||||
SDCC_HC_PRG_RCLK_DLY_UDFWR(130);
|
||||
else { /* Program PRG_RCLK_DLY to 57 for a required delay of 1.8 ns */
|
||||
SDCC_HC_PRG_RCLK_DLY_UDFWR(57);
|
||||
}
|
||||
SDCC_HC_REG_DDR_CONFIG_RGRD(data);
|
||||
data |= (1 << 31);
|
||||
SDCC_HC_REG_DDR_CONFIG_RGWR(data);
|
||||
RGMII_LOOPBACK_EN_UDFWR(loopback_mode_en);
|
||||
}
|
||||
break;
|
||||
|
||||
case SPEED_100:
|
||||
EMACDBG("Set RGMII registers for speed = %d\n", pdata->speed);
|
||||
|
||||
if (pdata->io_macro_tx_mode_non_id) {
|
||||
EMACDBG("Set registers for Bypass mode = %d\n",
|
||||
pdata->io_macro_tx_mode_non_id);
|
||||
RGMII_DDR_MODE_UDFWR(0x0);
|
||||
RGMII_BYPASS_TX_ID_EN_UDFWR(0x1);
|
||||
RGMII_POS_NEG_DATA_SEL_UDFWR(0x0);
|
||||
RGMII_PROG_SWAP_UDFWR(0x0);
|
||||
RGMII_CONFIG_2_DATA_DIVIDE_CLK_SEL_UDFWR(rgmii_data_divide_clk);
|
||||
RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFWR(0x0);
|
||||
|
||||
RGMII_MAX_SPD_PRG_2_UDFWR(0x1);
|
||||
RGMII_CONFIG_2_RERVED_CONFIG_16_EN_UDFWR(0x1);
|
||||
/* Rx Path */
|
||||
RGMII_CONFIG_2_RX_PROG_SWAP_UDFWR(0x0);
|
||||
RGMII_LOOPBACK_EN_UDFWR(loopback_mode_en);
|
||||
if (pdata->emac_hw_version_type == EMAC_HW_v2_1_0 ||
|
||||
pdata->emac_hw_version_type == EMAC_HW_v2_1_2 ||
|
||||
(pdata->emac_hw_version_type == EMAC_HW_v2_3_1) ||
|
||||
pdata->emac_hw_version_type == EMAC_HW_v2_1_1)
|
||||
RGMII_CONFIG_2_RX_PROG_SWAP_UDFWR(0x1);
|
||||
if (pdata->emac_hw_version_type == EMAC_HW_v2_1_2 ||
|
||||
pdata->emac_hw_version_type == EMAC_HW_v2_1_1)
|
||||
RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFWR(0x1);
|
||||
} else{
|
||||
RGMII_DDR_MODE_UDFWR(0x1);
|
||||
RGMII_BYPASS_TX_ID_EN_UDFWR(0x1);
|
||||
RGMII_POS_NEG_DATA_SEL_UDFWR(0x0);
|
||||
RGMII_PROG_SWAP_UDFWR(0x0);
|
||||
RGMII_CONFIG_2_DATA_DIVIDE_CLK_SEL_UDFWR(rgmii_data_divide_clk);
|
||||
RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFWR(0x1);
|
||||
RGMII_MAX_SPD_PRG_2_UDFWR(0x1);
|
||||
RGMII_CONFIG_2_RERVED_CONFIG_16_EN_UDFWR(0x0);
|
||||
/* Rx Path */
|
||||
if (pdata->emac_hw_version_type == EMAC_HW_v2_3_0)
|
||||
RGMII_CONFIG_2_RX_PROG_SWAP_UDFWR(0x0);
|
||||
else
|
||||
RGMII_CONFIG_2_RX_PROG_SWAP_UDFWR(0x1);
|
||||
|
||||
SDCC_HC_EXT_PRG_RCLK_DLY_CODE_UDFWR(0x5);
|
||||
SDCC_HC_EXT_PRG_RCLK_DLY_UDFWR(0x3f);
|
||||
SDCC_HC_EXT_PRG_RCLK_DLY_EN_UDFWR(0x1);
|
||||
RGMII_LOOPBACK_EN_UDFWR(loopback_mode_en);
|
||||
}
|
||||
break;
|
||||
|
||||
case SPEED_10:
|
||||
EMACDBG("Set RGMII registers for speed = %d\n", pdata->speed);
|
||||
|
||||
if (pdata->io_macro_tx_mode_non_id) {
|
||||
EMACDBG("Set registers for Bypass mode = %d\n",
|
||||
pdata->io_macro_tx_mode_non_id);
|
||||
RGMII_DDR_MODE_UDFWR(0x0);
|
||||
RGMII_BYPASS_TX_ID_EN_UDFWR(0x1);
|
||||
RGMII_POS_NEG_DATA_SEL_UDFWR(0x0);
|
||||
RGMII_PROG_SWAP_UDFWR(0x0);
|
||||
RGMII_CONFIG_2_DATA_DIVIDE_CLK_SEL_UDFWR(rgmii_data_divide_clk);
|
||||
RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFWR(0x0);
|
||||
RGMII_MAX_SPD_PRG_9_UDFWR(0x13);
|
||||
RGMII_CONFIG_2_RERVED_CONFIG_16_EN_UDFWR(0x1);
|
||||
/* Rx Path */
|
||||
if (pdata->emac_hw_version_type == EMAC_HW_v2_3_1)
|
||||
RGMII_LOOPBACK_EN_UDFWR(loopback_mode_en);
|
||||
RGMII_CONFIG_2_RX_PROG_SWAP_UDFWR(0x0);
|
||||
RGMII_LOOPBACK_EN_UDFWR(loopback_mode_en);
|
||||
if (pdata->emac_hw_version_type == EMAC_HW_v2_1_0 ||
|
||||
pdata->emac_hw_version_type == EMAC_HW_v2_1_2 ||
|
||||
(pdata->emac_hw_version_type == EMAC_HW_v2_3_1) ||
|
||||
pdata->emac_hw_version_type == EMAC_HW_v2_1_1)
|
||||
RGMII_CONFIG_2_RX_PROG_SWAP_UDFWR(0x1);
|
||||
if (pdata->emac_hw_version_type == EMAC_HW_v2_1_2 ||
|
||||
pdata->emac_hw_version_type == EMAC_HW_v2_1_1)
|
||||
RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFWR(0x1);
|
||||
} else{
|
||||
RGMII_DDR_MODE_UDFWR(0x1);
|
||||
RGMII_BYPASS_TX_ID_EN_UDFWR(0x1);
|
||||
RGMII_POS_NEG_DATA_SEL_UDFWR(0x0);
|
||||
RGMII_PROG_SWAP_UDFWR(0x0);
|
||||
RGMII_CONFIG_2_DATA_DIVIDE_CLK_SEL_UDFWR(rgmii_data_divide_clk);
|
||||
RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFWR(0x1);
|
||||
RGMII_MAX_SPD_PRG_9_UDFWR(0x13);
|
||||
RGMII_CONFIG_2_RERVED_CONFIG_16_EN_UDFWR(0x0);
|
||||
|
||||
/* Rx Path */
|
||||
if (pdata->emac_hw_version_type == EMAC_HW_v2_3_0)
|
||||
RGMII_CONFIG_2_RX_PROG_SWAP_UDFWR(0x0);
|
||||
else
|
||||
RGMII_CONFIG_2_RX_PROG_SWAP_UDFWR(0x1);
|
||||
SDCC_HC_EXT_PRG_RCLK_DLY_CODE_UDFWR(0x5);
|
||||
SDCC_HC_EXT_PRG_RCLK_DLY_UDFWR(0x3f);
|
||||
SDCC_HC_EXT_PRG_RCLK_DLY_EN_UDFWR(0x1);
|
||||
RGMII_LOOPBACK_EN_UDFWR(loopback_mode_en);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
EMACDBG(
|
||||
"No RGMII register settings for link speed = %d\n",
|
||||
pdata->speed);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case RMII_MODE:
|
||||
EMACDBG("Set registers for RMII mode and speed = %d\n", pdata->speed);
|
||||
RGMII_INTF_SEL_UDFWR(0x01);
|
||||
RGMII_DDR_MODE_UDFWR(0x0);
|
||||
RGMII_BYPASS_TX_ID_EN_UDFWR(0x1);
|
||||
RGMII_POS_NEG_DATA_SEL_UDFWR(0x0);
|
||||
RGMII_PROG_SWAP_UDFWR(0x1);
|
||||
RGMII_CONFIG_2_DATA_DIVIDE_CLK_SEL_UDFWR(0x1);
|
||||
RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFWR(0x0);
|
||||
RGMII_CONFIG_2_CLK_DIVIDE_SEL_UDFWR(0x1);
|
||||
RGMII_MAX_SPD_PRG_2_UDFWR(0x1);
|
||||
RGMII_MAX_SPD_PRG_9_UDFWR(0x13);
|
||||
RGMII_CONFIG_2_RERVED_CONFIG_16_EN_UDFWR(0x0);
|
||||
if (pdata->emac_hw_version_type == EMAC_HW_v2_3_0 || (pdata->emac_hw_version_type == EMAC_HW_v2_3_1))
|
||||
RGMII_LOOPBACK_EN_UDFWR(0x0);
|
||||
else
|
||||
RGMII_LOOPBACK_EN_UDFWR(0x1);
|
||||
|
||||
break;
|
||||
|
||||
case MII_MODE:
|
||||
EMACDBG("Set registers for MII mode and speed = %d\n", pdata->speed);
|
||||
RGMII_INTF_SEL_UDFWR(0x2);
|
||||
RGMII_DDR_MODE_UDFWR(0x0);
|
||||
RGMII_BYPASS_TX_ID_EN_UDFWR(0x1);
|
||||
RGMII_POS_NEG_DATA_SEL_UDFWR(0x0);
|
||||
RGMII_PROG_SWAP_UDFWR(0x0);
|
||||
RGMII_CONFIG_2_DATA_DIVIDE_CLK_SEL_UDFWR(0x1);
|
||||
RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFWR(0x0);
|
||||
RGMII_CONFIG_2_RERVED_CONFIG_16_EN_UDFWR(0x1);
|
||||
if (pdata->emac_hw_version_type == EMAC_HW_v2_1_2 ||
|
||||
pdata->emac_hw_version_type == EMAC_HW_v2_1_1)
|
||||
RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFWR(0x1);
|
||||
if (pdata->emac_hw_version_type == EMAC_HW_v2_3_1)
|
||||
RGMII_LOOPBACK_EN_UDFWR(0x1);
|
||||
break;
|
||||
}
|
||||
|
||||
EMACDBG("Exit\n");
|
||||
return Y_SUCCESS;
|
||||
}
|
||||
|
||||
/* Programming IO macro and DLL registers with POR values */
|
||||
/*!
|
||||
* \brief Reset the IO MACRO and DLL blocks
|
||||
*
|
||||
* \details This function will write POR values to RGMII and
|
||||
* DLL registers.
|
||||
*
|
||||
*\return Y_SUCCESS
|
||||
*/
|
||||
int DWC_ETH_QOS_rgmii_io_macro_dll_reset(struct DWC_ETH_QOS_prv_data *pdata)
|
||||
{
|
||||
int index_of_reg;
|
||||
ULONG data, address;
|
||||
EMACDBG("Enter\n");
|
||||
|
||||
for (index_of_reg = 0 ; index_of_reg < RGMII_IO_MACRO_DLL_POR_NUM_OF_REGS; index_of_reg++) {
|
||||
address = RGMII_IO_BASE_ADDRESS
|
||||
+ rgmii_io_macro_dll_por_values
|
||||
[pdata->emac_hw_version_type]
|
||||
[index_of_reg]
|
||||
[RGMII_IO_MACRO_DLL_POR_REG_OFFSET_INDEX];
|
||||
data = rgmii_io_macro_dll_por_values
|
||||
[pdata->emac_hw_version_type]
|
||||
[index_of_reg]
|
||||
[RGMII_IO_MACRO_DLL_POR_REG_DATA_INDEX];
|
||||
iowrite32(data, (void *)address);
|
||||
}
|
||||
|
||||
DWC_ETH_QOS_set_rgmii_func_clk_en();
|
||||
|
||||
EMACDBG("Exit\n");
|
||||
return Y_SUCCESS;
|
||||
}
|
||||
|
||||
void dump_rgmii_io_macro_registers(void)
|
||||
{
|
||||
int reg_val;
|
||||
|
||||
pr_alert(
|
||||
"\n************* RGMII IO Macro Reg dump *************************\n");
|
||||
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(reg_val);
|
||||
pr_alert(
|
||||
"RGMII_IO_MACRO_CONFIG (0x%p) = %#x\n",
|
||||
RGMII_IO_MACRO_CONFIG_RGOFFADDR, reg_val);
|
||||
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(reg_val);
|
||||
pr_alert(
|
||||
"SDCC_HC_REG_DLL_CONFIG (0x%p) = %#x\n",
|
||||
SDCC_HC_REG_DLL_CONFIG_RGOFFADDR, reg_val);
|
||||
|
||||
SDCC_HC_REG_DDR_CONFIG_RGRD(reg_val);
|
||||
pr_alert(
|
||||
"SDCC_HC_REG_DDR_CONFIG (0x%p) = %#x\n",
|
||||
SDCC_HC_REG_DDR_CONFIG_RGOFFADDR, reg_val);
|
||||
|
||||
SDCC_HC_REG_DLL_CONFIG_2_RGRD(reg_val);
|
||||
pr_alert(
|
||||
"SDCC_HC_REG_DLL_CONFIG_2 (0x%p) = %#x\n",
|
||||
SDCC_HC_REG_DLL_CONFIG_2_RGOFFADDR, reg_val);
|
||||
|
||||
RGMII_IO_MACRO_CONFIG_2_RGRD(reg_val);
|
||||
pr_alert(
|
||||
"RGMII_IO_MACRO_CONFIG_2 (0x%p) = %#x\n",
|
||||
RGMII_IO_MACRO_CONFIG_2_RGOFFADDR, reg_val);
|
||||
|
||||
RGMII_IO_MACRO_DEBUG_1_RGRD(reg_val);
|
||||
pr_alert(
|
||||
"RGMII_IO_MACRO_DEBUG_1 (0x%p) = %#x\n",
|
||||
RGMII_IO_MACRO_DEBUG_1_RGOFFADDR, reg_val);
|
||||
|
||||
SDC4_STATUS_RGRD(reg_val);
|
||||
pr_alert(
|
||||
"SDC4_STATUS_RGRD (0x%p) = %#x\n",
|
||||
SDC4_STATUS_RGOFFADDR, reg_val);
|
||||
|
||||
SDCC_USR_CTL_RGRD(reg_val);
|
||||
pr_alert(
|
||||
"SDCC_USR_CTL_RGRD (0x%p) = %#x\n",
|
||||
SDCC_USR_CTL_RGOFFADDR, reg_val);
|
||||
|
||||
EMAC_SYSTEM_LOW_POWER_DEBUG_RGRD(reg_val);
|
||||
pr_alert(
|
||||
"EMAC_SYSTEM_LOW_POWER_DEBUG_RGRD (0x%p) = %#x\n",
|
||||
EMAC_SYSTEM_LOW_POWER_DEBUG_RGOFFADDR, reg_val);
|
||||
|
||||
pr_alert("\n****************************************************\n");
|
||||
}
|
@@ -0,0 +1,617 @@
|
||||
/* Copyright (c) 2017,2019, 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.
|
||||
*
|
||||
* This file contain content copied from Synopsis driver,
|
||||
* provided under the license below
|
||||
*/
|
||||
/* =========================================================================
|
||||
* The Synopsys DWC ETHER QOS Software Driver and documentation (hereinafter
|
||||
* "Software") is an unsupported proprietary work of Synopsys, Inc. unless
|
||||
* otherwise expressly agreed to in writing between Synopsys and you.
|
||||
*
|
||||
* The Software IS NOT an item of Licensed Software or Licensed Product under
|
||||
* any End User Software License Agreement or Agreement for Licensed Product
|
||||
* with Synopsys or any supplement thereto. Permission is hereby granted,
|
||||
* free of charge, to any person obtaining a copy of this software annotated
|
||||
* with this license and the Software, to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject
|
||||
* to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
* ========================================================================= */
|
||||
|
||||
#ifndef __DWC_ETH_QOS_YAPPHDR_H__
|
||||
|
||||
#define __DWC_ETH_QOS_YAPPHDR_H__
|
||||
|
||||
#define DWC_ETH_QOS_MAX_TX_QUEUE_CNT 8
|
||||
#define DWC_ETH_QOS_MAX_RX_QUEUE_CNT 8
|
||||
|
||||
#define CONFIG_PPS_OUTPUT // for PPS Output
|
||||
|
||||
/* Private IOCTL for handling device specific task */
|
||||
#define DWC_ETH_QOS_PRV_IOCTL SIOCDEVPRIVATE
|
||||
#define DWC_ETH_QOS_PRV_IOCTL_IPA SIOCDEVPRIVATE+1
|
||||
/* IOCTL cmd to eMAC to register the RX/TX properties with VLAN hdr*/
|
||||
enum{
|
||||
DWC_ETH_QOS_IPA_VLAN_DISABLE_CMD= 0,
|
||||
DWC_ETH_QOS_IPA_VLAN_ENABLE_CMD=1,
|
||||
};
|
||||
|
||||
#define DWC_ETH_QOS_POWERUP_MAGIC_CMD 1
|
||||
#define DWC_ETH_QOS_POWERDOWN_MAGIC_CMD 2
|
||||
#define DWC_ETH_QOS_POWERUP_REMOTE_WAKEUP_CMD 3
|
||||
#define DWC_ETH_QOS_POWERDOWN_REMOTE_WAKEUP_CMD 4
|
||||
|
||||
/* for TX and RX threshold configures */
|
||||
#define DWC_ETH_QOS_RX_THRESHOLD_CMD 5
|
||||
#define DWC_ETH_QOS_TX_THRESHOLD_CMD 6
|
||||
|
||||
/* for TX and RX Store and Forward mode configures */
|
||||
#define DWC_ETH_QOS_RSF_CMD 7
|
||||
#define DWC_ETH_QOS_TSF_CMD 8
|
||||
|
||||
/* for TX DMA Operate on Second Frame mode configures */
|
||||
#define DWC_ETH_QOS_OSF_CMD 9
|
||||
|
||||
/* for TX and RX PBL configures */
|
||||
#define DWC_ETH_QOS_TX_PBL_CMD 10
|
||||
#define DWC_ETH_QOS_RX_PBL_CMD 11
|
||||
|
||||
/* INCR and INCRX mode */
|
||||
#define DWC_ETH_QOS_INCR_INCRX_CMD 12
|
||||
|
||||
/* for MAC Double VLAN Processing config */
|
||||
#define DWC_ETH_QOS_DVLAN_TX_PROCESSING_CMD 13
|
||||
#define DWC_ETH_QOS_DVLAN_RX_PROCESSING_CMD 14
|
||||
#define DWC_ETH_QOS_SVLAN_CMD 15
|
||||
|
||||
/* Manju: Remove the below defines */
|
||||
/* RX/TX VLAN */
|
||||
/* #define DWC_ETH_QOS_RX_OUTER_VLAN_STRIPPING_CMD 13 */
|
||||
/* #define DWC_ETH_QOS_RX_INNER_VLAN_STRIPPING_CMD 14 */
|
||||
/* #define DWC_ETH_QOS_TX_VLAN_DESC_CMD 15 */
|
||||
/* #define DWC_ETH_QOS_TX_VLAN_REG_CMD 16 */
|
||||
|
||||
/* SA on TX */
|
||||
#define DWC_ETH_QOS_SA0_DESC_CMD 17
|
||||
#define DWC_ETH_QOS_SA1_DESC_CMD 18
|
||||
#define DWC_ETH_QOS_SA0_REG_CMD 19
|
||||
#define DWC_ETH_QOS_SA1_REG_CMD 20
|
||||
|
||||
/* CONTEX desc setup control */
|
||||
#define DWC_ETH_QOS_SETUP_CONTEXT_DESCRIPTOR 21
|
||||
|
||||
/* Packet generation */
|
||||
#define DWC_ETH_QOS_PG_TEST 22
|
||||
|
||||
/* TX/RX channel/queue count */
|
||||
#define DWC_ETH_QOS_GET_TX_QCNT 23
|
||||
#define DWC_ETH_QOS_GET_RX_QCNT 24
|
||||
|
||||
/* Line speed */
|
||||
#define DWC_ETH_QOS_GET_CONNECTED_SPEED 25
|
||||
|
||||
/* DCB/AVB algorithm */
|
||||
#define DWC_ETH_QOS_DCB_ALGORITHM 26
|
||||
#define DWC_ETH_QOS_AVB_ALGORITHM 27
|
||||
|
||||
/* RX split header */
|
||||
#define DWC_ETH_QOS_RX_SPLIT_HDR_CMD 28
|
||||
|
||||
/* L3/L4 filter */
|
||||
#define DWC_ETH_QOS_L3_L4_FILTER_CMD 29
|
||||
/* IPv4/6 and TCP/UDP filtering */
|
||||
#define DWC_ETH_QOS_IPV4_FILTERING_CMD 30
|
||||
#define DWC_ETH_QOS_IPV6_FILTERING_CMD 31
|
||||
#define DWC_ETH_QOS_UDP_FILTERING_CMD 32
|
||||
#define DWC_ETH_QOS_TCP_FILTERING_CMD 33
|
||||
/* VLAN filtering */
|
||||
#define DWC_ETH_QOS_VLAN_FILTERING_CMD 34
|
||||
/* L2 DA filtering */
|
||||
#define DWC_ETH_QOS_L2_DA_FILTERING_CMD 35
|
||||
/* ARP Offload */
|
||||
#define DWC_ETH_QOS_ARP_OFFLOAD_CMD 36
|
||||
/* for AXI PBL configures */
|
||||
#define DWC_ETH_QOS_AXI_PBL_CMD 37
|
||||
/* for AXI Write Outstanding Request Limit configures */
|
||||
#define DWC_ETH_QOS_AXI_WORL_CMD 38
|
||||
/* for AXI Read Outstanding Request Limit configures */
|
||||
#define DWC_ETH_QOS_AXI_RORL_CMD 39
|
||||
/* for MAC LOOPBACK configuration */
|
||||
#define DWC_ETH_QOS_MAC_LOOPBACK_MODE_CMD 40
|
||||
/* PFC(Priority Based Flow Control) mode */
|
||||
#define DWC_ETH_QOS_PFC_CMD 41
|
||||
/* for PTP OFFLOADING configuration */
|
||||
#define DWC_ETH_QOS_PTPOFFLOADING_CMD 42
|
||||
|
||||
/* To configure PPS output */
|
||||
#ifdef CONFIG_PPS_OUTPUT
|
||||
#define DWC_ETH_QOS_CONFIG_PTPCLK_CMD 43
|
||||
#define DWC_ETH_QOS_CONFIG_PPSOUT_CMD 44
|
||||
#endif
|
||||
|
||||
#define DWC_ETH_QOS_RWK_FILTER_LENGTH 8
|
||||
|
||||
/* List of command errors driver can set */
|
||||
#define DWC_ETH_QOS_NO_HW_SUPPORT -1
|
||||
#define DWC_ETH_QOS_CONFIG_FAIL -3
|
||||
#define DWC_ETH_QOS_CONFIG_SUCCESS 0
|
||||
|
||||
/* RX THRESHOLD operations */
|
||||
#define DWC_ETH_QOS_RX_THRESHOLD_32 0x1
|
||||
#define DWC_ETH_QOS_RX_THRESHOLD_64 0x0
|
||||
#define DWC_ETH_QOS_RX_THRESHOLD_96 0x2
|
||||
#define DWC_ETH_QOS_RX_THRESHOLD_128 0x3
|
||||
|
||||
/* TX THRESHOLD operations */
|
||||
#define DWC_ETH_QOS_TX_THRESHOLD_32 0x1
|
||||
#define DWC_ETH_QOS_TX_THRESHOLD_64 0x0
|
||||
#define DWC_ETH_QOS_TX_THRESHOLD_96 0x2
|
||||
#define DWC_ETH_QOS_TX_THRESHOLD_128 0x3
|
||||
#define DWC_ETH_QOS_TX_THRESHOLD_192 0x4
|
||||
#define DWC_ETH_QOS_TX_THRESHOLD_256 0x5
|
||||
#define DWC_ETH_QOS_TX_THRESHOLD_384 0x6
|
||||
#define DWC_ETH_QOS_TX_THRESHOLD_512 0x7
|
||||
|
||||
/* TX and RX Store and Forward Mode operations */
|
||||
#define DWC_ETH_QOS_RSF_DISABLE 0x0
|
||||
#define DWC_ETH_QOS_RSF_ENABLE 0x1
|
||||
|
||||
#define DWC_ETH_QOS_TSF_DISABLE 0x0
|
||||
#define DWC_ETH_QOS_TSF_ENABLE 0x1
|
||||
|
||||
/* TX DMA Operate on Second Frame operations */
|
||||
#define DWC_ETH_QOS_OSF_DISABLE 0x0
|
||||
#define DWC_ETH_QOS_OSF_ENABLE 0x1
|
||||
|
||||
/* INCR and INCRX mode */
|
||||
#define DWC_ETH_QOS_INCR_ENABLE 0x1
|
||||
#define DWC_ETH_QOS_INCRX_ENABLE 0x0
|
||||
|
||||
/* TX and RX PBL operations */
|
||||
#define DWC_ETH_QOS_PBL_1 1
|
||||
#define DWC_ETH_QOS_PBL_2 2
|
||||
#define DWC_ETH_QOS_PBL_4 4
|
||||
#define DWC_ETH_QOS_PBL_8 8
|
||||
#define DWC_ETH_QOS_PBL_16 16
|
||||
#define DWC_ETH_QOS_PBL_32 32
|
||||
#define DWC_ETH_QOS_PBL_64 64 /* 8 x 8 */
|
||||
#define DWC_ETH_QOS_PBL_128 128 /* 8 x 16 */
|
||||
#define DWC_ETH_QOS_PBL_256 256 /* 8 x 32 */
|
||||
|
||||
/* AXI operations */
|
||||
#define DWC_ETH_QOS_AXI_PBL_4 0x2
|
||||
#define DWC_ETH_QOS_AXI_PBL_8 0x6
|
||||
#define DWC_ETH_QOS_AXI_PBL_16 0xE
|
||||
#define DWC_ETH_QOS_AXI_PBL_32 0x1E
|
||||
#define DWC_ETH_QOS_AXI_PBL_64 0x3E
|
||||
#define DWC_ETH_QOS_AXI_PBL_128 0x7E
|
||||
#define DWC_ETH_QOS_AXI_PBL_256 0xFE
|
||||
|
||||
#define DWC_ETH_QOS_MAX_AXI_WORL 31
|
||||
#define DWC_ETH_QOS_MAX_AXI_RORL 31
|
||||
|
||||
/* RX VLAN operations */
|
||||
/* Do not strip VLAN tag from received pkt */
|
||||
#define DWC_ETH_QOS_RX_NO_VLAN_STRIP 0x0
|
||||
/* Strip VLAN tag if received pkt pass VLAN filter */
|
||||
#define DWC_ETH_QOS_RX_VLAN_STRIP_IF_FILTER_PASS 0x1
|
||||
/* Strip VLAN tag if received pkt fial VLAN filter */
|
||||
#define DWC_ETH_QOS_RX_VLAN_STRIP_IF_FILTER_FAIL 0x2
|
||||
/* Strip VALN tag always from received pkt */
|
||||
#define DWC_ETH_QOS_RX_VLAN_STRIP_ALWAYS 0x3
|
||||
|
||||
/* TX VLAN operations */
|
||||
/* Do not add a VLAN tag dring pkt transmission */
|
||||
#define DWC_ETH_QOS_TX_VLAN_TAG_NONE 0x0
|
||||
/* Remove the VLAN tag from the pkt before transmission */
|
||||
#define DWC_ETH_QOS_TX_VLAN_TAG_DELETE 0x1
|
||||
/* Insert the VLAN tag into pkt to be transmitted */
|
||||
#define DWC_ETH_QOS_TX_VLAN_TAG_INSERT 0x2
|
||||
/* Replace the VLAN tag into pkt to be transmitted */
|
||||
#define DWC_ETH_QOS_TX_VLAN_TAG_REPLACE 0x3
|
||||
|
||||
/* RX split header operations */
|
||||
#define DWC_ETH_QOS_RX_SPLIT_HDR_DISABLE 0x0
|
||||
#define DWC_ETH_QOS_RX_SPLIT_HDR_ENABLE 0x1
|
||||
|
||||
/* L3/L4 filter operations */
|
||||
#define DWC_ETH_QOS_L3_L4_FILTER_DISABLE 0x0
|
||||
#define DWC_ETH_QOS_L3_L4_FILTER_ENABLE 0x1
|
||||
|
||||
/* Loopback mode */
|
||||
#define DWC_ETH_QOS_MAC_LOOPBACK_DISABLE 0x0
|
||||
#define DWC_ETH_QOS_MAC_LOOPBACK_ENABLE 0x1
|
||||
|
||||
/* PFC(Priority Based Flow Control) mode */
|
||||
#define DWC_ETH_QOS_PFC_DISABLE 0x0
|
||||
#define DWC_ETH_QOS_PFC_ENABLE 0x1
|
||||
|
||||
#define DWC_ETH_QOS_MAC0REG 0
|
||||
#define DWC_ETH_QOS_MAC1REG 1
|
||||
|
||||
#define DWC_ETH_QOS_SA0_NONE ((DWC_ETH_QOS_MAC0REG << 2) | 0) /* Do not include the SA */
|
||||
#define DWC_ETH_QOS_SA0_DESC_INSERT ((DWC_ETH_QOS_MAC0REG << 2) | 1) /* Include/Insert the SA with value given in MAC Addr 0 Reg */
|
||||
#define DWC_ETH_QOS_SA0_DESC_REPLACE ((DWC_ETH_QOS_MAC0REG << 2) | 2) /* Replace the SA with the value given in MAC Addr 0 Reg */
|
||||
#define DWC_ETH_QOS_SA0_REG_INSERT ((DWC_ETH_QOS_MAC0REG << 2) | 2) /* Include/Insert the SA with value given in MAC Addr 0 Reg */
|
||||
#define DWC_ETH_QOS_SA0_REG_REPLACE ((DWC_ETH_QOS_MAC0REG << 2) | 3) /* Replace the SA with the value given in MAC Addr 0 Reg */
|
||||
|
||||
#define DWC_ETH_QOS_SA1_NONE ((DWC_ETH_QOS_MAC1REG << 2) | 0) /* Do not include the SA */
|
||||
#define DWC_ETH_QOS_SA1_DESC_INSERT ((DWC_ETH_QOS_MAC1REG << 2) | 1) /* Include/Insert the SA with value given in MAC Addr 1 Reg */
|
||||
#define DWC_ETH_QOS_SA1_DESC_REPLACE ((DWC_ETH_QOS_MAC1REG << 2) | 2) /* Replace the SA with the value given in MAC Addr 1 Reg */
|
||||
#define DWC_ETH_QOS_SA1_REG_INSERT ((DWC_ETH_QOS_MAC1REG << 2) | 2) /* Include/Insert the SA with value given in MAC Addr 1 Reg */
|
||||
#define DWC_ETH_QOS_SA1_REG_REPLACE ((DWC_ETH_QOS_MAC1REG << 2) | 3) /* Replace the SA with the value given in MAC Addr 1 Reg */
|
||||
|
||||
#define DWC_ETH_QOS_MAX_WFQ_WEIGHT 0X7FFF /* value for bandwidth calculation */
|
||||
|
||||
#define DWC_ETH_QOS_MAX_INT_FRAME_SIZE (1024 * 16)
|
||||
|
||||
typedef enum {
|
||||
EDWC_ETH_QOS_DMA_TX_FP = 0,
|
||||
EDWC_ETH_QOS_DMA_TX_WSP = 1,
|
||||
EDWC_ETH_QOS_DMA_TX_WRR = 2,
|
||||
} e_DWC_ETH_QOS_dma_tx_arb_algo;
|
||||
|
||||
typedef enum {
|
||||
EDWC_ETH_QOS_DCB_WRR = 0,
|
||||
EDWC_ETH_QOS_DCB_WFQ = 1,
|
||||
EDWC_ETH_QOS_DCB_DWRR = 2,
|
||||
EDWC_ETH_QOS_DCB_SP = 3,
|
||||
} e_DWC_ETH_QOS_dcb_algorithm;
|
||||
|
||||
typedef enum {
|
||||
EDWC_ETH_QOS_AVB_SP = 0,
|
||||
EDWC_ETH_QOS_AVB_CBS = 1,
|
||||
} e_DWC_ETH_QOS_avb_algorithm;
|
||||
|
||||
typedef enum {
|
||||
EDWC_ETH_QOS_QDISABLED = 0x0,
|
||||
EDWC_ETH_QOS_QAVB,
|
||||
EDWC_ETH_QOS_QDCB,
|
||||
EDWC_ETH_QOS_QGENERIC
|
||||
} EDWC_ETH_QOS_QUEUE_OPERATING_MODE;
|
||||
|
||||
/* common data structure between driver and application for
|
||||
* sharing info through ioctl
|
||||
* */
|
||||
struct ifr_data_struct {
|
||||
unsigned int flags;
|
||||
unsigned int qinx; /* dma channel no to be configured */
|
||||
unsigned int cmd;
|
||||
unsigned int context_setup;
|
||||
unsigned int connected_speed;
|
||||
unsigned int rwk_filter_values[DWC_ETH_QOS_RWK_FILTER_LENGTH];
|
||||
unsigned int rwk_filter_length;
|
||||
int command_error;
|
||||
int test_done;
|
||||
void *ptr;
|
||||
};
|
||||
|
||||
struct ifr_data_struct_ipa {
|
||||
unsigned int chInx_tx_ipa;
|
||||
unsigned int chInx_rx_ipa;
|
||||
unsigned int cmd;
|
||||
unsigned short vlan_id;
|
||||
};
|
||||
|
||||
struct DWC_ETH_QOS_dcb_algorithm {
|
||||
unsigned int qinx;
|
||||
unsigned int algorithm;
|
||||
unsigned int weight;
|
||||
EDWC_ETH_QOS_QUEUE_OPERATING_MODE op_mode;
|
||||
};
|
||||
|
||||
struct DWC_ETH_QOS_avb_algorithm_params {
|
||||
unsigned int idle_slope;
|
||||
unsigned int send_slope;
|
||||
unsigned int hi_credit;
|
||||
unsigned int low_credit;
|
||||
};
|
||||
|
||||
struct DWC_ETH_QOS_avb_algorithm {
|
||||
unsigned int qinx;
|
||||
unsigned int algorithm;
|
||||
unsigned int cc;
|
||||
struct DWC_ETH_QOS_avb_algorithm_params speed100params;
|
||||
struct DWC_ETH_QOS_avb_algorithm_params speed1000params;
|
||||
EDWC_ETH_QOS_QUEUE_OPERATING_MODE op_mode;
|
||||
};
|
||||
|
||||
struct DWC_ETH_QOS_l3_l4_filter {
|
||||
/* 0, 1,2,3,4,5,6 or 7*/
|
||||
unsigned int filter_no;
|
||||
/* 0 - disable and 1 - enable */
|
||||
int filter_enb_dis;
|
||||
/* 0 - src addr/port and 1- dst addr/port match */
|
||||
int src_dst_addr_match;
|
||||
/* 0 - perfect and 1 - inverse match filtering */
|
||||
int perfect_inverse_match;
|
||||
/* To hold source/destination IPv4 addresses */
|
||||
unsigned char ip4_addr[4];
|
||||
/* holds single IPv6 addresses */
|
||||
unsigned short ip6_addr[8];
|
||||
|
||||
/* TCP/UDP src/dst port number */
|
||||
unsigned short port_no;
|
||||
};
|
||||
|
||||
struct DWC_ETH_QOS_vlan_filter {
|
||||
/* 0 - disable and 1 - enable */
|
||||
int filter_enb_dis;
|
||||
/* 0 - perfect and 1 - hash filtering */
|
||||
int perfect_hash;
|
||||
/* 0 - perfect and 1 - inverse matching */
|
||||
int perfect_inverse_match;
|
||||
};
|
||||
|
||||
struct DWC_ETH_QOS_l2_da_filter {
|
||||
/* 0 - perfect and 1 - hash filtering */
|
||||
int perfect_hash;
|
||||
/* 0 - perfect and 1 - inverse matching */
|
||||
int perfect_inverse_match;
|
||||
};
|
||||
|
||||
struct DWC_ETH_QOS_arp_offload {
|
||||
unsigned char ip_addr[4];
|
||||
};
|
||||
|
||||
#define DWC_ETH_QOS_VIA_REG 0
|
||||
#define DWC_ETH_QOS_VIA_DESC 1
|
||||
|
||||
/* for MAC Double VLAN Processing config */
|
||||
#define DWC_ETH_QOS_DVLAN_OUTER (1)
|
||||
#define DWC_ETH_QOS_DVLAN_INNER (1 << 1)
|
||||
#define DWC_ETH_QOS_DVLAN_BOTH (DWC_ETH_QOS_DVLAN_OUTER | DWC_ETH_QOS_DVLAN_INNER)
|
||||
|
||||
#define DWC_ETH_QOS_DVLAN_NONE 0
|
||||
#define DWC_ETH_QOS_DVLAN_DELETE 1
|
||||
#define DWC_ETH_QOS_DVLAN_INSERT 2
|
||||
#define DWC_ETH_QOS_DVLAN_REPLACE 3
|
||||
|
||||
#define DWC_ETH_QOS_DVLAN_DISABLE 0
|
||||
#define DWC_ETH_QOS_DVLAN_ENABLE 1
|
||||
|
||||
struct DWC_ETH_QOS_config_dvlan {
|
||||
int inner_vlan_tag;
|
||||
int outer_vlan_tag;
|
||||
/* op_type will be
|
||||
* 0/1/2/3 for none/delet/insert/replace respectively
|
||||
* */
|
||||
int op_type;
|
||||
/* in_out will be
|
||||
* 1/2/3 for outer/inner/both respectively.
|
||||
* */
|
||||
int in_out;
|
||||
/* 0 for via registers and 1 for via descriptor */
|
||||
int via_reg_or_desc;
|
||||
};
|
||||
|
||||
/* for PTP offloading configuration */
|
||||
#define DWC_ETH_QOS_PTP_OFFLOADING_DISABLE 0
|
||||
#define DWC_ETH_QOS_PTP_OFFLOADING_ENABLE 1
|
||||
|
||||
#define DWC_ETH_QOS_PTP_ORDINARY_SLAVE 1
|
||||
#define DWC_ETH_QOS_PTP_ORDINARY_MASTER 2
|
||||
#define DWC_ETH_QOS_PTP_TRASPARENT_SLAVE 3
|
||||
#define DWC_ETH_QOS_PTP_TRASPARENT_MASTER 4
|
||||
#define DWC_ETH_QOS_PTP_PEER_TO_PEER_TRANSPARENT 5
|
||||
|
||||
struct DWC_ETH_QOS_config_ptpoffloading {
|
||||
int en_dis;
|
||||
int mode;
|
||||
int domain_num;
|
||||
int mc_uc;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PPS_OUTPUT
|
||||
struct ETH_PPS_Config
|
||||
{
|
||||
unsigned int ptpclk_freq;
|
||||
unsigned int ppsout_freq;
|
||||
unsigned int ppsout_ch;
|
||||
unsigned int ppsout_duty;
|
||||
unsigned int ppsout_start;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef DWC_ETH_QOS_CONFIG_PGTEST
|
||||
|
||||
/* uncomment below macro to enable application
|
||||
* to record all run reports to file */
|
||||
/* #define PGTEST_LOGFILE */
|
||||
|
||||
/* TX DMA CHANNEL Weights */
|
||||
#define DWC_ETH_QOS_TX_CH_WEIGHT1 0x0
|
||||
#define DWC_ETH_QOS_TX_CH_WEIGHT2 0x1
|
||||
#define DWC_ETH_QOS_TX_CH_WEIGHT3 0x2
|
||||
#define DWC_ETH_QOS_TX_CH_WEIGHT4 0x3
|
||||
#define DWC_ETH_QOS_TX_CH_WEIGHT5 0x4
|
||||
#define DWC_ETH_QOS_TX_CH_WEIGHT6 0x5
|
||||
#define DWC_ETH_QOS_TX_CH_WEIGHT7 0x6
|
||||
#define DWC_ETH_QOS_TX_CH_WEIGHT8 0x7
|
||||
|
||||
/* PG test sub commands macro's */
|
||||
#define DWC_ETH_QOS_PG_SET_CONFIG 0x1
|
||||
#define DWC_ETH_QOS_PG_CONFIG_HW 0x2
|
||||
#define DWC_ETH_QOS_PG_RUN_TEST 0x3
|
||||
#define DWC_ETH_QOS_PG_GET_RESULT 0x4
|
||||
#define DWC_ETH_QOS_PG_TEST_DONE 0x5
|
||||
|
||||
/* DMA channel bandwidth allocation parameters */
|
||||
struct DWC_ETH_QOS_pg_user_ch_input {
|
||||
unsigned char ch_arb_weight; /* Channel weights(1/2/3/4/5/6/7/8) for arbitration */
|
||||
unsigned int ch_fr_size; /* Channel Frame size */
|
||||
unsigned char ch_bw_alloc; /* The percentage bandwidth allocation for ch */
|
||||
|
||||
unsigned char ch_use_slot_no_check; /* Should Ch use slot number checking ? */
|
||||
unsigned char ch_use_adv_slot_no_check;
|
||||
unsigned char ch_slot_count_to_use; /* How many slot used to report pg bits per slot value */
|
||||
|
||||
unsigned char ch_use_credit_shape; /* Should Ch use Credid shape algorithm for traffic shaping ? */
|
||||
unsigned char CH_CREDITCONTROL; /* Sould Ch use Credit Control algorithm for traffic shaping ? */
|
||||
|
||||
unsigned char ch_tx_desc_slot_no_start;
|
||||
unsigned char ch_tx_desc_slot_no_skip;
|
||||
unsigned char ch_operating_mode;
|
||||
unsigned long CH_AVGBITS;
|
||||
unsigned long CH_AVGBITS_INTERRUPT_COUNT;
|
||||
unsigned char ch_avb_algorithm;
|
||||
unsigned char ch_debug_mode; /* enable/disable debug mode */
|
||||
unsigned int ch_max_tx_frame_cnt; /* maximum pkts to be sent on this channel, can be used for debug purpose */
|
||||
};
|
||||
|
||||
struct DWC_ETH_QOS_pg_user_input {
|
||||
unsigned char duration_of_exp;
|
||||
/* enable bits for DMA. bit0=>ch0, bit1=>ch1, bit2=>ch2 */
|
||||
unsigned char dma_ch_en;
|
||||
|
||||
unsigned char ch_tx_rx_arb_scheme; /* Should Ch use Weighted RR policy with Rx:Tx/Tx:Rx or Fixed Priority */
|
||||
unsigned char ch_use_tx_high_prio; /* Should Ch Tx have High priority over Rx */
|
||||
unsigned char ch_tx_rx_prio_ratio; /* For RR what is the ratio between Tx:Rx/Rx:Tx */
|
||||
unsigned char dma_tx_arb_algo; /* Refer DMA Mode register TAA field */
|
||||
|
||||
unsigned char queue_dcb_algorithm;
|
||||
|
||||
unsigned char mac_lb_mode; /* 0 => No MAC Loopback; 1 => MAC Loopback On */
|
||||
unsigned int speed_100M_1G; /* 0 => No MAC Loopback; 1 => MAC Loopback On */
|
||||
|
||||
struct DWC_ETH_QOS_pg_user_ch_input ch_input[DWC_ETH_QOS_MAX_TX_QUEUE_CNT];
|
||||
};
|
||||
|
||||
#define copy_pg_ch_input_members(to, from) do { \
|
||||
(to)->interrupt_prints = (from)->interrupt_prints; \
|
||||
(to)->tx_interrupts = (from)->tx_interrupts; \
|
||||
(to)->ch_arb_weight = (from)->ch_arb_weight; \
|
||||
(to)->ch_queue_weight = (from)->ch_queue_weight; \
|
||||
(to)->ch_bw = (from)->ch_bw; \
|
||||
(to)->ch_frame_size = (from)->ch_frame_size; \
|
||||
(to)->CH_ENABLESLOTCHECK = (from)->CH_ENABLESLOTCHECK; \
|
||||
(to)->CH_ENABLEADVSLOTCHECK = (from)->CH_ENABLEADVSLOTCHECK; \
|
||||
(to)->ch_avb_algorithm = (from)->ch_avb_algorithm; \
|
||||
(to)->CH_SLOTCOUNT = (from)->CH_SLOTCOUNT; \
|
||||
(to)->CH_AVGBITS = (from)->CH_AVGBITS; \
|
||||
(to)->CH_AVGBITS_INTERRUPT_COUNT = (from)->CH_AVGBITS_INTERRUPT_COUNT; \
|
||||
(to)->CH_CREDITCONTROL = (from)->CH_CREDITCONTROL; \
|
||||
(to)->ch_tx_desc_slot_no_start = (from)->ch_tx_desc_slot_no_start; \
|
||||
(to)->ch_tx_desc_slot_no_skip = (from)->ch_tx_desc_slot_no_skip; \
|
||||
(to)->CH_SENDSLOPE = (from)->CH_SENDSLOPE; \
|
||||
(to)->CH_IDLESLOPE = (from)->CH_IDLESLOPE; \
|
||||
(to)->CH_HICREDIT = (from)->CH_HICREDIT; \
|
||||
(to)->CH_LOCREDIT = (from)->CH_LOCREDIT; \
|
||||
(to)->CH_FRAMECOUNTTX = (from)->CH_FRAMECOUNTTX; \
|
||||
(to)->CH_FRAMECOUNTRX = (from)->CH_FRAMECOUNTRX; \
|
||||
(to)->ch_operating_mode = (from)->ch_operating_mode; \
|
||||
(to)->ch_debug_mode = (from)->ch_debug_mode;\
|
||||
(to)->ch_max_tx_frame_cnt = (from)->ch_max_tx_frame_cnt;\
|
||||
} while (0)
|
||||
|
||||
struct DWC_ETH_QOS_pg_ch_input {
|
||||
unsigned int interrupt_prints;
|
||||
unsigned int tx_interrupts;
|
||||
unsigned char ch_arb_weight;
|
||||
unsigned int ch_queue_weight;
|
||||
unsigned char ch_bw;
|
||||
unsigned int ch_frame_size;
|
||||
unsigned char CH_ENABLESLOTCHECK; /* Enable checking of slot numbers programmed in the Tx Desc */
|
||||
unsigned char CH_ENABLEADVSLOTCHECK; /* When Set Data fetched for current slot and for next 2 slots in advance
|
||||
When reset data fetched for current slot and in advance for next slot*/
|
||||
|
||||
unsigned char ch_avb_algorithm;
|
||||
unsigned char CH_SLOTCOUNT; /* Over which transmiteed bits per slot needs to be computed (Only for Credit based shaping) */
|
||||
unsigned long CH_AVGBITS;
|
||||
unsigned long CH_AVGBITS_INTERRUPT_COUNT;
|
||||
|
||||
unsigned char CH_CREDITCONTROL; /* Will be zero (Not used) */
|
||||
|
||||
unsigned char ch_tx_desc_slot_no_start;
|
||||
unsigned char ch_tx_desc_slot_no_skip;
|
||||
|
||||
unsigned int CH_SENDSLOPE;
|
||||
unsigned int CH_IDLESLOPE;
|
||||
unsigned int CH_HICREDIT;
|
||||
unsigned int CH_LOCREDIT;
|
||||
|
||||
unsigned long CH_FRAMECOUNTTX; /* No of Frames Transmitted on Channel 1 */
|
||||
unsigned long CH_FRAMECOUNTRX; /* No of Frames Received on Channel 1 */
|
||||
unsigned char ch_operating_mode;
|
||||
|
||||
unsigned char ch_debug_mode; /* enable/disable debug mode */
|
||||
unsigned int ch_max_tx_frame_cnt; /* maximum pkts to be sent on this channel, can be used for debug purpose */
|
||||
unsigned int ch_desc_prepare; /* max packets which will be reprepared in Tx-interrupt
|
||||
do not copy contents to app-copy, only driver should use this variable*/
|
||||
};
|
||||
|
||||
#define COPY_PGSTRUCT_MEMBERS(to, from) do { \
|
||||
(to)->CH_SELMASK = (from)->CH_SELMASK; \
|
||||
(to)->DURATIONOFEXP = (from)->DURATIONOFEXP; \
|
||||
(to)->PRIOTAGFORAV = (from)->PRIOTAGFORAV; \
|
||||
(to)->queue_dcb_algorithm = (from)->queue_dcb_algorithm; \
|
||||
(to)->ch_tx_rx_arb_scheme = (from)->ch_tx_rx_arb_scheme; \
|
||||
(to)->ch_use_tx_high_prio = (from)->ch_use_tx_high_prio; \
|
||||
(to)->ch_tx_rx_prio_ratio = (from)->ch_tx_rx_prio_ratio; \
|
||||
(to)->dma_tx_arb_algo = (from)->dma_tx_arb_algo; \
|
||||
(to)->mac_lb_mode = (from)->mac_lb_mode; \
|
||||
} while (0)
|
||||
|
||||
struct DWC_ETH_QOS_PGSTRUCT {
|
||||
/* This gives which DMA channel is enabled and which is disabled
|
||||
* Bit0 for Ch0
|
||||
* Bit1 for Ch1
|
||||
* Bit2 for Ch2 and so on
|
||||
* Bit7 for Ch7
|
||||
* */
|
||||
unsigned char CH_SELMASK;
|
||||
|
||||
/* Duration for which experiment should be conducted in minutes - Default 2 Minutes */
|
||||
unsigned char DURATIONOFEXP;
|
||||
|
||||
/* Used when more than One channel enabled in Rx path (Not Used)
|
||||
* for only CH1 Enabled:
|
||||
* Frames sith Priority > Value programmed, frames sent to CH1
|
||||
* Frames with priority < Value programmed are sent to CH0
|
||||
*
|
||||
* For both CH1 and CH2 Enabled:
|
||||
* Frames sith Priority > Value programmed, frames sent to CH2
|
||||
* Frames with priority < Value programmed are sent to CH
|
||||
* */
|
||||
unsigned char PRIOTAGFORAV;
|
||||
|
||||
unsigned char queue_dcb_algorithm;
|
||||
|
||||
unsigned char ch_tx_rx_arb_scheme; /* Should Ch use Weighted RR policy with Rx:Tx/Tx:Rx or Fixed Priority */
|
||||
unsigned char ch_use_tx_high_prio; /* Should Ch Tx have High priority over Rx */
|
||||
unsigned char ch_tx_rx_prio_ratio; /* For RR what is the ratio between Tx:Rx/Rx:Tx */
|
||||
unsigned char dma_tx_arb_algo; /* Refer DMA Mode register TAA field */
|
||||
|
||||
unsigned char mac_lb_mode; /* 0 => No MAC Loopback; 1 => MAC Loopback On */
|
||||
unsigned int speed_100M_1G;
|
||||
struct DWC_ETH_QOS_pg_ch_input pg_ch_input[DWC_ETH_QOS_MAX_TX_QUEUE_CNT];
|
||||
unsigned char channel_running[DWC_ETH_QOS_MAX_TX_QUEUE_CNT];
|
||||
};
|
||||
#endif /* end of DWC_ETH_QOS_CONFIG_PGTEST */
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
37534
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/DWC_ETH_QOS_yregacc.h
Normal file
37534
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/DWC_ETH_QOS_yregacc.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,724 @@
|
||||
/* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
#ifndef __DWC_ETH_QOS__RGMII_IO_MACRO_REGACC__H__
|
||||
|
||||
#define __DWC_ETH_QOS__RGMII_IO_MACRO_REGACC__H__
|
||||
|
||||
/* Read Write register operations for EMAC_RGMII_IO_MACRO_CONFIG */
|
||||
|
||||
extern ULONG dwc_rgmii_io_csr_base_addr;
|
||||
#define RGMII_IO_BASE_ADDRESS dwc_rgmii_io_csr_base_addr
|
||||
|
||||
#define RGMII_IO_MACRO_CONFIG_RGOFFADDR_OFFSET (0x00000000)
|
||||
#define RGMII_IO_MACRO_CONFIG_RGOFFADDR ((volatile ULONG *) (RGMII_IO_BASE_ADDRESS + RGMII_IO_MACRO_CONFIG_RGOFFADDR_OFFSET))
|
||||
|
||||
#define RGMII_IO_MACRO_CONFIG_RGWR(data) do {\
|
||||
iowrite32(data, (void *)RGMII_IO_MACRO_CONFIG_RGOFFADDR);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_IO_MACRO_CONFIG_RGRD(data) do {\
|
||||
(data) = ioread32((void *)RGMII_IO_MACRO_CONFIG_RGOFFADDR);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_FUNC_CLK_EN_MASK (ULONG)(0x1)
|
||||
|
||||
#define RGMII_FUNC_CLK_EN_WR_MASK (ULONG)(0xbfffffff)
|
||||
|
||||
#define RGMII_FUNC_CLK_EN_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(v);\
|
||||
v = ((v & RGMII_FUNC_CLK_EN_WR_MASK) | ((data & RGMII_FUNC_CLK_EN_MASK) << 30));\
|
||||
RGMII_IO_MACRO_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_FUNC_CLK_EN_UDFRD(data) do {\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(data);\
|
||||
data = ((data >> 30) & RGMII_FUNC_CLK_EN_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_GPIO_CFG_RX_INT_MASK (ULONG)(0x3)
|
||||
|
||||
#define RGMII_GPIO_CFG_RX_INT_WR_MASK (ULONG)(0xffe7ffff)
|
||||
|
||||
#define RGMII_GPIO_CFG_RX_INT_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(v);\
|
||||
v = ((v & RGMII_GPIO_CFG_RX_INT_WR_MASK) | ((data & RGMII_GPIO_CFG_RX_INT_MASK) << 19));\
|
||||
RGMII_IO_MACRO_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_GPIO_CFG_RX_INT_UDFRD(data) do {\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(data);\
|
||||
data = ((data >> 19) & RGMII_GPIO_CFG_RX_INT_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_GPIO_CFG_TX_INT_MASK (ULONG)(0x3)
|
||||
|
||||
#define RGMII_GPIO_CFG_TX_INT_WR_MASK (ULONG)(0xfff9ffff)
|
||||
|
||||
#define RGMII_GPIO_CFG_TX_INT_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(v);\
|
||||
v = ((v & RGMII_GPIO_CFG_TX_INT_WR_MASK) | ((data & RGMII_GPIO_CFG_TX_INT_MASK) << 17));\
|
||||
RGMII_IO_MACRO_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_GPIO_CFG_TX_INT_UDFRD(data) do {\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(data);\
|
||||
data = ((data >> 17) & RGMII_GPIO_CFG_TX_INT_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_MAX_SPD_PRG_9_MASK (ULONG)(0x1ff)
|
||||
|
||||
#define RGMII_MAX_SPD_PRG_9_WR_MASK (ULONG)(0xfffe00ff)
|
||||
|
||||
#define RGMII_MAX_SPD_PRG_9_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(v);\
|
||||
v = ((v & RGMII_MAX_SPD_PRG_9_WR_MASK) | ((data & RGMII_MAX_SPD_PRG_9_MASK) << 8));\
|
||||
RGMII_IO_MACRO_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_MAX_SPD_PRG_9_UDFRD(data) do {\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(data);\
|
||||
data = ((data >> 8) & RGMII_MAX_SPD_PRG_9_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_MAX_SPD_PRG_2_MASK (ULONG)(0x3)
|
||||
|
||||
#define RGMII_MAX_SPD_PRG_2_WR_MASK (ULONG)(0xffffff3f)
|
||||
|
||||
#define RGMII_MAX_SPD_PRG_2_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(v);\
|
||||
v = ((v & RGMII_MAX_SPD_PRG_2_WR_MASK) | ((data & RGMII_MAX_SPD_PRG_2_MASK) << 6));\
|
||||
RGMII_IO_MACRO_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_MAX_SPD_PRG_2_UDFRD(data) do {\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(data);\
|
||||
data = ((data >> 6) & RGMII_MAX_SPD_PRG_2_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_INTF_SEL_MASK (ULONG)(0x3)
|
||||
|
||||
#define RGMII_INTF_SEL_WR_MASK (ULONG)(0xffffffcf)
|
||||
|
||||
#define RGMII_INTF_SEL_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(v);\
|
||||
v = ((v & RGMII_INTF_SEL_WR_MASK) | ((data & RGMII_INTF_SEL_MASK) << 4));\
|
||||
RGMII_IO_MACRO_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_INTF_SEL_UDFRD(data) do {\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(data);\
|
||||
data = ((data >> 4) & RGMII_INTF_SEL_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_POS_NEG_DATA_SEL_MASK (ULONG)(0x1)
|
||||
|
||||
#define RGMII_POS_NEG_DATA_SEL_WR_MASK (ULONG)(0xff7fffff)
|
||||
|
||||
#define RGMII_POS_NEG_DATA_SEL_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(v);\
|
||||
v = ((v & RGMII_POS_NEG_DATA_SEL_WR_MASK) | ((data & RGMII_POS_NEG_DATA_SEL_MASK) << 23));\
|
||||
RGMII_IO_MACRO_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_POS_NEG_DATA_SEL_UDFRD(data) do {\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(data);\
|
||||
data = ((data >> 23) & RGMII_POS_NEG_DATA_SEL_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_BYPASS_TX_ID_EN_MASK (ULONG)(0x1)
|
||||
|
||||
#define RGMII_BYPASS_TX_ID_EN_WR_MASK (ULONG)(0xfffffff7)
|
||||
|
||||
#define RGMII_BYPASS_TX_ID_EN_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(v);\
|
||||
v = ((v & RGMII_BYPASS_TX_ID_EN_WR_MASK) | ((data & RGMII_BYPASS_TX_ID_EN_MASK) << 3));\
|
||||
RGMII_IO_MACRO_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_BYPASS_TX_ID_EN_UDFRD(data) do {\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(data);\
|
||||
data = ((data >> 3) & RGMII_BYPASS_TX_ID_EN_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_LOOPBACK_EN_MASK (ULONG)(0x1)
|
||||
|
||||
#define RGMII_LOOPBACK_EN_WR_MASK (ULONG)(0xfffffffb)
|
||||
|
||||
#define RGMII_LOOPBACK_EN_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(v);\
|
||||
v = ((v & RGMII_LOOPBACK_EN_WR_MASK) | ((data & RGMII_LOOPBACK_EN_MASK) << 2));\
|
||||
RGMII_IO_MACRO_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_LOOPBACK_EN_UDFRD(data) do {\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(data);\
|
||||
data = ((data >> 2) & RGMII_LOOPBACK_EN_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_PROG_SWAP_MASK (ULONG)(0x1)
|
||||
|
||||
#define RGMII_PROG_SWAP_WR_MASK (ULONG)(0xfffffffd)
|
||||
|
||||
#define RGMII_PROG_SWAP_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(v);\
|
||||
v = ((v & RGMII_PROG_SWAP_WR_MASK) | ((data & RGMII_PROG_SWAP_MASK) << 1));\
|
||||
RGMII_IO_MACRO_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_PROG_SWAP_UDFRD(data) do {\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(data);\
|
||||
data = ((data >> 1) & RGMII_PROG_SWAP_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_DDR_MODE_MASK (ULONG)(0x1)
|
||||
|
||||
#define RGMII_DDR_MODE_WR_MASK (ULONG)(0xfffffffe)
|
||||
|
||||
#define RGMII_DDR_MODE_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(v);\
|
||||
v = ((v & RGMII_DDR_MODE_WR_MASK) | ((data & RGMII_DDR_MODE_MASK) << 0));\
|
||||
RGMII_IO_MACRO_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_DDR_MODE_UDFRD(data) do {\
|
||||
RGMII_IO_MACRO_CONFIG_RGRD(data);\
|
||||
data = ((data >> 0) & RGMII_DDR_MODE_MASK);\
|
||||
} while (0)
|
||||
|
||||
/* Read Write register operations for EMAC_SDCC_HC_REG_DLL_CONFIG */
|
||||
|
||||
#define SDCC_HC_REG_DLL_CONFIG_RGOFFADDR_OFFSET (0x00000004)
|
||||
#define SDCC_HC_REG_DLL_CONFIG_RGOFFADDR ((volatile ULONG *)(RGMII_IO_BASE_ADDRESS + SDCC_HC_REG_DLL_CONFIG_RGOFFADDR_OFFSET))
|
||||
|
||||
#define SDCC_HC_REG_DLL_CONFIG_RGWR(data) do {\
|
||||
iowrite32(data, (void *)SDCC_HC_REG_DLL_CONFIG_RGOFFADDR);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_REG_DLL_CONFIG_RGRD(data) do {\
|
||||
(data) = ioread32((void *)SDCC_HC_REG_DLL_CONFIG_RGOFFADDR);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_DLL_RST_MASK (ULONG)(0x1)
|
||||
|
||||
#define SDCC_HC_DLL_RST_WR_MASK (ULONG)(0xbfffffff)
|
||||
|
||||
#define SDCC_HC_DLL_RST_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(v);\
|
||||
v = ((v & SDCC_HC_DLL_RST_WR_MASK) | ((data & SDCC_HC_DLL_RST_MASK) << 30));\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_DLL_RST_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(data);\
|
||||
data = ((data >> 30) & SDCC_HC_DLL_RST_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_PDN_MASK (ULONG)(0x1)
|
||||
|
||||
#define SDCC_HC_PDN_WR_MASK (ULONG)(0xdfffffff)
|
||||
|
||||
#define SDCC_HC_PDN_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(v);\
|
||||
v = ((v & SDCC_HC_PDN_WR_MASK) | ((data & SDCC_HC_PDN_MASK) << 29));\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_PDN_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(data);\
|
||||
data = ((data >> 29) & SDCC_HC_PDN_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_MCLK_FREQ_MASK (ULONG)(0x7)
|
||||
|
||||
#define SDCC_HC_MCLK_FREQ_WR_MASK (ULONG)(0xf8ffffff)
|
||||
|
||||
#define SDCC_HC_MCLK_FREQ_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(v);\
|
||||
v = ((v & SDCC_HC_MCLK_FREQ_WR_MASK) | ((data & SDCC_HC_MCLK_FREQ_MASK) << 24));\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_MCLK_FREQ_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(data);\
|
||||
data = ((data >> 24) & SDCC_HC_MCLK_FREQ_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CDR_SELEXT_MASK (ULONG)(0xf)
|
||||
|
||||
#define SDCC_HC_CDR_SELEXT_WR_MASK (ULONG)(0xff0fffff)
|
||||
|
||||
#define SDCC_HC_CDR_SELEXT_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(v);\
|
||||
v = ((v & SDCC_HC_CDR_SELEXT_WR_MASK) | ((data & SDCC_HC_CDR_SELEXT_MASK) << 20));\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CDR_SELEXT_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(data);\
|
||||
data = ((data >> 20) & SDCC_HC_CDR_SELEXT_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CDR_EXT_EN_MASK (ULONG)(0x1)
|
||||
|
||||
#define SDCC_HC_CDR_EXT_EN_WR_MASK (ULONG)(0xfff7ffff)
|
||||
|
||||
#define SDCC_HC_CDR_EXT_EN_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(v);\
|
||||
v = ((v & SDCC_HC_CDR_EXT_EN_WR_MASK) | ((data & SDCC_HC_CDR_EXT_EN_MASK) << 19));\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CDR_EXT_EN_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(data);\
|
||||
data = ((data >> 19) & SDCC_HC_CDR_EXT_EN_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CK_OUT_EN_MASK (ULONG)(0x1)
|
||||
|
||||
#define SDCC_HC_CK_OUT_EN_WR_MASK (ULONG)(0xfffbffff)
|
||||
|
||||
#define SDCC_HC_CK_OUT_EN_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(v);\
|
||||
v = ((v & SDCC_HC_CK_OUT_EN_WR_MASK) | ((data & SDCC_HC_CK_OUT_EN_MASK) << 18));\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CK_OUT_EN_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(data);\
|
||||
data = ((data >> 18) & SDCC_HC_CK_OUT_EN_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CDR_EN_MASK (ULONG)(0x1)
|
||||
|
||||
#define SDCC_HC_CDR_EN_WR_MASK (ULONG)(0xfffdffff)
|
||||
|
||||
#define SDCC_HC_CDR_EN_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(v);\
|
||||
v = ((v & SDCC_HC_CDR_EN_WR_MASK) | ((data & SDCC_HC_CDR_EN_MASK) << 17));\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CDR_EN_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(data);\
|
||||
data = ((data >> 17) & SDCC_HC_CDR_EN_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_MCLK_GATING_ENABLE_MASK (ULONG)(0x1)
|
||||
|
||||
#define SDCC_HC_MCLK_GATING_ENABLE_WR_MASK (ULONG)(0xffffffdf)
|
||||
|
||||
#define SDCC_HC_MCLK_GATING_ENABLE_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(v);\
|
||||
v = ((v & SDCC_HC_MCLK_GATING_ENABLE_WR_MASK) | ((data & SDCC_HC_MCLK_GATING_ENABLE_MASK) << 5));\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_MCLK_GATING_ENABLE_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(data);\
|
||||
data = ((data >> 5) & SDCC_HC_MCLK_GATING_ENABLE_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CDR_FINE_PHASE_MASK (ULONG)(0x1)
|
||||
|
||||
#define SDCC_HC_CDR_FINE_PHASE_WR_MASK (ULONG)(0xfffffff3)
|
||||
|
||||
#define SDCC_HC_CDR_FINE_PHASE_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(v);\
|
||||
v = ((v & SDCC_HC_CDR_FINE_PHASE_WR_MASK) | ((data & SDCC_HC_CDR_FINE_PHASE_MASK) << 2));\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CDR_FINE_PHASE_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(data);\
|
||||
data = ((data >> 2) & SDCC_HC_CDR_FINE_PHASE_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_DLL_EN_MASK (ULONG)(0x1)
|
||||
|
||||
#define SDCC_HC_DLL_EN_WR_MASK (ULONG)(0xfffeffff)
|
||||
|
||||
#define SDCC_HC_DLL_EN_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(v);\
|
||||
v = ((v & SDCC_HC_DLL_EN_WR_MASK) | ((data & SDCC_HC_DLL_EN_MASK) << 16));\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_DLL_EN_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DLL_CONFIG_RGRD(data);\
|
||||
data = ((data >> 16) & SDCC_HC_DLL_EN_MASK);\
|
||||
} while (0)
|
||||
|
||||
/* Read Write register operations for EMAC_SDCC_HC_REG_DDR_CONFIG */
|
||||
#define SDCC_HC_REG_DDR_CONFIG_RGOFFADDR_OFFSET (0x0000000C)
|
||||
#define SDCC_HC_REG_DDR_CONFIG_RGOFFADDR ((volatile ULONG *)(RGMII_IO_BASE_ADDRESS + SDCC_HC_REG_DDR_CONFIG_RGOFFADDR_OFFSET))
|
||||
|
||||
#define SDCC_HC_REG_DDR_CONFIG_RGWR(data) do {\
|
||||
iowrite32(data, (void *)SDCC_HC_REG_DDR_CONFIG_RGOFFADDR);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_REG_DDR_CONFIG_RGRD(data) do {\
|
||||
(data) = ioread32((void *)SDCC_HC_REG_DDR_CONFIG_RGOFFADDR);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_PRG_RCLK_DLY_MASK (ULONG)(0x1ff)
|
||||
|
||||
#define SDCC_HC_PRG_RCLK_DLY_WR_MASK (ULONG)(0xfffffe00)
|
||||
|
||||
#define SDCC_HC_PRG_RCLK_DLY_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DDR_CONFIG_RGRD(v);\
|
||||
v = ((v & SDCC_HC_PRG_RCLK_DLY_WR_MASK) | ((data & SDCC_HC_PRG_RCLK_DLY_MASK) << 0));\
|
||||
SDCC_HC_REG_DDR_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_PRG_RCLK_DLY_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DDR_CONFIG_RGRD(data);\
|
||||
data = ((data >> 0) & SDCC_HC_PRG_RCLK_DLY_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_EXT_PRG_RCLK_DLY_MASK (ULONG)(0x3f)
|
||||
|
||||
#define SDCC_HC_EXT_PRG_RCLK_DLY_WR_MASK (ULONG)(0xf81fffff)
|
||||
|
||||
#define SDCC_HC_EXT_PRG_RCLK_DLY_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DDR_CONFIG_RGRD(v);\
|
||||
v = ((v & SDCC_HC_EXT_PRG_RCLK_DLY_WR_MASK) | ((data & SDCC_HC_EXT_PRG_RCLK_DLY_MASK) << 21));\
|
||||
SDCC_HC_REG_DDR_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_EXT_PRG_RCLK_DLY_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DDR_CONFIG_RGRD(data);\
|
||||
data = ((data >> 0) & SDCC_HC_EXT_PRG_RCLK_DLY_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_EXT_PRG_RCLK_DLY_CODE_MASK (ULONG)(0x7)
|
||||
|
||||
#define SDCC_HC_EXT_PRG_RCLK_DLY_CODE_WR_MASK (ULONG)(0xc7ffffff)
|
||||
|
||||
#define SDCC_HC_EXT_PRG_RCLK_DLY_CODE_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DDR_CONFIG_RGRD(v);\
|
||||
v = ((v & SDCC_HC_EXT_PRG_RCLK_DLY_CODE_WR_MASK) | ((data & SDCC_HC_EXT_PRG_RCLK_DLY_CODE_MASK) << 27));\
|
||||
SDCC_HC_REG_DDR_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_EXT_PRG_RCLK_DLY_CODE_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DDR_CONFIG_RGRD(data);\
|
||||
data = ((data >> 0) & SDCC_HC_EXT_PRG_RCLK_DLY_CODE_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_EXT_PRG_RCLK_DLY_EN_MASK (ULONG)(0x1)
|
||||
|
||||
#define SDCC_HC_EXT_PRG_RCLK_DLY_EN_WR_MASK (ULONG)(0xbfffffff)
|
||||
|
||||
#define SDCC_HC_EXT_PRG_RCLK_DLY_EN_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DDR_CONFIG_RGRD(v);\
|
||||
v = ((v & SDCC_HC_EXT_PRG_RCLK_DLY_EN_WR_MASK) | ((data & SDCC_HC_EXT_PRG_RCLK_DLY_EN_MASK) << 30));\
|
||||
SDCC_HC_REG_DDR_CONFIG_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_EXT_PRG_RCLK_DLY_EN_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DDR_CONFIG_RGRD(data);\
|
||||
data = ((data >> 0) & SDCC_HC_EXT_PRG_RCLK_DLY_EN_MASK);\
|
||||
} while (0)
|
||||
|
||||
/* Read Write register operations for EMAC_SDCC_HC_REG_DLL_CONFIG_2 */
|
||||
|
||||
#define SDCC_HC_REG_DLL_CONFIG_2_RGOFFADDR_OFFSET (0x00000010)
|
||||
#define SDCC_HC_REG_DLL_CONFIG_2_RGOFFADDR ((volatile ULONG *)(RGMII_IO_BASE_ADDRESS + SDCC_HC_REG_DLL_CONFIG_2_RGOFFADDR_OFFSET))
|
||||
|
||||
#define SDCC_HC_REG_DLL_CONFIG_2_RGWR(data) do {\
|
||||
iowrite32(data, (void *)SDCC_HC_REG_DLL_CONFIG_2_RGOFFADDR);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_REG_DLL_CONFIG_2_RGRD(data) do {\
|
||||
(data) = ioread32((void *)SDCC_HC_REG_DLL_CONFIG_2_RGOFFADDR);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CFG_2_MCLK_FREQ_CALC_MASK (ULONG)(0xff)
|
||||
|
||||
#define SDCC_HC_CFG_2_MCLK_FREQ_CALC_WR_MASK (ULONG)(0xfffc03ff)
|
||||
|
||||
#define SDCC_HC_CFG_2_MCLK_FREQ_CALC_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DLL_CONFIG_2_RGRD(v);\
|
||||
v = ((v & SDCC_HC_CFG_2_MCLK_FREQ_CALC_WR_MASK) | ((data & SDCC_HC_CFG_2_MCLK_FREQ_CALC_MASK) << 10));\
|
||||
SDCC_HC_REG_DLL_CONFIG_2_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CFG_2_MCLK_FREQ_CALC_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DLL_CONFIG_2_RGRD(data);\
|
||||
data = ((data >> 10) & SDCC_HC_CFG_2_MCLK_FREQ_CALC_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CFG_2_DLL_CLOCK_DISABLE_MASK (ULONG)(0x1)
|
||||
|
||||
#define SDCC_HC_CFG_2_DLL_CLOCK_DISABLE_WR_MASK (ULONG)(0xffdfffff)
|
||||
|
||||
#define SDCC_HC_CFG_2_DLL_CLOCK_DISABLE_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DLL_CONFIG_2_RGRD(v);\
|
||||
v = ((v & SDCC_HC_CFG_2_DLL_CLOCK_DISABLE_WR_MASK) | ((data & SDCC_HC_CFG_2_DLL_CLOCK_DISABLE_MASK) << 21));\
|
||||
SDCC_HC_REG_DLL_CONFIG_2_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CFG_2_DLL_CLOCK_DISABLE_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DLL_CONFIG_2_RGRD(data);\
|
||||
data = ((data >> 21) & SDCC_HC_CFG_2_DLL_CLOCK_DISABLE_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CFG_2_DDR_TRAFFIC_INIT_SEL_MASK (ULONG)(0x1)
|
||||
|
||||
#define SDCC_HC_CFG_2_DDR_TRAFFIC_INIT_SEL_WR_MASK (ULONG)(0xfffffff3)
|
||||
|
||||
#define SDCC_HC_CFG_2_DDR_TRAFFIC_INIT_SEL_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DLL_CONFIG_2_RGRD(v);\
|
||||
v = ((v & SDCC_HC_CFG_2_DDR_TRAFFIC_INIT_SEL_WR_MASK) | ((data & SDCC_HC_CFG_2_DDR_TRAFFIC_INIT_SEL_MASK) << 2));\
|
||||
SDCC_HC_REG_DLL_CONFIG_2_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CFG_2_DDR_TRAFFIC_INIT_SEL_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DLL_CONFIG_2_RGRD(data);\
|
||||
data = ((data >> 2) & SDCC_HC_CFG_2_DDR_TRAFFIC_INIT_SEL_MASK);\
|
||||
} while (0)
|
||||
|
||||
|
||||
#define SDCC_HC_CFG_2_DDR_CAL_EN_MASK (ULONG)(0x1)
|
||||
|
||||
#define SDCC_HC_CFG_2_DDR_CAL_EN_WR_MASK (ULONG)(0xfffffffe)
|
||||
|
||||
#define SDCC_HC_CFG_2_DDR_CAL_EN_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DLL_CONFIG_2_RGRD(v);\
|
||||
v = ((v & SDCC_HC_CFG_2_DDR_CAL_EN_WR_MASK) | ((data & SDCC_HC_CFG_2_DDR_CAL_EN_MASK) << 0));\
|
||||
SDCC_HC_REG_DLL_CONFIG_2_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CFG_2_DDR_CAL_EN_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DLL_CONFIG_2_RGRD(data);\
|
||||
data = ((data >> 0) & SDCC_HC_CFG_2_DDR_CAL_EN_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CFG_2_DDR_TRAFFIC_INIT_SW_MASK (ULONG)(0x1)
|
||||
|
||||
#define SDCC_HC_CFG_2_DDR_TRAFFIC_INIT_SW_WR_MASK (ULONG)(0xfffffffd)
|
||||
|
||||
#define SDCC_HC_CFG_2_DDR_TRAFFIC_INIT_SW_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_HC_REG_DLL_CONFIG_2_RGRD(v);\
|
||||
v = ((v & SDCC_HC_CFG_2_DDR_TRAFFIC_INIT_SW_WR_MASK) | ((data & SDCC_HC_CFG_2_DDR_TRAFFIC_INIT_SW_MASK) << 1));\
|
||||
SDCC_HC_REG_DLL_CONFIG_2_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_HC_CFG_2_DDR_TRAFFIC_INIT_SW_UDFRD(data) do {\
|
||||
SDCC_HC_REG_DLL_CONFIG_2_RGRD(data);\
|
||||
data = ((data >> 0) & SDCC_HC_CFG_2_DDR_TRAFFIC_INIT_SW_MASK);\
|
||||
} while (0)
|
||||
|
||||
/* Read register operations for EMAC_SDC4_STATUS */
|
||||
|
||||
#define SDC4_STATUS_RGOFFADDR ((volatile ULONG *)(RGMII_IO_BASE_ADDRESS + 0x00000014))
|
||||
|
||||
#define SDC4_STATUS_RGRD(data) do {\
|
||||
(data) = ioread32((void *)SDC4_STATUS_RGOFFADDR);\
|
||||
} while (0)
|
||||
|
||||
#define SDC4_STATUS_DLL_LOCK_STS_MASK (ULONG)(0x1)
|
||||
|
||||
#define SDC4_STATUS_DLL_LOCK_STS_UDFRD(data) do {\
|
||||
SDC4_STATUS_RGRD(data);\
|
||||
data = ((data >> 7) & SDC4_STATUS_DLL_LOCK_STS_MASK);\
|
||||
} while (0)
|
||||
|
||||
/* Read register operations for EMAC_SDCC_USR_CTL */
|
||||
|
||||
#define SDCC_USR_CTL_RGOFFADDR_OFFSET (0x00000018)
|
||||
#define SDCC_USR_CTL_RGOFFADDR ((volatile ULONG *)(RGMII_IO_BASE_ADDRESS + SDCC_USR_CTL_RGOFFADDR_OFFSET))
|
||||
|
||||
#define SDCC_USR_CTL_BYPASS_MODE_MASK (ULONG)(0x1)
|
||||
|
||||
#define SDCC_USR_CTL_BYPASS_MODE_WR_MASK (ULONG)(0xbfffffff)
|
||||
|
||||
#define SDCC_USR_CTL_RGRD(data) do {\
|
||||
(data) = ioread32((void *)SDCC_USR_CTL_RGOFFADDR);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_USR_CTL_RGWR(data) do {\
|
||||
iowrite32(data, (void *)SDCC_USR_CTL_RGOFFADDR);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_USR_CTL_BYPASS_MODE_UDFRD(data) do {\
|
||||
SDCC_USR_CTL_RGRD(data);\
|
||||
data = ((data >> 30) & SDCC_USR_CTL_BYPASS_MODE_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define SDCC_USR_CTL_BYPASS_MODE_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
SDCC_USR_CTL_RGRD(v);\
|
||||
v = ((v & SDCC_USR_CTL_BYPASS_MODE_WR_MASK) | ((data & SDCC_USR_CTL_BYPASS_MODE_MASK) << 30));\
|
||||
SDCC_USR_CTL_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
/* Read Write register operations for
|
||||
* EMAC_RGMII_IO_MACRO_CONFIG_2
|
||||
*/
|
||||
|
||||
#define RGMII_IO_MACRO_CONFIG_2_RGOFFADDR_OFFSET (0x0000001C)
|
||||
#define RGMII_IO_MACRO_CONFIG_2_RGOFFADDR ((volatile ULONG *)(RGMII_IO_BASE_ADDRESS + RGMII_IO_MACRO_CONFIG_2_RGOFFADDR_OFFSET))
|
||||
|
||||
#define RGMII_IO_MACRO_CONFIG_2_RGWR(data) do {\
|
||||
iowrite32(data, (void *)RGMII_IO_MACRO_CONFIG_2_RGOFFADDR);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_IO_MACRO_CONFIG_2_RGRD(data) do {\
|
||||
(data) = ioread32((void *)RGMII_IO_MACRO_CONFIG_2_RGOFFADDR);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_DATA_DIVIDE_CLK_SEL_MASK (ULONG)(0x1)
|
||||
|
||||
#define RGMII_DATA_DIVIDE_CLK_SEL_WR_MASK (ULONG)(0xffffffbf)
|
||||
|
||||
#define RGMII_CONFIG_2_DATA_DIVIDE_CLK_SEL_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
RGMII_IO_MACRO_CONFIG_2_RGRD(v);\
|
||||
v = ((v & RGMII_DATA_DIVIDE_CLK_SEL_WR_MASK) | ((data & RGMII_DATA_DIVIDE_CLK_SEL_MASK) << 6));\
|
||||
RGMII_IO_MACRO_CONFIG_2_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_CONFIG_2_DATA_DIVIDE_CLK_SEL_UDFRD(data) do {\
|
||||
RGMII_IO_MACRO_CONFIG_2_RGRD(data);\
|
||||
data = ((data >> 6) & RGMII_DATA_DIVIDE_CLK_SEL_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_TX_CLK_PHASE_SHIFT_EN_MASK (ULONG)(0x1)
|
||||
|
||||
#define RGMII_TX_CLK_PHASE_SHIFT_EN_WR_MASK (ULONG)(0xffffffdf)
|
||||
|
||||
#define RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
RGMII_IO_MACRO_CONFIG_2_RGRD(v);\
|
||||
v = ((v & RGMII_TX_CLK_PHASE_SHIFT_EN_WR_MASK) | ((data & RGMII_TX_CLK_PHASE_SHIFT_EN_MASK) << 5));\
|
||||
RGMII_IO_MACRO_CONFIG_2_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_CONFIG_2_TX_CLK_PHASE_SHIFT_EN_UDFRD(data) do {\
|
||||
RGMII_IO_MACRO_CONFIG_2_RGRD(data);\
|
||||
data = ((data >> 5) & RGMII_TX_CLK_PHASE_SHIFT_EN_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_TX_TO_RX_LOOPBACK_EN_MASK (ULONG)(0x1)
|
||||
|
||||
#define RGMII_TX_TO_RX_LOOPBACK_EN_WR_MASK (ULONG)(0xffffdfff)
|
||||
|
||||
#define RGMII_CONFIG_2_TX_TO_RX_LOOPBACK_EN_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
RGMII_IO_MACRO_CONFIG_2_RGRD(v);\
|
||||
v = ((v & RGMII_TX_TO_RX_LOOPBACK_EN_WR_MASK) | ((data & RGMII_TX_TO_RX_LOOPBACK_EN_MASK) << 13));\
|
||||
RGMII_IO_MACRO_CONFIG_2_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_CONFIG_2_TX_TO_RX_LOOPBACK_EN_UDFRD(data) do {\
|
||||
RGMII_IO_MACRO_CONFIG_2_RGRD(data);\
|
||||
data = ((data >> 13) & RGMII_TX_TO_RX_LOOPBACK_EN_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_RX_PROG_SWAP_MASK (ULONG)(0x1)
|
||||
|
||||
#define RGMII_RX_PROG_SWAP_WR_MASK (ULONG)(0xffffff7f)
|
||||
|
||||
#define RGMII_CONFIG_2_RX_PROG_SWAP_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
RGMII_IO_MACRO_CONFIG_2_RGRD(v);\
|
||||
v = ((v & RGMII_RX_PROG_SWAP_WR_MASK) | ((data & RGMII_RX_PROG_SWAP_MASK) << 7));\
|
||||
RGMII_IO_MACRO_CONFIG_2_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_CONFIG_2_RX_PROG_SWAP_UDFRD(data) do {\
|
||||
RGMII_IO_MACRO_CONFIG_2_RGRD(data);\
|
||||
data = ((data >> 7) & RGMII_RX_PROG_SWAP_MASK);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_CLK_DIVIDE_SEL_MASK (ULONG)(0x1)
|
||||
|
||||
#define RGMII_CLK_DIVIDE_SEL_WR_MASK (ULONG)(0xffffefff)
|
||||
|
||||
#define RGMII_CONFIG_2_CLK_DIVIDE_SEL_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
RGMII_IO_MACRO_CONFIG_2_RGRD(v);\
|
||||
v = ((v & RGMII_CLK_DIVIDE_SEL_WR_MASK) | ((data & RGMII_CLK_DIVIDE_SEL_MASK) << 12));\
|
||||
RGMII_IO_MACRO_CONFIG_2_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_CONFIG_2_CLK_DIVIDE_SEL_UDFRD(data) do {\
|
||||
RGMII_IO_MACRO_CONFIG_2_RGRD(data);\
|
||||
data = ((data >> 7) & RGMII_CLK_DIVIDE_SEL_MASK);\
|
||||
} while (0)
|
||||
|
||||
|
||||
#define RGMII_RERVED_CONFIG_16_EN_MASK (ULONG)(0xffff)
|
||||
|
||||
#define RGMII_RERVED_CONFIG_16_EN_WR_MASK (ULONG)(0x0000ffff)
|
||||
|
||||
#define RGMII_CONFIG_2_RERVED_CONFIG_16_EN_UDFWR(data) do {\
|
||||
ULONG v;\
|
||||
RGMII_IO_MACRO_CONFIG_2_RGRD(v);\
|
||||
v = ((v & RGMII_RERVED_CONFIG_16_EN_WR_MASK) | ((data & RGMII_RERVED_CONFIG_16_EN_MASK) << 16));\
|
||||
RGMII_IO_MACRO_CONFIG_2_RGWR(v);\
|
||||
} while (0)
|
||||
|
||||
#define RGMII_CONFIG_2_RERVED_CONFIG_16_EN_UDFRD(data) do {\
|
||||
RGMII_IO_MACRO_CONFIG_2_RGRD(data);\
|
||||
data = ((data >> 16) & RGMII_RERVED_CONFIG_16_EN_MASK);\
|
||||
} while (0)
|
||||
|
||||
/* EMAC_RGMII_IO_MACRO_DEBUG_1 */
|
||||
#define RGMII_IO_MACRO_DEBUG_1_RGOFFADDR ((volatile ULONG *)(RGMII_IO_BASE_ADDRESS + 0x00000020))
|
||||
|
||||
#define RGMII_IO_MACRO_DEBUG_1_RGRD(data) do {\
|
||||
(data) = ioread32((void *)RGMII_IO_MACRO_DEBUG_1_RGOFFADDR);\
|
||||
} while (0)
|
||||
|
||||
/* EMAC_SYSTEM_LOW_POWER_DEBUG */
|
||||
#define EMAC_SYSTEM_LOW_POWER_DEBUG_RGOFFADDR ((volatile ULONG *)(RGMII_IO_BASE_ADDRESS + 0x00000028))
|
||||
|
||||
#define EMAC_SYSTEM_LOW_POWER_DEBUG_RGRD(data) do {\
|
||||
(data) = ioread32((void *)EMAC_SYSTEM_LOW_POWER_DEBUG_RGOFFADDR);\
|
||||
} while (0)
|
||||
|
||||
void dump_rgmii_io_macro_registers(void);
|
||||
|
||||
#endif
|
13
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/Kbuild
Normal file
13
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/Kbuild
Normal file
@@ -0,0 +1,13 @@
|
||||
# Kernel module instructions go here.
|
||||
obj-m := emac_dwc_eqos.o
|
||||
emac_dwc_eqos-y := DWC_ETH_QOS_dev.o DWC_ETH_QOS_drv.o DWC_ETH_QOS_desc.o DWC_ETH_QOS_ethtool.o DWC_ETH_QOS_platform.o DWC_ETH_QOS_mdio.o DWC_ETH_QOS_eee.o DWC_ETH_QOS_rgmii_io_macro.o DWC_ETH_QOS_poll_support.o
|
||||
|
||||
ifeq ($(CONFIG_PTP_1588_CLOCK), y)
|
||||
EXTRA_CFLAGS+=-DCONFIG_PTPSUPPORT_OBJ
|
||||
emac_dwc_eqos-y += DWC_ETH_QOS_ptp.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_IPA_OFFLOAD), 1)
|
||||
EXTRA_CFLAGS+=-DDWC_ETH_QOS_ENABLE_IPA
|
||||
emac_dwc_eqos-y += DWC_ETH_QOS_ipa.o
|
||||
endif
|
11
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/Kconfig
Normal file
11
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/Kconfig
Normal file
@@ -0,0 +1,11 @@
|
||||
#
|
||||
# Synopsis EMAC device configuration
|
||||
#
|
||||
|
||||
config EMAC_DWC_EQOS
|
||||
tristate "Qualcomm Technologies Inc. EMAC support"
|
||||
depends on (ARM || ARM64)
|
||||
default y
|
||||
help
|
||||
This driver supports the Synopsis EMAC Gigabit
|
||||
Ethernet controller.
|
@@ -0,0 +1,6 @@
|
||||
config EMAC_APP
|
||||
bool "EMAC app support"
|
||||
depends on EMAC_DWC_EQOS
|
||||
default y
|
||||
help
|
||||
Say y here if you want to run Neutrino ethernet open function
|
52
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/Makefile
Normal file
52
qcom/opensource/data-kernel/drivers/emac-dwc-eqos/Makefile
Normal file
@@ -0,0 +1,52 @@
|
||||
export PTPSUPPORT CONFIG_PTPSUPPORT_OBJ DWC_ETH_QOS_CONFIG_PTP
|
||||
|
||||
#default values
|
||||
PTPSUPPORT=y #ptp is enabled
|
||||
|
||||
ifeq ($(RELEASE_PACKAGE),1)
|
||||
EXTRA_CFLAGS+=-DRELEASE_PACKAGE
|
||||
endif
|
||||
LBITS ?= $(shell getconf LONG_BIT)
|
||||
ifeq ($(LBITS),64)
|
||||
CCFLAGS += -m64
|
||||
EXTRA_CFLAGS+=-DSYSTEM_IS_64
|
||||
else
|
||||
CCFLAGS += -m32
|
||||
endif
|
||||
|
||||
ifeq "$(PTPSUPPORT)" "y"
|
||||
CONFIG_PTPSUPPORT_OBJ=y
|
||||
DWC_ETH_QOS_CONFIG_PTP=-DPTPSUPPORT
|
||||
EXTRA_CFLAGS+=-DCONFIG_PTPSUPPORT_OBJ
|
||||
else
|
||||
CONFIG_PTPSUPPORT_OBJ=y
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_IPA_OFFLOAD), 1)
|
||||
CDEFINES+=-DDWC_ETH_QOS_ENABLE_IPA
|
||||
emac_dwc_eqos-y += DWC_ETH_QOS_ipa.o
|
||||
endif
|
||||
|
||||
obj-m := emac_dwc_eqos.o
|
||||
|
||||
emac_dwc_eqos-y += DWC_ETH_QOS_dev.o \
|
||||
DWC_ETH_QOS_drv.o \
|
||||
DWC_ETH_QOS_desc.o \
|
||||
DWC_ETH_QOS_ethtool.o \
|
||||
DWC_ETH_QOS_platform.o \
|
||||
DWC_ETH_QOS_mdio.o \
|
||||
DWC_ETH_QOS_eee.o \
|
||||
DWC_ETH_QOS_rgmii_io_macro.o
|
||||
|
||||
emac_dwc_eqos-$(CONFIG_PTPSUPPORT_OBJ) += DWC_ETH_QOS_ptp.o
|
||||
|
||||
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
|
||||
|
||||
all:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS)
|
||||
|
||||
modules_install:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules_install
|
||||
|
||||
clean:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean
|
@@ -0,0 +1,49 @@
|
||||
export PTPSUPPORT CONFIG_PTPSUPPORT_OBJ DWC_ETH_QOS_CONFIG_PTP
|
||||
|
||||
#default values
|
||||
PTPSUPPORT=y #ptp is enabled
|
||||
|
||||
ifeq ($(RELEASE_PACKAGE),1)
|
||||
EXTRA_CFLAGS+=-DRELEASE_PACKAGE
|
||||
endif
|
||||
LBITS := $(shell getconf LONG_BIT)
|
||||
ifeq ($(LBITS),64)
|
||||
CCFLAGS += -m64
|
||||
EXTRA_CFLAGS+=-DSYSTEM_IS_64
|
||||
else
|
||||
CCFLAGS += -m32
|
||||
endif
|
||||
|
||||
ifeq "$(PTPSUPPORT)" "y"
|
||||
CONFIG_PTPSUPPORT_OBJ=y
|
||||
DWC_ETH_QOS_CONFIG_PTP=-DPTPSUPPORT
|
||||
EXTRA_CFLAGS+=-DCONFIG_PTPSUPPORT_OBJ
|
||||
else
|
||||
CONFIG_PTPSUPPORT_OBJ=y
|
||||
endif
|
||||
|
||||
emacdir = $(prefix)/emac
|
||||
emac_CFLAGS = -Werror
|
||||
|
||||
|
||||
KERNEL_FLAGS ?= ARCH=arm
|
||||
|
||||
module = emac_dwc_eqos.ko
|
||||
kmake = $(MAKE) $(KERNEL_FLAGS) -C $(KERNEL_DIR) M=$(CURDIR)
|
||||
|
||||
$(module):
|
||||
$(kmake) modules
|
||||
|
||||
all-local: $(module)
|
||||
|
||||
install-exec-local: $(module)
|
||||
$(kmake) INSTALL_MOD_PATH=$(DESTDIR)$(prefix)/modules modules_install
|
||||
|
||||
# "make distclean" will always run clean-local in this directory,
|
||||
# regardless of the KERNELMODULES conditional. Therefore, ensure
|
||||
# KERNEL_DIR exists before running clean. Further, don't fail even
|
||||
# if there is a problem.
|
||||
clean-local:
|
||||
-test ! -d "$(KERNEL_DIR)" || $(kmake) clean
|
||||
|
||||
|
@@ -0,0 +1,21 @@
|
||||
obj-$(CONFIG_EMAC_DWC_EQOS) += DWC_ETH_QOS_dev.o \
|
||||
DWC_ETH_QOS_drv.o \
|
||||
DWC_ETH_QOS_desc.o \
|
||||
DWC_ETH_QOS_ethtool.o \
|
||||
DWC_ETH_QOS_mdio.o \
|
||||
DWC_ETH_QOS_eee.o \
|
||||
DWC_ETH_QOS_platform.o \
|
||||
DWC_ETH_QOS_rgmii_io_macro.o \
|
||||
DWC_ETH_QOS_poll_support.o
|
||||
|
||||
ifeq ($(CONFIG_PTP_1588_CLOCK), y)
|
||||
EXTRA_CFLAGS+=-DCONFIG_PTPSUPPORT_OBJ
|
||||
obj-$(CONFIG_EMAC_DWC_EQOS) += DWC_ETH_QOS_ptp.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_IPA_OFFLOAD), y)
|
||||
KBUILD_CFLAGS += -DDWC_ETH_QOS_ENABLE_IPA
|
||||
obj-$(CONFIG_EMAC_DWC_EQOS) += DWC_ETH_QOS_ipa.o
|
||||
endif
|
||||
|
||||
KBUILD_CFLAGS += -DDWC_ETH_QOS_BUILTIN
|
@@ -0,0 +1,4 @@
|
||||
#
|
||||
# Makefile for the DWC_ETH_QOS app kernel module
|
||||
#
|
||||
obj-$(CONFIG_EMAC_APP) = DWC_ETH_QOS_app.o
|
@@ -0,0 +1,22 @@
|
||||
#!/vendor/bin/sh
|
||||
#Copyright (c) 2019, 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.
|
||||
#
|
||||
#
|
||||
echo 12582912 > /proc/sys/net/core/wmem_max;
|
||||
echo 12582912 > /proc/sys/net/core/rmem_max;
|
||||
echo 10240 87380 12582912 > /proc/sys/net/ipv4/tcp_rmem;
|
||||
echo 10240 87380 12582912 > /proc/sys/net/ipv4/tcp_wmem;
|
||||
echo 12582912 > /proc/sys/net/ipv4/udp_rmem_min;
|
||||
echo 12582912 > /proc/sys/net/ipv4/udp_wmem_min;
|
||||
echo 1 > /proc/sys/net/ipv4/tcp_window_scaling;
|
||||
echo 18 > /sys/class/net/eth0/queues/rx-0/rps_cpus;
|
||||
|
19
qcom/opensource/data-kernel/drivers/smem-mailbox/Android.mk
Normal file
19
qcom/opensource/data-kernel/drivers/smem-mailbox/Android.mk
Normal file
@@ -0,0 +1,19 @@
|
||||
# Android makefile for SMEM kernel modules
|
||||
ifeq ($(call is-board-platform-in-list,sun), true)
|
||||
ifneq (,$(filter arm aarch64 arm64, $(TARGET_ARCH)))
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
LOCAL_MODULE_DDK_BUILD := true
|
||||
|
||||
DLKM_DIR := device/qcom/common/dlkm
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := $(LOCAL_PATH)/smem-mailbox.c
|
||||
LOCAL_EXPORT_KO_INCLUDE_DIRS := $(LOCAL_PATH)/include
|
||||
LOCAL_MODULE := smem-mailbox.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||
|
||||
endif
|
||||
endif
|
10
qcom/opensource/data-kernel/drivers/smem-mailbox/BUILD.bazel
Normal file
10
qcom/opensource/data-kernel/drivers/smem-mailbox/BUILD.bazel
Normal file
@@ -0,0 +1,10 @@
|
||||
load(":define_modules.bzl", "define_modules")
|
||||
|
||||
define_modules("sun", "consolidate")
|
||||
define_modules("sun", "perf")
|
||||
|
||||
package(
|
||||
default_visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
14
qcom/opensource/data-kernel/drivers/smem-mailbox/Makefile
Normal file
14
qcom/opensource/data-kernel/drivers/smem-mailbox/Makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
KBUILD_OPTIONS += SMEM_MAILBOX_ROOT=$(KERNEL_SRC)/$(M)
|
||||
|
||||
all:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(M) modules $(KBUILD_OPTIONS)
|
||||
|
||||
modules_install:
|
||||
$(MAKE) M=$(M) -C $(KERNEL_SRC) modules_install
|
||||
|
||||
%:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(M) $@ $(KBUILD_OPTIONS)
|
||||
|
||||
clean:
|
||||
rm -f *.o *.ko *.mod.c *.mod.o *~ .*.cmd Module.symvers
|
||||
rm -rf .tmp_versions
|
@@ -0,0 +1,32 @@
|
||||
load("//build/kernel/kleaf:kernel.bzl", "ddk_module")
|
||||
load("//build/bazel_common_rules/dist:dist.bzl", "copy_to_dist_dir")
|
||||
|
||||
def define_modules(target, variant):
|
||||
kernel_build_variant = "{}_{}".format(target, variant)
|
||||
|
||||
ddk_module(
|
||||
name = "{}_smem_mailbox".format(kernel_build_variant),
|
||||
kernel_build = "//msm-kernel:{}".format(kernel_build_variant),
|
||||
deps = ["//msm-kernel:all_headers"],
|
||||
srcs = [
|
||||
"smem-mailbox.c"
|
||||
],
|
||||
hdrs = [
|
||||
"include/smem-mailbox.h"
|
||||
],
|
||||
includes = [
|
||||
"include"
|
||||
],
|
||||
out = "smem-mailbox.ko",
|
||||
visibility = ["//visibility:public"]
|
||||
)
|
||||
|
||||
copy_to_dist_dir(
|
||||
name = "{}_smem_mailbox_dist".format(kernel_build_variant),
|
||||
data = [":{}_smem_mailbox".format(kernel_build_variant)],
|
||||
dist_dir = "out/target/product/{}/dlkm/lib/modules/".format(kernel_build_variant),
|
||||
flat = True,
|
||||
wipe_dist_dir = False,
|
||||
allow_duplicate_filenames = False,
|
||||
mode_overrides = {"**/*": "644"},
|
||||
)
|
@@ -0,0 +1,21 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __SMEM_MAILBOX_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Flags for Write API */
|
||||
#define FLAG_URGENT 1
|
||||
|
||||
typedef void (*smem_mailbox_urgent_cb)(u16 pending_bytes);
|
||||
|
||||
/* API's Exposed to External Modules */
|
||||
int smem_mailbox_start(int id, smem_mailbox_urgent_cb urgent_cb);
|
||||
int smem_mailbox_stop(int id);
|
||||
int smem_mailbox_read(int id, u8 **data, u16 *data_length, unsigned long long *xo_time);
|
||||
int smem_mailbox_write(int id, int flags, __u8 *data, u16 data_length);
|
||||
|
||||
#endif
|
2
qcom/opensource/data-kernel/drivers/smem-mailbox/kbuild
Normal file
2
qcom/opensource/data-kernel/drivers/smem-mailbox/kbuild
Normal file
@@ -0,0 +1,2 @@
|
||||
LINUXINCLUDE += -I$(SMEM_MAILBOX_ROOT)/include
|
||||
obj-m := smem-mailbox.o
|
577
qcom/opensource/data-kernel/drivers/smem-mailbox/smem-mailbox.c
Normal file
577
qcom/opensource/data-kernel/drivers/smem-mailbox/smem-mailbox.c
Normal file
@@ -0,0 +1,577 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/soc/qcom/smem.h>
|
||||
#include <linux/soc/qcom/smem_state.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/version.h>
|
||||
#include <net/genetlink.h>
|
||||
|
||||
#include "smem-mailbox.h"
|
||||
|
||||
#define SMEM_VERSION 0x00000001 // v0.1
|
||||
#define START_COOKIE 0xbeefcafe
|
||||
#define END_COOKIE 0x0fed0fed
|
||||
|
||||
#define DEVICE_NAME "smem_mailbox"
|
||||
|
||||
#define HEAD_PTR_SIZE 4
|
||||
#define TAIL_PTR_SIZE 4
|
||||
#define BUF_IO_PTR_SIZE HEAD_PTR_SIZE + TAIL_PTR_SIZE
|
||||
|
||||
#define GET_READ_HEAD(smem, entry) *(u32 *)(smem + entry->start_loc)
|
||||
#define GET_READ_TAIL(smem, entry) *(u32 *)(smem + entry->start_loc + HEAD_PTR_SIZE)
|
||||
#define GET_READ_BUF(smem, entry) smem + entry->start_loc + BUF_IO_PTR_SIZE
|
||||
|
||||
#define GET_WRITE_HEAD(smem, entry) \
|
||||
*(u32 *)(smem + entry->start_loc + BUF_IO_PTR_SIZE + entry->read_size)
|
||||
#define GET_WRITE_TAIL(smem, entry) \
|
||||
*(u32 *)(smem + entry->start_loc + BUF_IO_PTR_SIZE + entry->read_size + HEAD_PTR_SIZE)
|
||||
#define GET_WRITE_BUF(smem, entry) \
|
||||
smem + entry->start_loc + BUF_IO_PTR_SIZE + entry->read_size + BUF_IO_PTR_SIZE
|
||||
|
||||
#define UPDATE_WRITE_HEAD(smem, value) \
|
||||
memcpy_toio(smem + entry->start_loc + BUF_IO_PTR_SIZE + entry->read_size, &value, \
|
||||
sizeof(value));
|
||||
#define UPDATE_READ_TAIL(smem, value) \
|
||||
memcpy_toio(smem + entry->start_loc + HEAD_PTR_SIZE, &value, sizeof(value));
|
||||
|
||||
// This list must match the configured names in the device tree for the smp2p in (IRQ).
|
||||
#define IRQ_NUM_NAMES 4
|
||||
static char *IRQ_NAMES[] = {"smem-mailbox-smp2p-1-in", "smem-mailbox-smp2p-2-in",
|
||||
"smem-mailbox-smp2p-3-in", "smem-mailbox-smp2p-4-in"};
|
||||
|
||||
#define SMEM_DESCRIPTOR 655
|
||||
/* SMEM host id representing the modem. */
|
||||
#define QCOM_SMEM_HOST_MODEM 1
|
||||
|
||||
struct smem_client_channel {
|
||||
struct list_head list;
|
||||
u32 id;
|
||||
u32 start_loc;
|
||||
u32 read_size;
|
||||
u32 write_size;
|
||||
bool client_connected;
|
||||
char irq_name[24];
|
||||
smem_mailbox_urgent_cb urgent_cb;
|
||||
};
|
||||
static LIST_HEAD(smem_client_channel_list_head);
|
||||
|
||||
struct mailbox_smp2p {
|
||||
struct qcom_smem_state *smem_state;
|
||||
u32 smem_bit;
|
||||
};
|
||||
struct mailbox_smp2p *mailbox;
|
||||
struct device *dev;
|
||||
|
||||
struct client_info {
|
||||
u32 id;
|
||||
u32 start_loc;
|
||||
u32 read_size;
|
||||
u32 write_size;
|
||||
};
|
||||
|
||||
struct smem_info {
|
||||
u32 start_cookie;
|
||||
u32 version;
|
||||
u32 num_of_clients;
|
||||
struct client_info clients[4];
|
||||
u32 end_cookie;
|
||||
};
|
||||
bool info_validated;
|
||||
|
||||
#define TLV_TYPE_TIME 0
|
||||
#define TLV_TYPE_DATA 1
|
||||
#define TLV_TYPE_MODULE_MAX 32767
|
||||
// TLV range of 32,768 - 65,535 is reserved for client use.
|
||||
|
||||
struct tlv {
|
||||
u16 type;
|
||||
u16 length;
|
||||
};
|
||||
|
||||
int free_bytes(u32 head, u32 tail, u32 max) {
|
||||
int free_bytes = 0;
|
||||
|
||||
if (head >= tail) {
|
||||
free_bytes = max - head + tail;
|
||||
} else {
|
||||
free_bytes = tail - head;
|
||||
}
|
||||
return free_bytes;
|
||||
}
|
||||
|
||||
static irqreturn_t smem_read_ready(int irq, void *channel)
|
||||
{
|
||||
int id = 0;
|
||||
int pending_bytes = 0;
|
||||
void *smem;
|
||||
size_t size;
|
||||
struct smem_client_channel *entry = NULL;
|
||||
|
||||
id = ((struct smem_client_channel *)channel)->id;
|
||||
|
||||
list_for_each_entry(entry, &smem_client_channel_list_head, list) {
|
||||
if (entry->id == id) break;
|
||||
}
|
||||
|
||||
if (entry == NULL || entry->id != id) {
|
||||
pr_err(KERN_ALERT "smem: ID does not match any smem sub allocation %d\n", id);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (!entry->client_connected) {
|
||||
pr_err(KERN_ALERT "smem: there is no connected client for ID %d, ignore\n", id);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
smem = qcom_smem_get(QCOM_SMEM_HOST_MODEM, SMEM_DESCRIPTOR, &size);
|
||||
if (IS_ERR(smem)) {
|
||||
pr_err("%s: smem qcom_smem_get fail.\n", __func__);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
pending_bytes = entry->read_size -
|
||||
free_bytes(GET_READ_HEAD(smem, entry), GET_READ_TAIL(smem, entry), entry->read_size);
|
||||
entry->urgent_cb(pending_bytes);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static bool read_client_info_map(void) {
|
||||
int ret = 0;
|
||||
int irq;
|
||||
size_t info_size;
|
||||
struct smem_info smem_info;
|
||||
struct device_node *node = dev->of_node;
|
||||
struct smem_client_channel *entry = NULL;
|
||||
|
||||
void *smem = qcom_smem_get(QCOM_SMEM_HOST_MODEM, SMEM_DESCRIPTOR, &info_size);
|
||||
if (IS_ERR(smem)) {
|
||||
pr_err("%s: smem qcom_smem_get fail.\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy_fromio(&smem_info, smem, sizeof(struct smem_info));
|
||||
info_validated = false;
|
||||
|
||||
if (smem_info.start_cookie != START_COOKIE) {
|
||||
pr_err(KERN_ALERT "smem: start cookie does not match %d\n", smem_info.start_cookie);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (smem_info.version != SMEM_VERSION) {
|
||||
pr_err(KERN_ALERT "smem: version does not match %d\n", smem_info.version);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < smem_info.num_of_clients && i < IRQ_NUM_NAMES; i++) {
|
||||
struct client_info client = smem_info.clients[i];
|
||||
u32 id = client.id;
|
||||
u32 start_loc = client.start_loc;
|
||||
u32 read_size = client.read_size;
|
||||
u32 write_size = client.write_size;
|
||||
|
||||
struct smem_client_channel *new_entry;
|
||||
new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
|
||||
new_entry->id = id;
|
||||
new_entry->start_loc = start_loc;
|
||||
new_entry->read_size = read_size;
|
||||
new_entry->write_size = write_size;
|
||||
|
||||
// IRQ name is hardcoded
|
||||
strscpy(new_entry->irq_name, IRQ_NAMES[i], sizeof(new_entry->irq_name));
|
||||
|
||||
INIT_LIST_HEAD(&new_entry->list);
|
||||
list_add_tail(&new_entry->list, &smem_client_channel_list_head);
|
||||
}
|
||||
|
||||
if (smem_info.end_cookie != END_COOKIE) {
|
||||
pr_err(KERN_ALERT "smem: end cookie does not match %d\n", smem_info.end_cookie);
|
||||
return false;
|
||||
}
|
||||
info_validated = true;
|
||||
|
||||
list_for_each_entry(entry, &smem_client_channel_list_head, list) {
|
||||
irq = ret = of_irq_get_byname(node, entry->irq_name);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: smem platform_get_irq_byname fail. %d %s\n", __func__, ret,
|
||||
entry->irq_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(dev, irq, NULL, smem_read_ready,
|
||||
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, entry->irq_name,
|
||||
entry);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: smem request_threaded_irq fail. %d\n", __func__, ret);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int smem_probe(struct platform_device *pdev) {
|
||||
dev = &pdev->dev;
|
||||
|
||||
if (mailbox == NULL) {
|
||||
mailbox = kzalloc(sizeof(struct mailbox_smp2p), GFP_KERNEL);
|
||||
}
|
||||
|
||||
mailbox->smem_state = qcom_smem_state_get(dev, "smem-mailbox-smp2p-out", &mailbox->smem_bit);
|
||||
if (IS_ERR(mailbox->smem_state)) {
|
||||
pr_err("%s: smem fail to get smp2p clk resp bit %ld\n", __func__,
|
||||
PTR_ERR(mailbox->smem_state));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Attempt to read client map. This should fail at boot since modem is not up. Retry at first
|
||||
// client connection.
|
||||
read_client_info_map();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smem_remove(struct platform_device *pdev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int smem_mailbox_start(int id, smem_mailbox_urgent_cb urgent_cb) {
|
||||
struct smem_client_channel *entry = NULL;
|
||||
|
||||
if (!info_validated && !read_client_info_map()) {
|
||||
pr_err(KERN_ALERT "smem: client info map has not been setup by modem.\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
list_for_each_entry(entry, &smem_client_channel_list_head, list) {
|
||||
if (entry->id == id) break;
|
||||
}
|
||||
|
||||
if (entry == NULL || entry->id != id) {
|
||||
pr_err(KERN_ALERT "smem: ID does not match any smem sub allocation %d\n", id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (entry->client_connected) {
|
||||
pr_err(KERN_ALERT "smem: there is already a client connected to this ID %d\n", id);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
entry->urgent_cb = urgent_cb;
|
||||
entry->client_connected = true;
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(smem_mailbox_start);
|
||||
|
||||
int smem_mailbox_stop(int id) {
|
||||
void *smem;
|
||||
size_t size;
|
||||
u32 read_head_index;
|
||||
u32 read_tail_index;
|
||||
u32 write_head_index;
|
||||
u32 write_tail_index;
|
||||
struct smem_client_channel *entry = NULL;
|
||||
|
||||
list_for_each_entry(entry, &smem_client_channel_list_head, list) {
|
||||
if (entry->id == id) break;
|
||||
}
|
||||
|
||||
if (entry == NULL || entry->id != id) {
|
||||
pr_err(KERN_ALERT "smem: ID does not match any smem sub allocation %d\n", id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!entry->client_connected) {
|
||||
pr_err(KERN_ALERT "smem: client never started this ID %d\n", id);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
smem = qcom_smem_get(QCOM_SMEM_HOST_MODEM, SMEM_DESCRIPTOR, &size);
|
||||
if (IS_ERR(smem)) {
|
||||
pr_err("%s: smem qcom_smem_get fail.\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
read_head_index = GET_READ_HEAD(smem, entry);
|
||||
read_tail_index = GET_READ_TAIL(smem, entry);
|
||||
if (read_head_index != read_tail_index) {
|
||||
pr_err("%s: smem read_head_index %d does not equal read_tail_index %d.\n", __func__,
|
||||
read_head_index, read_tail_index);
|
||||
UPDATE_READ_TAIL(smem, read_head_index);
|
||||
}
|
||||
|
||||
write_head_index = GET_WRITE_HEAD(smem, entry);
|
||||
write_tail_index = GET_WRITE_TAIL(smem, entry);
|
||||
if (write_head_index != write_tail_index) {
|
||||
pr_err("%s: smem write_head_index %d does not equal write_tail_index %d.\n", __func__,
|
||||
write_head_index, write_tail_index);
|
||||
UPDATE_WRITE_HEAD(smem, write_tail_index);
|
||||
}
|
||||
|
||||
entry->client_connected = false;
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(smem_mailbox_stop);
|
||||
|
||||
bool read_item(struct smem_client_channel *entry, void *item, u16 item_size) {
|
||||
int offset;
|
||||
void *smem;
|
||||
void *read_buf;
|
||||
size_t size;
|
||||
u32 head_index;
|
||||
u32 tail_index;
|
||||
|
||||
smem = qcom_smem_get(QCOM_SMEM_HOST_MODEM, SMEM_DESCRIPTOR, &size);
|
||||
if (IS_ERR(smem)) {
|
||||
pr_err("%s: smem qcom_smem_get fail.\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
head_index = GET_READ_HEAD(smem, entry);
|
||||
tail_index = GET_READ_TAIL(smem, entry);
|
||||
offset = tail_index + item_size - entry->read_size;
|
||||
read_buf = GET_READ_BUF(smem, entry);
|
||||
|
||||
if (offset > 0) {
|
||||
if (offset > head_index) {
|
||||
pr_err("%s: smem item size is greater than remaining buffer. head %d\n", __func__,
|
||||
head_index);
|
||||
tail_index = head_index;
|
||||
UPDATE_READ_TAIL(smem, tail_index);
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy_fromio(item, read_buf + tail_index, item_size - offset);
|
||||
memcpy_fromio(item + (item_size - offset), read_buf, offset);
|
||||
UPDATE_READ_TAIL(smem, offset);
|
||||
} else {
|
||||
if ((tail_index + item_size) > head_index) {
|
||||
pr_err("%s: smem item size is greater than remaining buffer. head %d\n", __func__,
|
||||
head_index);
|
||||
tail_index = head_index;
|
||||
UPDATE_READ_TAIL(smem, tail_index);
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy_fromio(item, read_buf + tail_index, item_size);
|
||||
tail_index = tail_index + item_size;
|
||||
UPDATE_READ_TAIL(smem, tail_index);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int smem_mailbox_read(int id, u8 **data, u16 *data_length, unsigned long long *xo_time) {
|
||||
bool ret;
|
||||
size_t size;
|
||||
void *smem;
|
||||
struct smem_client_channel *entry = NULL;
|
||||
u32 head_index;
|
||||
u32 tail_index;
|
||||
int word_offset;
|
||||
|
||||
list_for_each_entry(entry, &smem_client_channel_list_head, list) {
|
||||
if (entry->id == id) break;
|
||||
}
|
||||
|
||||
if (entry == NULL || entry->id != id) {
|
||||
pr_err(KERN_ALERT "smem: incorrect ID %d\n", id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!entry->client_connected) {
|
||||
pr_err(KERN_ALERT "smem: client never started this ID %d\n", id);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
smem = qcom_smem_get(QCOM_SMEM_HOST_MODEM, SMEM_DESCRIPTOR, &size);
|
||||
if (IS_ERR(smem)) {
|
||||
pr_err("%s: smem qcom_smem_get fail.\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
head_index = GET_READ_HEAD(smem, entry);
|
||||
tail_index = GET_READ_TAIL(smem, entry);
|
||||
|
||||
if (head_index == tail_index) {
|
||||
pr_err("%s: smem qcom_smem_get nothing to read for this client %d. %d %d \n", __func__, id,
|
||||
head_index, tail_index);
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
struct tlv temp_tlv;
|
||||
ret = read_item(entry, &temp_tlv, sizeof(struct tlv));
|
||||
if (!ret) goto exit_loop;
|
||||
|
||||
switch (temp_tlv.type) {
|
||||
case TLV_TYPE_TIME:
|
||||
ret = read_item(entry, xo_time, sizeof(unsigned long long));
|
||||
if (!ret) goto exit_loop;
|
||||
break;
|
||||
case TLV_TYPE_DATA:
|
||||
*data_length = temp_tlv.length - sizeof(struct tlv);
|
||||
*data = kmalloc(*data_length, GFP_KERNEL);
|
||||
ret = read_item(entry, *data, *data_length);
|
||||
if (!ret) goto exit_loop;
|
||||
|
||||
// Round to next word.
|
||||
word_offset = 4 - (*data_length % 4);
|
||||
if (word_offset > 0) {
|
||||
tail_index = GET_READ_TAIL(smem, entry) + word_offset;
|
||||
UPDATE_READ_TAIL(smem, tail_index);
|
||||
}
|
||||
goto exit_loop;
|
||||
break;
|
||||
default:
|
||||
pr_err(KERN_ALERT "smem: invalid TLV type %d.\n", temp_tlv.type);
|
||||
return -ENOMSG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
exit_loop:
|
||||
return (entry->read_size -
|
||||
free_bytes(GET_READ_HEAD(smem, entry), GET_READ_TAIL(smem, entry), entry->read_size));
|
||||
}
|
||||
EXPORT_SYMBOL(smem_mailbox_read);
|
||||
|
||||
int smem_mailbox_write(int id, int flags, __u8 *data, u16 data_length) {
|
||||
size_t size;
|
||||
void *smem;
|
||||
void *write_buf;
|
||||
u32 head_index;
|
||||
u32 tail_index;
|
||||
u8 *buf;
|
||||
struct tlv time_tlv;
|
||||
struct tlv data_tlv;
|
||||
struct smem_client_channel *entry = NULL;
|
||||
unsigned long long xo_time = 0;
|
||||
int overflow_bytes;
|
||||
int buf_length;
|
||||
int word_offset;
|
||||
|
||||
list_for_each_entry(entry, &smem_client_channel_list_head, list) {
|
||||
if (entry->id == id) break;
|
||||
}
|
||||
|
||||
if (entry == NULL || entry->id != id) {
|
||||
pr_err(KERN_ALERT "smem: incorrect ID %d\n", id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!entry->client_connected) {
|
||||
pr_err(KERN_ALERT "smem: client never started this ID %d\n", id);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
// Size of u32 in subtracted from max size because a full buffer would be the same as an emtpy
|
||||
// buffer.
|
||||
if (data_length > (entry->write_size - sizeof(u32))) {
|
||||
pr_err(KERN_ALERT
|
||||
"smem: data size is larger than write buffer size %d, smem allocation %d\n",
|
||||
data_length, entry->write_size);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
smem = qcom_smem_get(QCOM_SMEM_HOST_MODEM, SMEM_DESCRIPTOR, &size);
|
||||
if (IS_ERR(smem)) {
|
||||
pr_err("%s: smem qcom_smem_get fail.\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
head_index = GET_WRITE_HEAD(smem, entry);
|
||||
tail_index = GET_WRITE_TAIL(smem, entry);
|
||||
buf_length = sizeof(struct tlv) + sizeof(xo_time) + sizeof(struct tlv) + data_length;
|
||||
|
||||
// Not enough space in circular buffer, exit.
|
||||
// Subtract u32 from max size so a full buffer does not have head == tail.
|
||||
if (head_index > tail_index) {
|
||||
if ((tail_index + (entry->write_size - head_index)) < (buf_length - sizeof(u32))) {
|
||||
pr_err("%s: smem qcom_smem_get fail, not enough room in write buffer. %d %d\n",
|
||||
__func__, (tail_index - head_index), buf_length);
|
||||
return -ENOSPC;
|
||||
}
|
||||
} else if (head_index != tail_index) {
|
||||
if ((tail_index - head_index) < (buf_length - sizeof(u32))) {
|
||||
pr_err("%s: smem qcom_smem_get2 fail, not enough room in write buffer. %d %d\n",
|
||||
__func__, (tail_index - head_index), buf_length);
|
||||
return -ENOSPC;
|
||||
}
|
||||
}
|
||||
|
||||
buf = kmalloc(buf_length, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
pr_err("%s: smem kmalloc fail.\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
xo_time = arch_timer_read_cntvct_el0();
|
||||
time_tlv.type = TLV_TYPE_TIME;
|
||||
time_tlv.length = sizeof(xo_time) + sizeof(struct tlv);
|
||||
memcpy(buf, &time_tlv, sizeof(time_tlv));
|
||||
memcpy(buf + sizeof(time_tlv), &xo_time, sizeof(xo_time));
|
||||
|
||||
data_tlv.type = TLV_TYPE_DATA;
|
||||
data_tlv.length = data_length + sizeof(struct tlv);
|
||||
memcpy(buf + sizeof(time_tlv) + sizeof(xo_time), &data_tlv, sizeof(data_tlv));
|
||||
memcpy(buf + sizeof(time_tlv) + sizeof(xo_time) + sizeof(data_tlv), data, data_length);
|
||||
|
||||
// Read/Write must always be word aligned for modem.
|
||||
word_offset = (~4 & (4 - (buf_length % 4)));
|
||||
write_buf = GET_WRITE_BUF(smem, entry);
|
||||
|
||||
overflow_bytes = head_index + buf_length - entry->write_size;
|
||||
if (overflow_bytes < 0) {
|
||||
memcpy_toio(write_buf + head_index, buf, buf_length);
|
||||
head_index = head_index + buf_length + word_offset;
|
||||
UPDATE_WRITE_HEAD(smem, head_index);
|
||||
} else {
|
||||
memcpy_toio(write_buf + head_index, buf, buf_length - overflow_bytes);
|
||||
memcpy_toio(write_buf, buf + buf_length - overflow_bytes, overflow_bytes);
|
||||
head_index = overflow_bytes + word_offset;
|
||||
UPDATE_WRITE_HEAD(smem, head_index);
|
||||
}
|
||||
|
||||
if ((flags & FLAG_URGENT) == FLAG_URGENT) {
|
||||
if (mailbox->smem_state) {
|
||||
// FIFO 1 client ID range starts at 16 (0xF).
|
||||
mailbox->smem_bit = mailbox->smem_bit ^ (1 << id);
|
||||
qcom_smem_state_update_bits(mailbox->smem_state, 0xff, mailbox->smem_bit);
|
||||
} else {
|
||||
pr_err("%s: smem smem_state is not setup.\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
return (free_bytes(GET_WRITE_HEAD(smem, entry), GET_WRITE_TAIL(smem, entry), entry->read_size));
|
||||
}
|
||||
EXPORT_SYMBOL(smem_mailbox_write);
|
||||
|
||||
static const struct of_device_id qcm_smem_match[] = {
|
||||
{ .compatible = "qcom,smem_mailbox", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, qcm_smem_match);
|
||||
|
||||
static struct platform_driver qcom_smem_driver = {
|
||||
.probe = smem_probe,
|
||||
.remove = smem_remove,
|
||||
.driver = {
|
||||
.name = DEVICE_NAME,
|
||||
.of_match_table = qcm_smem_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(qcom_smem_driver);
|
||||
|
||||
MODULE_DESCRIPTION("QCOM SMEM Mailbox Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
Reference in New Issue
Block a user